Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9d06f01
fix: bootstrap the initial plugin release
nathanvale Aug 5, 2026
83fd820
Address PR review feedback (#11)
nathanvale Aug 5, 2026
a1e3dab
fix: enforce native plugin release metadata
nathanvale Aug 5, 2026
246f1e3
Address PR review feedback (#11)
nathanvale Aug 5, 2026
6930f18
feat(init): reset recipient release lineage to 0.1.0
nathanvale Aug 5, 2026
96aad7e
feat(payload): enforce one safe regular-file-only payload inventory
nathanvale Aug 5, 2026
5396fd3
feat(metadata): own native package rules with two named profiles
nathanvale Aug 5, 2026
e6451fe
feat(release): bind proof, tag, release, and repair to one commit
nathanvale Aug 5, 2026
3127a5b
feat(ci): gate installable payload changes on releasable PR title
nathanvale Aug 5, 2026
5f1b06f
feat(readiness): verify human-owned publication safeguards read-only
nathanvale Aug 5, 2026
57cd1d3
feat(proof): prove native install, cache, trust, update, and rollback
nathanvale Aug 5, 2026
d1e859f
feat(canary): qualify publishing-system changes with hosted Git canaries
nathanvale Aug 5, 2026
048faae
docs: align operator guidance with the hardened release contract
nathanvale Aug 5, 2026
d00e0fb
docs(plan): add reviewed plugin publishing hardening plan
nathanvale Aug 5, 2026
4c4dd44
fix(ci): isolate packaging fixture from GitHub SHA
nathanvale Aug 5, 2026
04fb28a
Address PR review feedback (#11)
nathanvale Aug 5, 2026
79cd078
fix: close release and canary review gaps
nathanvale Aug 5, 2026
64b60ea
fix: exercise centralized release impact policy
nathanvale Aug 5, 2026
c55082c
fix: bind final release validation to candidate
nathanvale Aug 5, 2026
95c4fb2
fix: close release repair review gaps
nathanvale Aug 5, 2026
d32f637
fix: fetch fork canary heads from source
nathanvale Aug 5, 2026
4c95f28
fix: make hosted and repair gates fail closed
nathanvale Aug 5, 2026
ebbc03e
fix: bind release gates across rename and trust boundaries
nathanvale Aug 5, 2026
f3f8d03
fix: execute release gates from trusted code
nathanvale Aug 5, 2026
232ec8e
fix: isolate release impact in trusted workflow
nathanvale Aug 5, 2026
9c6954c
fix: preserve canary generator and transport boundaries
nathanvale Aug 5, 2026
aafeec5
fix: close release review gaps (#11)
nathanvale Aug 5, 2026
4cf8727
docs: bind release automation identity (#11)
nathanvale Aug 5, 2026
7180e3f
fix: bind package source to checkout (#11)
nathanvale Aug 5, 2026
7832ac9
fix: resolve publication review findings (#11)
nathanvale Aug 5, 2026
5cfdcdc
fix: pin bootstrap release to v0.1.0 (#11)
nathanvale Aug 5, 2026
fc0c99d
docs: clarify release automation credentials (#11)
nathanvale Aug 5, 2026
fef9097
fix: require release automation token (#11)
nathanvale Aug 5, 2026
2a9efcf
fix: harden release and canary admission (#11)
nathanvale Aug 5, 2026
6b9b3b6
fix: close release review gaps
nathanvale Aug 6, 2026
8660009
fix: fail closed on workflow policy gaps
nathanvale Aug 6, 2026
24034b5
fix: sanitize public canary publication
nathanvale Aug 6, 2026
9096fa6
fix: prove sanitized public canaries
nathanvale Aug 6, 2026
7036418
fix: preserve unusual archive filenames
nathanvale Aug 6, 2026
7ea726a
fix: detect list-item workflow actions
nathanvale Aug 6, 2026
ed5a995
fix: resolve release qualification review findings (#11)
nathanvale Aug 6, 2026
fac5e40
fix: close remaining release review gaps
nathanvale Aug 6, 2026
cb182a3
fix: check main linear history policy
nathanvale Aug 6, 2026
bf01654
fix: verify hosted canary credentials (#11)
nathanvale Aug 6, 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
2 changes: 1 addition & 1 deletion .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "harness-native-plugin-prototype",
"interface": {
"displayName": "Harness Native Plugin Prototype"
"displayName": "Harness Plugin Prototype"
},
"plugins": [
{
Expand Down
5 changes: 3 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"name": "Prototype"
},
"metadata": {
"description": "Marketplace for Harness Native Plugin Prototype",
"description": "Marketplace for Harness Plugin Prototype",
"version": "0.1.0"
},
"plugins": [
Expand All @@ -14,7 +14,8 @@
"author": {
"name": "Prototype"
},
"source": "./plugin"
"source": "./plugin",
"defaultEnabled": false
}
]
}
4 changes: 1 addition & 3 deletions .github/.release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
{
".": "0.1.0"
}
{}
Comment thread
myagentdojo marked this conversation as resolved.
3 changes: 3 additions & 0 deletions .github/release-please-config.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"include-component-in-tag": false,
"skip-github-release": true,
"release-search-depth": 100,
"commit-search-depth": 500,
"packages": {
".": {
"release-type": "node",
"initial-version": "0.1.0",
"package-name": "agent-plugin",
"changelog-path": "CHANGELOG.md",
"changelog-sections": [
Expand All @@ -23,6 +25,7 @@
{ "type": "json", "path": ".claude-plugin/marketplace.json", "jsonpath": "$.metadata.version" },
{ "type": "json", "path": "plugin/.claude-plugin/plugin.json", "jsonpath": "$.version" },
{ "type": "json", "path": "plugin/.codex-plugin/plugin.json", "jsonpath": "$.version" },
{ "type": "generic", "path": "plugin/hooks/codex/hooks.json" },
{ "type": "generic", "path": "plugin/runtime/hello-world.js" }
]
}
Expand Down
137 changes: 137 additions & 0 deletions .github/workflows/hosted-canary.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: Hosted canary qualification

on:
pull_request_target:

permissions:
checks: write
contents: read

concurrency:
group: hosted-canary-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}
cancel-in-progress: true

jobs:
classify:
name: Classify publishing-system paths
runs-on: ubuntu-24.04
outputs:
check_run_id: ${{ steps.check.outputs.check_run_id }}
required: ${{ steps.classify.outputs.required }}
triggers: ${{ steps.classify.outputs.triggers }}
steps:
- name: Start required check on the pull request head
id: check
env:
GH_TOKEN: ${{ github.token }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
check_run_id=$(gh api --method POST "repos/${GITHUB_REPOSITORY}/check-runs" \
-f name="Hosted public and private Git canaries" \
-f head_sha="$HEAD_SHA" \
-f status="in_progress" \
--jq .id)
Comment thread
myagentdojo marked this conversation as resolved.
Outdated
printf 'check_run_id=%s\n' "$check_run_id" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.base.sha }}
fetch-depth: 0
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: 1.3.14
- name: Fetch candidate object without executing it
env:
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: git fetch --no-tags origin "$HEAD_SHA"
Comment thread
myagentdojo marked this conversation as resolved.
Outdated
- name: Classify with trusted base code
id: classify
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
result="$(bun run ship:canary -- --classify --base "$BASE_SHA" --head "$HEAD_SHA" --json)"
printf '%s\n' "$result"
printf 'required=%s\n' "$(jq -r '.canaries.required' <<< "$result")" >> "$GITHUB_OUTPUT"
printf 'triggers=%s\n' "$(jq -c '.canaries.triggeringPaths' <<< "$result")" >> "$GITHUB_OUTPUT"

qualify:
name: Qualify immutable hosted candidates
if: needs.classify.outputs.required == 'true' && github.event.pull_request.head.repo.full_name == github.repository
needs: classify
runs-on: ubuntu-24.04
environment: hosted-canary-qualification
steps:
- name: Check out trusted driver
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.base.sha }}
fetch-depth: 0
- name: Check out candidate as data
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
path: candidate
persist-credentials: false
fetch-depth: 1
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: 1.3.14
- name: Install pinned native marketplace CLIs
run: bun add --global "@anthropic-ai/claude-code@2.1.222" "@openai/codex@0.146.1"
- name: Qualify immutable candidates with trusted driver
env:
CANARY_GH_TOKEN: ${{ secrets.CANARY_GH_TOKEN }}
CANARY_SSH_KNOWN_HOSTS: ${{ secrets.CANARY_SSH_KNOWN_HOSTS }}
CANARY_SSH_PRIVATE_KEY: ${{ secrets.CANARY_SSH_PRIVATE_KEY }}
SOURCE_SHA: ${{ github.event.pull_request.head.sha }}
run: |
test -n "$CANARY_GH_TOKEN"
test -n "$CANARY_SSH_KNOWN_HOSTS"
test -n "$CANARY_SSH_PRIVATE_KEY"
export GH_TOKEN="$CANARY_GH_TOKEN"
gh auth setup-git
install -m 700 -d "$HOME/.ssh"
printf '%s\n' "$CANARY_SSH_KNOWN_HOSTS" > "$HOME/.ssh/known_hosts"
chmod 600 "$HOME/.ssh/known_hosts"
eval "$(ssh-agent -s)"
trap 'ssh-agent -k >/dev/null' EXIT
ssh-add - <<< "$CANARY_SSH_PRIVATE_KEY"
git remote set-url origin "git@github.com:${GITHUB_REPOSITORY}.git"
bun run ship:canary -- --execute --source-root candidate --ref "$SOURCE_SHA" --json

result:
name: Publish hosted-canary check result
if: always()
needs:
- classify
- qualify
runs-on: ubuntu-24.04
steps:
- name: Enforce conditional qualification
env:
GH_TOKEN: ${{ github.token }}
CHECK_RUN_ID: ${{ needs.classify.outputs.check_run_id }}
CANARIES_REQUIRED: ${{ needs.classify.outputs.required }}
CLASSIFICATION_RESULT: ${{ needs.classify.result }}
QUALIFICATION_RESULT: ${{ needs.qualify.result }}
TRIGGERING_PATHS: ${{ needs.classify.outputs.triggers }}
run: |
conclusion=success
summary="Hosted canaries not required. Publishing-system triggers: ${TRIGGERING_PATHS}"
if [ "$CLASSIFICATION_RESULT" != "success" ]; then
conclusion=failure
summary="Publishing-system classification failed."
elif [ "$CANARIES_REQUIRED" = "true" ] && [ "$QUALIFICATION_RESULT" != "success" ]; then
conclusion=failure
summary="Hosted canaries were required but did not qualify. Publishing-system triggers: ${TRIGGERING_PATHS}"
elif [ "$CANARIES_REQUIRED" = "true" ]; then
summary="Hosted public and private Git canaries passed for: ${TRIGGERING_PATHS}"
fi
gh api --method PATCH "repos/${GITHUB_REPOSITORY}/check-runs/${CHECK_RUN_ID}" \
-f status="completed" \
-f conclusion="$conclusion" \
-f "output[title]=Hosted canary qualification" \
-f "output[summary]=$summary" >/dev/null
printf '%s\n' "$summary"
test "$conclusion" = "success"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
15 changes: 2 additions & 13 deletions .github/workflows/plugin-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,10 @@ name: Prove and package plugin

on:
pull_request:
paths:
- "plugin/**"
- "runtime/src/**"
- "plugin.config.json"
- "scripts/**"
- "package.json"
- "CHANGELOG.md"
- ".agents/plugins/marketplace.json"
- ".claude-plugin/marketplace.json"
- ".github/.release-please-manifest.json"
- ".github/release-please-config.json"
- ".github/workflows/**"
push:
branches:
- main
- "candidate/**"
workflow_dispatch:

permissions:
Expand Down Expand Up @@ -69,7 +58,7 @@ jobs:
name: agent-plugin-${{ github.sha }}
path: |
dist/*.tar.gz
dist/*.provenance.json
dist/*.checksums.json
if-no-files-found: error

attest:
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/pull-request-title.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,27 @@ jobs:
fi
echo "Use a Conventional Commit title, for example: feat: add a portable command" >&2
exit 1

release-impact:
name: Release impact
runs-on: ubuntu-24.04
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
PR_AUTHOR_LOGIN: ${{ github.event.pull_request.user.login }}
EXPECTED_RELEASE_PLEASE_LOGIN: ${{ vars.RELEASE_PLEASE_AUTOMATION_LOGIN || 'github-actions[bot]' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: 1.3.14
- name: Gate payload changes on release intent
run: >-
bun run scripts/release-impact.ts
Comment thread
myagentdojo marked this conversation as resolved.
Outdated
--pr-head-ref "$PR_HEAD_REF"
--pr-author-login "$PR_AUTHOR_LOGIN"
--expected-release-please-login "$EXPECTED_RELEASE_PLEASE_LOGIN"
Loading