Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3f8824a
Add immutable stable release channel
justin808 Aug 8, 2026
9490dca
Reconcile release workflow with Actions policy
justin808 Aug 12, 2026
fd88e22
Update workflow doctor status fixtures
justin808 Aug 12, 2026
4023611
Harden stable release installation trust
justin808 Aug 25, 2026
45d23cf
Harden stable release provenance verification
justin808 Aug 26, 2026
f6852ba
Cover stable status advisory reconciliation
justin808 Aug 27, 2026
0b3c46d
Fix stable upgrade release inventory
justin808 Aug 28, 2026
8518a53
Reconcile stable release managed files
justin808 Aug 28, 2026
daae98d
Fail stable status for non-executable helpers
justin808 Aug 28, 2026
d1c7152
Detect stable helper mutation during status
justin808 Aug 28, 2026
f08852d
Harden immutable release verification and stable installation
justin808 Sep 2, 2026
2e0df26
Verify exact release candidates and preserve stable installations
justin808 Sep 9, 2026
1fc04a9
Preserve corrupt channel evidence and avoid archive pipe races
justin808 Sep 9, 2026
80064db
Disable background Git maintenance in disposable upgrade fixtures
justin808 Sep 9, 2026
46dd564
Verify installed workflows against the stable release
justin808 Sep 9, 2026
a48151d
Verify stable upgrade availability separately from installed integrity
justin808 Sep 9, 2026
dbb3e1c
Bind stable inventories and verify managed path ancestors
justin808 Sep 9, 2026
9fc8ebc
Authenticate cold release bootstrap before executing candidate code
justin808 Sep 9, 2026
2bfc424
Verify stable installed runtimes and release version on current main
justin808 Sep 9, 2026
1dc3090
Reject incomplete stable skill and license installations
justin808 Sep 9, 2026
948d56c
Integrate verified delivery policy and CI improvements
justin808 Sep 10, 2026
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
205 changes: 205 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
name: Release

on:
workflow_dispatch:
inputs:
release:
description: New annotated release tag (vX.Y.Z)
required: true
type: string
candidate_sha:
description: Full final candidate commit (dispatch from a branch at this exact commit)
required: true
type: string
change_author:
description: GitHub login of the associated merged PR author
required: true
type: string

permissions:
contents: read

concurrency:
group: stable-release
cancel-in-progress: false

jobs:
verify:
name: Full exact release candidate
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout final candidate without write credentials
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
ref: ${{ inputs.candidate_sha }}

- name: Verify final candidate identity and version metadata
env:
CANDIDATE_SHA: ${{ inputs.candidate_sha }}
RELEASE_REF: ${{ inputs.release }}
WORKFLOW_SHA: ${{ github.workflow_sha }}
RUN_SHA: ${{ github.sha }}
run: |
set -euo pipefail
[[ "$CANDIDATE_SHA" =~ ^[0-9a-f]{40}$ ]]
[[ "$RELEASE_REF" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]
test "$WORKFLOW_SHA" = "$CANDIDATE_SHA"
test "$RUN_SHA" = "$CANDIDATE_SHA"
test "$(git rev-parse HEAD)" = "$CANDIDATE_SHA"
test -z "$(git status --porcelain)"
test "v$(cat VERSION)" = "$RELEASE_REF"
bin/agent-workflows-release check-version --root .
if git show-ref --verify --quiet "refs/tags/$RELEASE_REF"; then
echo "Release tag already exists; refusing to reuse it" >&2
exit 1
fi

- name: Set up Ruby
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1
with:
ruby-version: "3.4"

- name: Install validation gems
run: |
# JSON 3 changes malformed-input diagnostics used by the full suite.
gem install json -v 2.21.2 --no-document
gem install rubocop -v "$(tr -d '[:space:]' < .rubocop-version)" --no-document --conservative
gem install json_schemer -v "$(tr -d '[:space:]' < .json-schemer-version)" --no-document --conservative
ruby -rjson -e 'puts "Validation JSON #{JSON::VERSION}"; abort "unexpected JSON version" unless JSON::VERSION == "2.21.2"'

- name: Run every validation suite before tagging
env:
CI: "true"
run: bin/validate

- name: Confirm validation preserved the candidate
env:
CANDIDATE_SHA: ${{ inputs.candidate_sha }}
run: |
test "$(git rev-parse HEAD)" = "$CANDIDATE_SHA"
test -z "$(git status --porcelain)"

release:
needs: verify
permissions:
actions: read
contents: write
pull-requests: read
runs-on: ubuntu-latest
environment: stable-release
steps:
- name: Checkout the exact release ref
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
ref: ${{ inputs.candidate_sha }}

- name: Verify independent human approval before creating a tag
id: approval
env:
APPROVED_COMMIT: ${{ inputs.candidate_sha }}
CHANGE_AUTHOR: ${{ inputs.change_author }}
GH_TOKEN: ${{ github.token }}
RELEASE_ACTOR: ${{ github.actor }}
RELEASE_REF: ${{ inputs.release }}
REPOSITORY: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
RUN_ATTEMPT: ${{ github.run_attempt }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
WORKFLOW_PATH: .github/workflows/release.yml
run: |
set -euo pipefail
associated_authors="$(
gh api "repos/$REPOSITORY/commits/$APPROVED_COMMIT/pulls" \
--jq '[.[] | select(.merged_at != null) | .user.login] | unique'
)"
test "$(jq 'length' <<<"$associated_authors")" -eq 1
test "$(jq -r '.[0]' <<<"$associated_authors")" = "$CHANGE_AUTHOR"

approvals="$(gh api "repos/$REPOSITORY/actions/runs/$RUN_ID/approvals")"
approval_reviewer="$(
jq -er '[.[] |
select(.state == "approved") |
select(.user.type == "User") |
select(any(.environments[]?; .name == "stable-release")) |
.user.login] | last // empty' <<<"$approvals"
)"

test "${approval_reviewer,,}" != "${CHANGE_AUTHOR,,}"
test "${approval_reviewer,,}" != "${RELEASE_ACTOR,,}"
echo "reviewer=$approval_reviewer" >> "$GITHUB_OUTPUT"

- name: Create the immutable annotated tag after full validation and approval
id: tag
env:
GH_TOKEN: ${{ github.token }}
APPROVED_COMMIT: ${{ inputs.candidate_sha }}
RELEASE_REF: ${{ inputs.release }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
test "$(git rev-parse HEAD)" = "$APPROVED_COMMIT"
bin/agent-workflows-release check-version --root .
tag_object="$(jq -n --arg tag "$RELEASE_REF" --arg object "$APPROVED_COMMIT" \
'{tag: $tag, message: ("Agent Workflows " + $tag), object: $object, type: "commit"}' | \
gh api --method POST "repos/$REPOSITORY/git/tags" --input - --jq .sha)"
jq -n --arg ref "refs/tags/$RELEASE_REF" --arg sha "$tag_object" \
'{ref: $ref, sha: $sha}' | \
gh api --method POST "repos/$REPOSITORY/git/refs" --input -
git fetch origin "refs/tags/$RELEASE_REF:refs/tags/$RELEASE_REF"
bin/agent-workflows-release verify-tag --root . --release "$RELEASE_REF" \
--approved-commit "$APPROVED_COMMIT" --expected-tag-object "$tag_object"
echo "object=$tag_object" >> "$GITHUB_OUTPUT"

- name: Record protected-environment approval evidence
env:
APPROVAL_REVIEWER: ${{ steps.approval.outputs.reviewer }}
APPROVED_COMMIT: ${{ inputs.candidate_sha }}
CHANGE_AUTHOR: ${{ inputs.change_author }}
EXPECTED_TAG_OBJECT: ${{ steps.tag.outputs.object }}
RELEASE_ACTOR: ${{ github.actor }}
RELEASE_REF: ${{ inputs.release }}
REPOSITORY: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
RUN_ATTEMPT: ${{ github.run_attempt }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
WORKFLOW_PATH: .github/workflows/release.yml
run: |
set -euo pipefail
bin/agent-workflows-release record-receipt \
--root . \
--release "$RELEASE_REF" \
--approved-commit "$APPROVED_COMMIT" \
--expected-tag-object "$EXPECTED_TAG_OBJECT" \
--environment stable-release \
--change-author "$CHANGE_AUTHOR" \
--release-actor "$RELEASE_ACTOR" \
--approval-reviewer "$APPROVAL_REVIEWER" \
--repository "$REPOSITORY" \
--workflow-run-id "$RUN_ID" \
--workflow-run-attempt "$RUN_ATTEMPT" \
--workflow-path "$WORKFLOW_PATH" \
--workflow-run-url "$RUN_URL" \
--recorded-at "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
--receipt agent-workflows-release-receipt.json

- name: Publish release and durable receipt
env:
GH_TOKEN: ${{ github.token }}
RELEASE_REF: ${{ inputs.release }}
run: |
set -euo pipefail
if gh release view "$RELEASE_REF" >/dev/null 2>&1; then
echo "Release already exists; refusing to replace durable release evidence: $RELEASE_REF" >&2
exit 1
fi
gh release create "$RELEASE_REF" \
agent-workflows-release-receipt.json \
--verify-tag \
--title "Agent Workflows $RELEASE_REF" \
--generate-notes
7 changes: 7 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Portable language for multi-agent PR-batch workflows: how coordinators, workers, and a coordination backend talk about ownership, liveness, and batch lifecycle. Keep repo-specific policy, backend names, dashboards, and domain vocabulary in each consumer repo's `AGENTS.md` seam or local docs. The companion glossary for source-pack distribution, install-path, seam, readiness, and review terms is [docs/source-pack-glossary.md](docs/source-pack-glossary.md).

For the source pack itself, **stable channel** means one protected immutable
annotated `vX.Y.Z` tag plus protected-environment approval and a durable receipt
bound to its peeled exact commit. **Development channel** means an explicitly
selected mutable branch-following install. These delivery channels are distinct
from a consumer repository's beta/RC/final release phase. Agent Workflows does
not require or verify cryptographic tag signatures.

## Language

### Ownership
Expand Down
70 changes: 37 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,11 @@ default.

## Quick Start

Clone the workflow pack and install it into the agent host you use:

```bash
git clone https://github.com/shakacode/agent-workflows "$HOME/src/agent-workflows"
cd "$HOME/src/agent-workflows"
bin/install-agent-workflows --host codex
```

For a stable first install, follow the [authenticated release bootstrap](docs/release-channel.md#install-update-and-roll-back).
It checks a verifier against an independently trusted SHA-256 pin, verifies the
exact tag and protected release evidence, and only then executes the installer.
Use `--host claude` for Claude Code, or `--target "$HOME/.agents"` for an
explicit shared agent home.
explicit shared agent home. Do not execute an installer from an unverified tag.

New to the pack? Follow [Getting Started](docs/getting-started.md) for
prerequisites with versions, one host install, one repo adoption, and a first
Expand Down Expand Up @@ -127,19 +122,19 @@ delivery route: ordinary flat skills or the native `scw` plugin.
Install into the default Codex home:

```bash
bin/install-agent-workflows --host codex
bin/install-agent-workflows --host codex --release vX.Y.Z
```

Install into the default Claude Code home:

```bash
bin/install-agent-workflows --host claude
bin/install-agent-workflows --host claude --release vX.Y.Z
```

Install into a different agent home, such as `~/.agents`:

```bash
bin/install-agent-workflows --host codex --target "$HOME/.agents"
bin/install-agent-workflows --host codex --target "$HOME/.agents" --release vX.Y.Z
```

The installer copies:
Expand All @@ -149,19 +144,22 @@ The installer copies:
- selected `bin/*` helpers to `<target>/bin/`;
- install metadata to `<target>/.agent-workflows-install.json`.

The default `--delivery-mode flat` installs those skills directly. When the
native `scw` plugin is enabled, retain the installer-managed companion assets
without a second flat skill tree:
The default `--delivery-mode flat` installs those skills directly. With the
release-pinned Claude native `scw` plugin enabled, complete the
[exact-release bootstrap](docs/release-channel.md#install-update-and-roll-back)
before retaining the companion assets without a second flat skill tree:

```bash
bin/install-agent-workflows \
--host codex \
"$source/bin/install-agent-workflows" \
--host claude --source "$source" \
--release "$release" \
--delivery-mode plugin-companion
```

The selected delivery mode is durable install state. Repeated installs,
`upgrade-agent-workflows`, rollback, and `agent-stack sync` replay it unless an
explicit `--delivery-mode` changes it.
The selected delivery mode is durable install state. Stable install, update,
and rollback always name an exact annotated `vX.Y.Z` tag; development branch
following requires `--channel development`. Neither path silently crosses
channels. See [Stable Release Channel](docs/release-channel.md).

Add `<target>/bin` to `PATH` if you want `agent-workflow-seam-doctor`,
`agent-workflows-doctor`, `agent-workflows-refresh`, `agent-workflows-status`,
Expand All @@ -182,16 +180,18 @@ Code exposes `skills/verify/SKILL.md` as `/scw:verify`.
Add and install the Claude Code marketplace plugin with:

```text
/plugin marketplace add shakacode/agent-workflows
/plugin marketplace add shakacode/agent-workflows@vX.Y.Z
/plugin install scw@agent-workflows
```

Add and install the Codex marketplace plugin with:

```bash
codex plugin marketplace add shakacode/agent-workflows
codex plugin add scw@agent-workflows
```
For stable Codex skills, use the verified
[copy bootstrap](docs/release-channel.md#install-update-and-roll-back).
The current native Codex URL route is **development/unverified**: marketplace
`--ref` pins only the catalog, while the `scw` entry separately fetches the
default branch without a plugin ref or SHA. Stable companion assets do not
make that native plugin stable. See
[Native Plugin Paths](docs/installation-and-upgrades.md#native-plugin-paths)
for the explicitly development-only route.

The manifests point at the existing `./skills/` tree; native installation does
not copy helper binaries, write
Expand Down Expand Up @@ -237,11 +237,11 @@ Codex when an existing session must rediscover changed skills or instructions.

## Consumer Repo Adoption

From each repository that should use these workflows, initialize and validate a
starter seam in one command:
For a stable install, initialize and validate each consumer repository against
the installed exact-release target (`$HOME/.claude` for a Claude install):

```bash
agent-workflow-seam-doctor --init --shared "$HOME/src/agent-workflows"
agent-workflow-seam-doctor --init --shared "$HOME/.codex"
```

The initializer preserves existing repo-owned seam content. It detects executable
Expand All @@ -254,9 +254,12 @@ configuration. Supply both commands explicitly to complete the seam in one run:
agent-workflow-seam-doctor --init \
--validate-command 'bin/validate' \
--test-command 'bin/test' \
--shared "$HOME/src/agent-workflows"
--shared "$HOME/.codex"
```

Only development-channel installs should instead use a mutable source checkout
such as `--shared "$HOME/src/agent-workflows"`.

Simple explicit commands forward wrapper arguments automatically. Explicit
`npm run` commands add npm's `--` separator; `pnpm run` and `yarn run` pass the
arguments directly. Compound shell expressions are preserved verbatim; include
Expand Down Expand Up @@ -414,13 +417,14 @@ ruby bin/codex-plugin-manifest-check
Check the installed pack:

```bash
agent-workflows-status --host codex
agent-workflows-status --host codex --release vX.Y.Z
```

Upgrade and validate a consumer repo seam:

```bash
upgrade-agent-workflows --host codex --consumer-root /path/to/consumer/repo
upgrade-agent-workflows --host codex --release vX.Y.Z \
--consumer-root /path/to/consumer/repo
```

Long-running agents keep whatever skill text they already loaded. Let active
Expand Down
1 change: 1 addition & 0 deletions bin/agent-stack-test.bash
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
export AGENT_WORKFLOWS_CHANNEL=development
source "$ROOT/test/agent_stack/support.bash"
source "$ROOT/test/agent_stack/install_test.bash"
source "$ROOT/test/agent_stack/doctor_install_test.bash"
Expand Down
4 changes: 4 additions & 0 deletions bin/agent-workflows-doctor-test.bash
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def status_payload(status, installed_version:, available_version:, guidance: nil
"installed_revision" => installed_version && "installed-revision",
"available_version" => available_version,
"available_revision" => available_version && "available-revision",
"channel" => "stable",
"release_ref" => "v1.0.0",
"available_release_ref" => "v1.0.0",
"exact_commit" => installed_version && "installed-revision",
"checked_remote" => false,
"reason" => nil,
"guidance" => guidance,
Expand Down
Loading