Skip to content

Regenerate the stale index - #40

Merged
lwaldron merged 1 commit into
mainfrom
regenerate-stale-index
Sep 14, 2026
Merged

lwaldron merged 1 commit into
mainfrom
regenerate-stale-index

Conversation

@lwaldron

Copy link
Copy Markdown
Member

The committed index predates the citation field renames — it still emits method_citation and protocol_citation: ~. This is the runner's only lookup surface, so it has been serving field names the current standard rejects outright.

Why it went stale

Index generation has been failing since the require-pr-review ruleset was added. The generator itself succeeds; the push is rejected:

remote: error: GH013: Repository rule violations found for refs/heads/main.

github-actions[bot] is not a bypass actor, and it cannot be made one — bypass actors of type Integration must be GitHub Apps installed on the organisation, and Actions isn't one. The org's installed apps are slack, stale, codecov, appveyor, travis-ci, repo-ranger, r-universe.

So this PR regenerates the index by hand to fix the live wrongness. Restoring the automation is a separate change — a write-scoped deploy key, which is a valid bypass actor type.

What changed

Everything here is generator output; nothing is hand-edited.

method_citationmethod_origin_citation on the three protocols that name a method origin
method_origin_citation dropped on the four database-build protocols that originate no method (ADR 0014)
protocol_citation populated on all seven, having been ~ throughout
database_urls becomes a list on humann4-translated-search-build — see below
artifact_doi: ~null same value, spelled the way PyYAML spells it

The database_urls change is a bug fix

humann4-translated-search-build has a one-element database_urls list in its source. The old R generator flattened it to a scalar string — R collapses length-1 vectors — so that one protocol's field had a different type in the index than the other six, which a consumer parsing the index would have tripped over. The Python generator preserves the list.

Worth knowing that the R→Python rewrite fixed this silently; it wasn't a stated goal of #39.

Verification

Generated with scripts/generate_protocols_yaml.py from agent-protocol-standard@2afdfc1, against this repository at 9a831cc, with GITHUB_REPOSITORY=waldronlab/agent-protocols and GITHUB_REF_NAME=main. Every changed line was categorised and accounted for; all seven protocol_url values still point at main, unchanged.

🤖 Generated with Claude Code

The committed index predates the citation field renames: it still emits
`method_citation` and `protocol_citation: ~`, so the runner — whose only lookup
surface this is — reads field names the current standard rejects outright.

It is stale because index generation has been failing since the
`require-pr-review` ruleset was added. The generator runs fine; the push is
rejected with GH013, because `github-actions[bot]` is not a bypass actor and
cannot be made one (bypass actors of type Integration must be GitHub Apps
installed on the org, and Actions is not one). Regenerated by hand here as a
normal pull request; the automation is a separate fix.

Three kinds of change, all from the generator, none hand-edited:

- `method_citation` -> `method_origin_citation`, and dropped entirely on the
  four database-build protocols that originate no method (ADR 0014).
- `protocol_citation` populated on all seven, having been `~` throughout.
- `database_urls` on humann4-translated-search-build becomes a list. Its source
  has always been a one-element list, and the old R generator flattened it to a
  scalar — so that one protocol's field had a different type in the index than
  the other six. The Python generator preserves it. A real fix, not churn.

`artifact_doi: ~` also reads `null` now, which is the same value spelled the way
PyYAML spells it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 14, 2026 01:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The regenerated index matches the current schema and preserves expected field types.

Pull request overview

Regenerates PROTOCOLS.yaml to match the current citation schema and source metadata.

Changes:

  • Renames and updates citation fields.
  • Removes inapplicable method-origin citations.
  • Preserves list types and normalizes null values.
File summaries
File Summary
PROTOCOLS.yaml Regenerated index metadata and citation fields.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@lwaldron
lwaldron merged commit 22ef171 into main Sep 14, 2026
2 checks passed
@lwaldron
lwaldron deleted the regenerate-stale-index branch September 14, 2026 01:44
lwaldron added a commit that referenced this pull request Sep 14, 2026
@v0 resolved to a commit from before the Python rewrite — 22 behind main — so
both workflows here were running the R tooling. Every pull request was being
checked by the old R validator, and the Pydantic rules merged in the rewrite
were enforcing nothing. CI was green the whole time.

Tracking main also unblocks this PR: the committer-name and committer-email
inputs it passes do not exist at @v0, and the R generator would have regenerated
the index in R's YAML style, re-flattening the one-element database_urls and
restoring `~` for `null` — partially reverting #40.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lwaldron added a commit that referenced this pull request Sep 14, 2026
* Generate the index with a deploy key

Index generation has been failing since the require-pr-review ruleset was
added: the generator runs, the push is rejected with GH013, because
github-actions[bot] is not a bypass actor and cannot be made one — bypass
actors of type Integration must be GitHub Apps installed on the organisation,
and Actions is not one.

A write-scoped deploy key is a valid bypass actor type and is scoped to this
repository alone. actions/checkout takes it via `ssh-key`, loads it, and sets
the remote to SSH, so the composite action's existing `git push` is unchanged.

The key is an environment secret rather than a repository secret, in an
environment whose deployment branch policy allows only `main`. A same-repo pull
request does receive repository secrets, and this key bypasses the branch
protection, so a contributor could otherwise read it out of a workflow added in
a PR.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Authenticate as a GitHub App, not a deploy key

waldronlab-index-generation (app 4936017) holds `contents: write` and nothing
else, is installed on this repository alone, and mints a token that expires after
an hour. The deploy key it replaces was a static credential whose ruleset bypass
covered every rule, including deletion and non-fast-forward.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Scope the token and attribute the commit to the App

`permission-contents: write` is requested explicitly rather than inheriting
whatever the installation holds, so granting the App another permission later
cannot silently widen this token.

GITHUB_TOKEN drops to `contents: read`: the push uses the installation token, so
write here only handed every step a second write-capable credential.

The commit is attributed to the App that pushes it rather than to
github-actions[bot], which no longer has anything to do with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Track main rather than @v0

@v0 resolved to a commit from before the Python rewrite — 22 behind main — so
both workflows here were running the R tooling. Every pull request was being
checked by the old R validator, and the Pydantic rules merged in the rewrite
were enforcing nothing. CI was green the whole time.

Tracking main also unblocks this PR: the committer-name and committer-email
inputs it passes do not exist at @v0, and the R generator would have regenerated
the index in R's YAML style, re-flattening the one-element database_urls and
restoring `~` for `null` — partially reverting #40.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Address review: fix the committer identity, serialize runs

The committer email used the App registration id from INDEX_APP_ID, but the
address needs the bot's *user* id — verified against the API, the registration
is 4936017 and the bot user is 328912240. With the wrong value the push still
succeeds and GitHub silently declines to link the commit to the bot, which is
exactly the sort of failure nobody notices. Resolved at run time instead of
hardcoded, so the same workflow shape works in the template.

Two merges in quick succession would have run concurrently, and the second push
would have been rejected as non-fast-forward: its checkout predates the first
run's index commit. Queued rather than cancelled, since a cancelled run leaves
the index describing the previous commit.

Separately, the ruleset is now split. The App's bypass was `always`, which
exempts every rule in a ruleset — so it could have deleted or force-pushed
`main`, not merely skipped review, and the least-privilege claim made for it was
not true. `require-pr-review` now holds only pull_request and
required_status_checks; a new `protect-main-history` holds deletion and
non_fast_forward and is bypassed by nobody but the owner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Address review: check out the tip, fail loudly, fix the local command

The concurrency group alone did not make the push safe. `actions/checkout`
defaults to the event SHA, so a queued run still started from the commit that
triggered it and pushed a non-fast-forward once `main` had moved. It checks out
the branch tip now, which also means the index describes `main` as it is rather
than as it was.

`echo "id=$(gh api ...)"` exits 0 when the lookup fails, writing an empty id — so
a failed lookup produced a malformed address and lost bot attribution silently,
which is the same class of quiet failure the id itself was wrong for an hour ago.
Assigned separately under `set -euo pipefail`, and empty fails the step.

Added `workflow_dispatch`. Tracking the generator at `@main` means the next run
uses it, but a generator change upstream raises no event here, so the index can
sit stale until an unrelated local change. A manual trigger is the honest
minimum; a schedule would be the fuller answer.

CONTRIBUTING told contributors to run `Rscript
../agent-protocol-standard/scripts/validate-protocol.R`, which has not existed
since the Python rewrite. Replaced, and the replacement was run against this
repository's protocols to confirm it works.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Pin the generator's ref to main as well as the checkout

The checkout is forced to `main`, but the generator reads GITHUB_REF_NAME to
build protocol_url values. On a workflow_dispatch from another branch or tag
those disagree: the index would describe main's content under a different ref's
URLs, and every URL in it would resolve to the wrong revision.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Pass the ref as an input, not by overriding GITHUB_REF_NAME

GITHUB_REF_NAME is runner-provided and a workflow cannot reliably override it
through `env`, so the previous commit's attempt to force `main` for the generator
would not have worked. The action takes a `ref` input instead, which the
generator reads from PROTOCOL_INDEX_REF — a name the runner does not own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants