Use full dependency resolution in automated lockfile repair paths, add regression coverage, and refresh the stale Rollup snapshot.
Co-Authored-By: Dotta <cryppadotta@users.noreply.github.com>
Co-Authored-By: Codex <codex@openai.com>
Co-Authored-By: lockfile-bot <lockfile-bot@users.noreply.github.com>
## Thinking Path
> - Paperclip uses GitHub Actions to protect changes before they enter
`master`.
> - GitHub evaluates every pull request in a native stack against the
stack base.
> - The current workflow therefore starts the complete CI matrix for
every layer in a stack.
> - A large stack can queue many copies of the same integrated
verification and delay every pull request.
> - GitHub provides stack position and base metadata so workflows can
select merge-relevant layers.
> - This pull request keeps policy and required check names on every
layer, but runs full CI only for ordinary pull requests, the top layer,
and the lowest unmerged layer.
> - The benefit is much lower CI load without weakening the
required-check contract.
## Linked Issues or Issue Description
**What existing behavior does this improve?**
The trusted pull request workflow currently runs every test, build,
canary, and E2E lane for every pull request in a native stack.
**Subsystem affected**
GitHub Actions pull request verification.
**Current behavior**
A stack with 61 pull requests can start 61 complete CI matrices after a
cascading rebase.
**Proposed behavior**
Run the always-on policy job and stable required-check aggregators for
every layer. Run the complete verification matrix only for ordinary pull
requests, the top stack layer, and the lowest unmerged stack layer.
**Reason and benefit**
The top layer verifies the integrated stack. The lowest unmerged layer
verifies the current merge candidate. Middle layers keep
branch-protection checks without consuming the complete runner matrix.
**Breaking changes**
Middle stack layers no longer run the complete CI matrix. Their `ci /
verify` and `ci / e2e` checks still require the policy job to pass and
require every expensive lane to be intentionally skipped.
## What Changed
- Add a fail-safe stack scope decision to the trusted PR runner gate.
- Run typecheck, general tests, build, serialized tests, canary, and E2E
shards only for ordinary, top, and lowest-unmerged pull requests.
- Preserve the required `ci / verify` and `ci / e2e` names on every
layer.
- Make the required aggregators distinguish valid middle-layer skips
from failures or missing scope decisions.
- Add regression coverage for ordinary, top, bottom, middle, and
malformed stack metadata.
## Verification
- `node --test scripts/__tests__/e2e-shard.test.mjs` — 11 tests passed.
- `actionlint .github/workflows/pr-trusted.yml .github/workflows/pr.yml`
— passed.
- `git diff --check origin/master...HEAD` — passed.
- The caller remains pinned to the current trusted workflow. A separate
activation change must advance the immutable SHA after this pull request
lands.
## Risks
- Incorrect stack classification could skip important jobs. Missing or
malformed stack metadata defaults to full CI.
- Middle-layer required checks depend on the policy job and verify that
all expensive jobs have the `skipped` result.
- The reusable workflow change does not become active until the
immutable caller SHA advances in a separate change.
> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
- OpenAI Codex with GPT-5. The exact deployment suffix and context
window are not exposed. The model used reasoning, repository tools, code
execution, Git, and GitHub API access.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs: #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip uses trusted GitHub Actions workflows to verify every pull
request
> - Native stacked pull requests use another pull request branch as
their base
> - A parent layer can change a package manifest without committing
`pnpm-lock.yaml`
> - A child layer can inherit that manifest change without changing a
manifest itself
> - The current policy skips lockfile regeneration for that child and
downstream frozen installs fail
> - This pull request validates the complete merge tree and shares a
regenerated lockfile only when needed
> - The benefit is reliable stacked pull request verification without
weakening the trusted workflow boundary
## Linked Issues or Issue Description
**What happened?**
A stacked child pull request inherited a package manifest change from
its parent. The child did not change a manifest itself. The policy job
skipped lockfile regeneration. Downstream jobs tried to restore an
artifact that did not exist and then failed during frozen dependency
installation.
**Expected behavior**
The policy job must validate the complete pull request merge tree. It
must upload a regenerated lockfile when the checked-in lockfile is
stale, including on a stacked child layer.
**Steps to reproduce**
1. Create a parent pull request that changes `package.json` without
committing `pnpm-lock.yaml`.
2. Create a child pull request on that branch without another manifest
change.
3. Run the trusted pull request workflow for the child.
4. Observe that frozen dependency installation fails because no
`pr-lockfile` artifact exists.
**Paperclip version or commit**
`f173ee09fa5c2ced7806bba47b54c3df853ab4df`
**Deployment mode**
GitHub Actions trusted pull request workflow.
**Agent adapter(s) involved**
Not adapter-specific. This is a core CI workflow bug.
## What Changed
- Regenerate the lockfile from every checked-out merge tree.
- Compare the generated lockfile with the checked-in copy before upload.
- Download the artifact only when the policy job reports that it
uploaded one.
- Fail closed when a reported artifact is missing.
- Add a workflow contract test for stacked lockfile handling.
- Keep the caller pinned to the last merged trusted SHA; after this
implementation merges, a separate activation PR will advance the
immutable pin to its merge commit.
## Verification
- `actionlint .github/workflows/pr-trusted.yml`
- `node --test scripts/__tests__/e2e-shard.test.mjs`
## Risks
- The policy job runs one lockfile-only install for every pull request.
This can add a small amount of CI time.
- A missing artifact now fails immediately when the policy job reports
an upload. This is intentional because it exposes workflow corruption.
- No runtime or product behavior changes.
- The implementation/activation split is intentional: unmerged
PR-authored workflow code must never execute on trusted runners.
## Model Used
OpenAI Codex with model `gpt-5`, reasoning, tool use, and code
execution.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
## Thinking Path
> - Paperclip uses pull request checks to protect changes.
> - The trusted CI gate selects GitHub or AWS runners.
> - GitHub can return an old pull request base SHA after the live base
advances.
> - The signed event, live Git ref, ancestry, and merge parents provide
the required proof.
> - The stale API field rejects a safe run even when those proofs pass.
> - This pull request removes that unreliable equality.
> - The benefit is correct AWS routing for trusted stacked pull
requests.
## Linked Issues or Issue Description
Refs #12339
Refs #12459
## What Changed
- Stop treating pull request base.sha as a current-state signal.
- Keep the signed event base SHA and live ref descendant check.
- Keep the live base or synthetic base merge-parent proof.
- Keep all numeric identity, repository, head SHA, and triggering actor
checks.
## Verification
- actionlint .github/workflows/pr-trusted.yml .github/workflows/pr.yml
- github-runners/tests/test-workflow.sh .github/workflows/pr-trusted.yml
.github/workflows/pr.yml
- The corrected gate selected the Fleet label with the exact live event
data from PR #12339 run 33201610330.
## Risks
- The pull request API base SHA can be stale and is no longer compared.
- Replaced ancestry, a changed head, a changed merge parent, and a
changed merge tree still fail closed.
## Model Used
- OpenAI Codex, GPT-5.6, with reasoning and terminal tool use.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used with version and capability
details
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have linked existing public pull requests
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket ID
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation in the operations repository
- [x] I have considered and documented risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open findings
- [x] I will address all Greptile and reviewer comments before
requesting merge
## Thinking Path
> - Paperclip uses pull request checks to protect changes.
> - The trusted CI workflow selects GitHub or AWS runners.
> - Stacked pull requests can advance their base branch while a gate
waits.
> - The gate already proves that the live base descends from the event
base.
> - An earlier exact base check rejects that safe state before the
ancestry check runs.
> - This pull request removes the conflicting check and verifies live
API consistency.
> - The benefit is automatic AWS routing for trusted stacked pull
requests without weaker identity checks.
## Linked Issues or Issue Description
Refs #12339
Refs #12457
## What Changed
- Allow the live pull request base SHA to advance from the signed event
base snapshot.
- Require the pull request API base SHA to match the live Git ref during
validation.
- Keep the numeric author, sender, and triggering actor checks.
- Keep descendant ancestry and synthetic merge validation.
## Verification
- actionlint .github/workflows/pr-trusted.yml .github/workflows/pr.yml
- github-runners/tests/test-workflow.sh .github/workflows/pr-trusted.yml
.github/workflows/pr.yml
- The routing suite covers a live stacked base advance and a base change
during validation.
## Risks
- A trusted stacked run can use a newer descendant base than its signed
event snapshot.
- Replaced ancestry still fails closed.
- A live base change during gate validation still fails closed.
## Model Used
- OpenAI Codex, GPT-5.6, with reasoning and terminal tool use.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either linked existing issues or described the issue in
this pull request
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket ID
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation in the operations repository
- [x] I have considered and documented risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open findings
- [x] I will address all Greptile and reviewer comments before
requesting merge
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Pull request checks protect the application and its contributors.
> - The trusted CI gate verifies signed event data against live GitHub
state.
> - GitHub gives a stacked pull request a synthetic merge commit for its
base stack.
> - The current validator expects the raw base SHA as the first merge
parent.
> - That assumption sends safe stacked pull requests to GitHub-hosted
runners.
> - This pull request validates the synthetic base merge and its
ancestry explicitly.
> - The benefit is safe automatic AWS routing for approved stacked pull
requests.
## Linked Issues or Issue Description
Refs #12455
Refs #12456
**What existing behavior does this improve?**
The trusted runner gate validates merge commits for master-based pull
requests but rejects GitHub synthetic base merges for stacked pull
requests.
**Subsystem affected**
GitHub Actions pull request identity and merge-state validation.
**Current behavior**
A trusted stacked pull request passes all numeric identity checks. The
gate fails closed because the first event merge parent is a GitHub
synthetic base merge instead of the raw base snapshot SHA.
**Proposed behavior**
The gate verifies the current base-ref tip, base-snapshot ancestry,
identical event and live merge parents, the child head parent, the
synthetic base merge parents, and identical event and live merge trees.
**Reason and benefit**
The change preserves fail-closed live-state validation while allowing
approved stacked pull requests to use the isolated AWS Fleet.
**Breaking changes**
None for untrusted contributors. Trusted stacked pull requests can
select AWS after the caller pins this workflow version.
**Additional context**
GitHub builds a stacked test merge in two steps. It first merges the
stack base into its own current base. It then uses that synthetic commit
as the first parent of the child test merge.
## What Changed
- Fetch and validate the current base branch ref.
- Require the event base snapshot to remain an ancestor of that ref.
- Validate direct and synthetic base merge parent shapes.
- Preserve the existing child-head, live-state, merge-tree, repository,
and actor checks.
## Verification
- Ran actionlint on the trusted workflow.
- Ran the external routing suite.
- Added positive coverage for the GitHub stacked merge shape.
- Added fail-closed coverage for replaced base ancestry and a synthetic
merge that omits the current base ref.
- Replayed the checks against the live merge shape for pull request
#12340.
## Risks
The gate has more GitHub API reads. Its five-minute timeout and
fail-closed behavior limit the effect of API errors. The accepted
synthetic commit must be the same in the event and live merge, must
include the current base branch as a direct parent, and must produce the
same merge tree.
> For core feature work, check ROADMAP.md first and discuss it in #dev
before opening the PR. Feature PRs that overlap with planned core work
may need to be redirected — check the roadmap first. See
CONTRIBUTING.md.
## Model Used
OpenAI Codex on GPT-5. The exact deployment ID and context-window size
are not exposed. The model used reasoning, tool use, GitHub API access,
and local code execution.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used with version and capability
details
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have linked existing public items and described the issue in-PR
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - Pull request checks protect the application and its contributors.
> - The trusted CI workflow sends approved contributors to isolated AWS
runners.
> - The workflow currently limits AWS routing to pull requests that
target master.
> - Stacked pull requests target another branch and stay in the GitHub
queue.
> - This pull request keeps the identity checks and accepts a live
nonempty base branch in the Paperclip repository.
> - The benefit is that trusted stacked pull requests can use the AWS
fleet automatically.
## Linked Issues or Issue Description
**What existing behavior does this improve?**
The trusted pull request runner gate currently sends only master-based
pull requests to AWS.
**Subsystem affected**
GitHub Actions pull request routing.
**Current behavior**
A trusted contributor can pass all numeric identity checks. The gate
still selects GitHub-hosted runners when the pull request targets
another branch in a stack.
**Proposed behavior**
The gate accepts any nonempty base branch in the Paperclip base
repository. It still verifies the live base ref, base SHA, head SHA,
merge SHA, author ID, sender ID, and triggering actor ID.
**Reason and benefit**
Large pull request stacks currently add all heavy jobs to the limited
GitHub-hosted queue. This change lets approved contributors use the
isolated AWS fleet for those jobs.
**Breaking changes**
Trusted pull requests that target a non-master branch now use AWS
instead of GitHub-hosted runners. Untrusted pull requests keep the
current GitHub-hosted route.
**Additional context**
Pull request #12339 is the master-based first item in a stack. Its child
pull requests show this queue pattern.
## What Changed
- Replace the master-only route check with a nonempty base-ref check.
Keep the existing base-repository and live-state checks.
## Verification
- Ran actionlint on .github/workflows/pr-trusted.yml.
- Ran the external routing test suite. It passed the trusted
stacked-base case and all fail-closed identity cases.
## Risks
The AWS trust boundary now includes code from a non-master base branch
when the current pull request author, sender, and triggering actor are
all approved numeric GitHub IDs. An approved account can already submit
arbitrary head code. The runner remains isolated and has no production
access or repository secrets.
> For core feature work, check ROADMAP.md first and discuss it in #dev
before opening the PR. Feature PRs that overlap with planned core work
may need to be redirected — check the roadmap first. See
CONTRIBUTING.md.
## Model Used
OpenAI Codex on GPT-5. The exact deployment ID and context-window size
are not exposed. The model used reasoning, tool use, GitHub API access,
and local code execution.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with Fixes: # / Closes #
/ Refs # OR (b) described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
## Summary
- validate the event base ref/SHA against the live PR state instead of
requiring the moving `master` branch tip to remain unchanged while a
hosted gate queues
- retain exact event/live merge parent and tree validation, plus
author/sender/rerun checks
## Canary finding
A seven-minute hosted-gate queue allowed `master` to advance. Requiring
the live branch tip to equal the event base snapshot would route
otherwise valid trusted runs back to GitHub-hosted indefinitely on a
busy repository.
## Validation
- actionlint and workflow-contract tests pass
- internal routing harness passes
- replaced PR base snapshot, stale head, changed merge parent/tree, and
untrusted actors all remain fail-closed
- AWS routing remains disabled during rotation
## Summary
- use `${{ github.sha }}` as the event merge commit validated by the
trusted gate
- retain exact base/head parent and identical-tree comparison against
the current live merge ref
## Canary finding
GitHub leaves `pull_request.merge_commit_sha` empty on some `opened`
payloads even though the workflow runs against a valid merge ref. The
gate safely fell back to GitHub-hosted and no EC2 instance launched.
## Validation
- `actionlint .github/workflows/pr-trusted.yml .github/workflows/pr.yml`
- `node --test ./scripts/__tests__/e2e-shard.test.mjs`
- internal routing harness passes and asserts `EVENT_MERGE_SHA` is
sourced from `${{ github.sha }}`
- AWS routing remains disabled during rotation
## Summary
- emit exactly one `runner` job output from the trusted gate
- write `ubuntu-latest` only inside fail-closed paths
- write the Fleet label only after every identity, PR-state,
merge-equivalence, and rerun-actor check passes
## Canary finding
The live gate reached the trusted success notice, but GitHub retained
the first of two duplicate `runner=` outputs, so policy still requested
`ubuntu-latest`. No EC2 instance launched. Routing was disabled
immediately.
## Validation
- `actionlint .github/workflows/pr-trusted.yml .github/workflows/pr.yml`
- `node --test ./scripts/__tests__/e2e-shard.test.mjs`
- internal routing harness passes and now requires exactly one runner
output in all cases
- AWS routing remains disabled during rotation
## Summary
- validate the live master ref and event base SHA before AWS routing
- accept GitHub synthetic merge commits only when the event and live
commits have the exact expected base/head parents and identical tree
- preserve fail-closed routing for malformed, stale, replaced, or
untrusted events
## Canary finding
A trusted reopened PR produced two synthetic merge SHAs with different
timestamps but identical current base/head parents and tree. The former
exact-SHA comparison safely fell back to GitHub-hosted runners, but
could not route a valid event to AWS.
## Validation
- `actionlint .github/workflows/pr-trusted.yml .github/workflows/pr.yml`
- `node --test ./scripts/__tests__/e2e-shard.test.mjs`
- real-event gate simulation selects the Fleet label for equivalent
merge commits
- negative simulations keep an untrusted sender and replaced head on
`ubuntu-latest`
- AWS routing remains disabled during rotation
## Thinking Path
> - Paperclip uses pull request CI to protect changes before merge
> - The trusted reusable workflow will select isolated AWS capacity
> - The active workflow changed while the reusable workflow waited for
merge
> - The reusable policy must contain every current CI policy step before
activation
> - This pull request synchronizes the migration-order check and shell
validation
> - The benefit is one reviewed workflow version with verified job
parity
## Linked Issues or Issue Description
Refs #12436
**What existing behavior does this improve?**
This improves the pull request CI workflow synchronization before AWS
runner activation.
**Subsystem affected**
Cross-cutting CI automation.
**Current behavior**
The active workflow validates migration order. The new reusable workflow
does not yet contain that check.
**Proposed behavior**
Both workflow definitions contain the same heavy jobs and policy steps
before the active workflow becomes a thin caller.
**Reason and benefit**
The synchronization prevents policy drift during the two-step secure
rollout.
**Breaking changes**
None. AWS routing remains disabled.
## What Changed
- Added the current migration-order validation to the trusted workflow.
- Added the existing shellcheck intent annotation to the active
workflow.
- Verified normalized heavy-job parity between both definitions.
## Verification
- actionlint on both workflow files
- Local trusted-routing and normalized workflow-parity tests
- git diff --check
## Risks
Low risk. The migration check already runs in active CI. This change
copies it into the inactive trusted definition. AWS routing stays
disabled.
## Model Used
OpenAI Codex with GPT-5, tool use, and code execution.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either linked a related public PR or described the issue
with the matching template fields
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [ ] I will address all Greptile and reviewer comments before
requesting merge
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Pull request checks protect the quality of the control plane
> - The current checks depend only on the shared GitHub-hosted runner
limit
> - Busy periods leave many pull request jobs queued even when external
capacity is available
> - Public pull request code must not select or directly access private
runner infrastructure
> - This pull request adds an inactive reusable workflow with a
fail-closed identity gate
> - A later pull request can pin this workflow by its full master commit
SHA
> - The benefit is automatic, controlled access to isolated runner
capacity without changing current CI during bootstrap
## Linked Issues or Issue Description
**What existing behavior does this improve?**
This improves the pull request CI workflow. It prepares the existing
checks to use an administrator-controlled runner selection.
**Subsystem affected**
Cross-cutting GitHub Actions CI configuration.
**Current behavior**
Every pull request job uses `ubuntu-latest`. Jobs wait when the
GitHub-hosted concurrency limit is full.
**Proposed behavior**
Add a reusable copy of the current PR workflow. A GitHub-hosted gate
validates durable numeric user IDs and current GitHub API state. The
gate emits one runner label. The default and every validation failure
use `ubuntu-latest`. The AWS label is possible only when an
administrator enables it and every identity check passes.
This bootstrap pull request does not change the active
`.github/workflows/pr.yml` caller. A follow-up change will call this
workflow by the full master commit SHA.
**Reason and benefit**
The split bootstrap creates an immutable trust boundary before external
runners are reachable. It also keeps CI automatic for contributors.
Contributors do not select a runner.
**Breaking changes**
None in this bootstrap pull request. The active PR workflow does not
change.
## What Changed
- Added an inactive `workflow_call` copy of the current PR checks.
- Added a GitHub-hosted routing gate that checks the repository ID, pull
request author ID, event sender ID, rerun actor ID, base branch, head
SHA, merge SHA, and current pull request state.
- Made every validation failure select `ubuntu-latest`.
- Pinned every third-party action to a full commit SHA.
- Disabled persistent checkout credentials for all jobs.
- Limited the workflow token to Actions read, contents read, and pull
request read access.
## Verification
- `actionlint .github/workflows/pr-trusted.yml`
- Ran the dedicated workflow routing test harness against
`.github/workflows/pr-trusted.yml`.
- Compared the job keys with `.github/workflows/pr.yml`. The new
workflow contains every existing job plus the gate.
- Verified each pinned action commit against its current GitHub
major-version tag.
## Risks
The gate could route a trusted pull request to the wrong runner if an
identity check is incomplete. The gate checks durable numeric IDs from
the event and current GitHub API state. It checks the rerun actor
separately. It defaults to GitHub-hosted capacity before any validation
runs.
This file is inactive in this pull request. The follow-up caller and
runner-group restriction must use the exact commit that reaches
`master`.
> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
OpenAI Codex based on GPT-5. The exact serving model ID and
context-window size are not exposed in this environment. The model used
high-reasoning, terminal, GitHub API, browser, and web-research
capabilities.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge