fix(evals): select Grok subscription protocol credentials explicitly (#13901)

## Thinking Path

> - Paperclip manages agent work through shared runner contracts.
> - Direct protocol evals qualify provider behavior against a mock
control plane.
> - Grok supports API keys and company subscription credentials.
> - The hosted protocol workflow selected an API key for every Grok
cell.
> - Product subscription support did not enable subscription protocol
runs.
> - This change adds explicit subscription selection and checks the
recorded authentication mode.

## Linked Issues or Issue Description

Refs #13878, #13882, #12618.

The direct Grok protocol roster cannot run with subscription
authentication through the trusted default-branch workflow. Add an
explicit selector while keeping API-key dispatches compatible. Keep the
actor allowlist, protected environment, immutable source revisions, and
publication gates.

## What Changed

- Add `grok_authentication` with `api_key` and `subscription` choices.
Keep `api_key` as the compatibility default.
- Deliver the protected `GROK_AUTH_JSON` secret only to a
subscription-selected Grok cell. Do not provide an API key to that cell.
- Read authentication mode from the pinned eval program's actual roster
summary. Retain it in the cell, catalog, campaign roster, and result.
- Reject missing or mismatched authentication evidence during
aggregation. Preserve cell metadata and an allowlisted failure reason
before failing a cell, so malformed evidence cannot hide the retained
attempt.
- Document credential setup, source separation, and temporary-secret
cleanup.

## Verification

- `node --test
packages/paperclip-runner/scripts/runner-protocol-eval-campaign.test.mjs
packages/paperclip-runner/scripts/runner-protocol-eval-workflow-security.test.mjs
scripts/__tests__/release-verify-workflow.test.mjs`: 34 tests passed.
- Validated all 39 Grok cells at eval revision
`3213dbec7e8ca1865ea95e6db7e7d34b095eb47a`; every selected cell requests
only the subscription credential. Validation made zero provider calls.
- Negative coverage rejects invalid selectors and missing or API
authentication evidence in an otherwise passing subscription attempt.
- `git diff --check` passed. All 53 current-head checks passed; the
unchanged callback-drain timing test passed its bounded rerun, and the
failed attempt is retained. Greptile reviewed
`ecd3dcc0e998f07cf56fcb1f087946f50f388bec` at 5/5 with no remaining
findings.
- No Docker or broad builds ran on the developer machine. CI performs
repository checks on the configured fleet.

## Risks

Grok runs require an eval revision that records `authenticationMode` in
the roster summary. Missing evidence fails closed. The credential
contains account access and refresh tokens; an owner must approve its
delivery to the protected environment before a live run. The change adds
no PR trigger or authorization bypass. Live subscription protocol
qualification remains pending this workflow reaching master.

## Model Used

OpenAI GPT-6 through Codex, with tool use and code execution. The exact
serving model identifier and context-window size are not exposed in this
session.

## 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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip authored and GitHub committed 2026-09-23 18:43:21 -05:00
1 parent 794b09f834
commit db8f8fe5b7
6 files changed
+198 -8

No files matched your search

@@ -22,6 +22,14 @@ on:
description: "Optional lower concurrency (at least 2, no higher than the configured campaign limit)"
type: string
required: false
grok_authentication:
description: "Explicit Grok credential source; subscription uses protected GROK_AUTH_JSON"
type: choice
options:
- api_key
- subscription
default: api_key
required: false
max_infrastructure_retries:
description: "Automatic retries only for explicitly retryable infrastructure failures (0-3)"
type: number
@@ -256,6 +264,7 @@ jobs:
MAX_PARALLEL_LIMIT: ${{ needs.authorize.outputs.max_parallel_limit }}
REQUESTED_MAX_PARALLEL: ${{ inputs.max_parallel }}
ROSTERS: ${{ inputs.rosters || 'all' }}
GROK_AUTHENTICATION: ${{ inputs.grok_authentication || 'api_key' }}
run: |
set -euo pipefail
if ! [[ "$MAX_PARALLEL" =~ ^[1-9][0-9]*$ ]] || [ "$MAX_PARALLEL" -lt 2 ] || [ "$MAX_PARALLEL" -gt "$MAX_PARALLEL_LIMIT" ]; then
@@ -272,6 +281,7 @@ jobs:
node packages/paperclip-runner/scripts/runner-protocol-eval-campaign.mjs catalog \
--evals-root .paperclip-evals \
--rosters "$ROSTERS" \
--grok-authentication "$GROK_AUTHENTICATION" \
--campaign-id "gha-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" \
--max-parallel "$MAX_PARALLEL" \
--output runner-protocol-eval-catalog.json
@@ -542,6 +552,7 @@ jobs:
ANTHROPIC_API_KEY: ${{ matrix.credentialName == 'ANTHROPIC_API_KEY' && secrets.ANTHROPIC_API_KEY || '' }}
OPENROUTER_API_KEY: ${{ matrix.credentialName == 'OPENROUTER_API_KEY' && secrets.OPENROUTER_API_KEY || '' }}
XAI_API_KEY: ${{ matrix.credentialName == 'XAI_API_KEY' && secrets.XAI_API_KEY || '' }}
PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET: ${{ matrix.credentialName == 'PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET' && secrets.GROK_AUTH_JSON || '' }}
PAPERCLIP_CLAUDE_MANAGED_PROFILE_ID: ${{ vars.PAPERCLIP_CLAUDE_MANAGED_PROFILE_ID }}
PAPERCLIP_CLAUDE_MANAGED_AGENT_ID: ${{ vars.PAPERCLIP_CLAUDE_MANAGED_AGENT_ID }}
PAPERCLIP_CLAUDE_MANAGED_AGENT_VERSION: ${{ vars.PAPERCLIP_CLAUDE_MANAGED_AGENT_VERSION }}
@@ -582,19 +593,36 @@ jobs:
--runner-package runner-protocol-build/extracted/paperclip-runner.tgz \
--runnerd runner-protocol-build/extracted/paperclip-runnerd \
--runs-root cell-output/runs \
--summary-path cell-output/roster-summary.json \
--max-infrastructure-retries "$MAX_INFRASTRUCTURE_RETRIES" \
--run-id "gha-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${CELL_ID}"
status=$?
set -e
CELL_EXIT_CODE="$status" node --input-type=module <<'NODE'
import { writeFileSync } from "node:fs";
import { readFileSync, writeFileSync } from "node:fs";
let authenticationMode;
let authenticationEvidenceFailure;
if (["XAI_API_KEY", "PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET"].includes(process.env.CREDENTIAL_NAME)) {
const expected = process.env.CREDENTIAL_NAME === "XAI_API_KEY" ? "api_key" : "subscription";
try {
const observed = JSON.parse(readFileSync("cell-output/roster-summary.json", "utf8")).authenticationMode;
// Never copy arbitrary provider output into cell metadata or errors.
if (["api_key", "subscription"].includes(observed)) authenticationMode = observed;
if (authenticationMode !== expected) authenticationEvidenceFailure = "grok_authentication_evidence_mismatch";
} catch {
authenticationEvidenceFailure = "grok_authentication_evidence_unreadable";
}
}
writeFileSync("cell-output/cell.json", `${JSON.stringify({
schema: "paperclip.runner-protocol-eval.cell/v1",
cellId: process.env.CELL_ID,
rosterFile: process.env.ROSTER_FILE,
caseId: process.env.CASE_ID,
...(authenticationMode ? { authenticationMode } : {}),
...(authenticationEvidenceFailure ? { authenticationEvidenceFailure } : {}),
exitCode: Number(process.env.CELL_EXIT_CODE),
}, null, 2)}\n`, { mode: 0o600 });
if (authenticationEvidenceFailure) throw new Error(authenticationEvidenceFailure);
NODE
exit "$status"
@@ -119,6 +119,20 @@ from the default branch and provide:
marked disabled;
- `max_infrastructure_retries`: zero through three, applied only when an
attempt explicitly reports a retryable infrastructure failure.
- `grok_authentication`: `api_key` (the compatibility default) or `subscription`.
Subscription requires an explicitly selected Grok roster and the owner-approved
`GROK_AUTH_JSON` secret in the protected `runner-e2e-paid` environment. API mode
uses only `XAI_API_KEY`. A missing selected credential fails; it never changes
authentication mode or falls back to another credential.
For subscription qualification, pass `-f grok_authentication=subscription` when
dispatching the default-branch workflow. The immutable catalog, retained cell,
campaign roster, and result record carry `authenticationMode`. The cell reads it
from the pinned eval program's actual roster summary, and aggregation rejects
missing or mismatched authentication evidence. Select an eval revision that
supports Grok subscription admission and records this summary field. Keep API
and subscription campaigns separate when interpreting results. Remove temporary
subscription test secrets after the authorized qualification completes.
The authorization job resolves the Paperclip branch to a commit and verifies
the supplied eval commit before any checkout. A short-lived bot token generated
@@ -54,7 +54,14 @@ function inside(root, candidate, label) {
return resolve(candidate);
}
export function credentialForConfig(config) {
function validateGrokAuthenticationMode(mode) {
if (mode !== "api_key" && mode !== "subscription") {
throw new Error("Grok authentication mode must be api_key or subscription");
}
return mode;
}
export function credentialForConfig(config, grokAuthenticationMode = "api_key") {
if (config.provider === "opencode") return "OPENROUTER_API_KEY";
if (config.provider === "claude_managed") return "ANTHROPIC_API_KEY";
if (config.provider === "aws_agentcore") return "AWS_AGENTCORE_OIDC";
@@ -64,7 +71,11 @@ export function credentialForConfig(config) {
if (config.provider === "acpx") {
if (config.acpxAgent === "pi") return "OPENROUTER_API_KEY";
if (config.acpxAgent === "claude") return "ANTHROPIC_API_KEY";
if (config.acpxAgent === "grok") return "XAI_API_KEY";
if (config.acpxAgent === "grok") {
return validateGrokAuthenticationMode(grokAuthenticationMode) === "subscription"
? "PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET"
: "XAI_API_KEY";
}
if (config.acpxAgent === "codex") return "OPENAI_API_KEY";
}
throw new Error(
@@ -117,8 +128,10 @@ export async function buildProtocolEvalCatalog({
campaignId,
source = {},
maxParallel = 100,
grokAuthenticationMode = "api_key",
}) {
safeId(campaignId, "campaign ID");
validateGrokAuthenticationMode(grokAuthenticationMode);
if (
!Number.isSafeInteger(maxParallel) ||
maxParallel < 2 ||
@@ -159,7 +172,7 @@ export async function buildProtocolEvalCatalog({
`Config for ${rosterId}`,
);
const config = await loadObject(configPath);
const credentialName = credentialForConfig(config);
const credentialName = credentialForConfig(config, grokAuthenticationMode);
const cases = roster.cases.map((caseId) => safeId(caseId, "case ID"));
if (new Set(cases).size !== cases.length) {
throw new Error(`Live roster ${rosterId} repeats a case`);
@@ -172,6 +185,9 @@ export async function buildProtocolEvalCatalog({
provider: String(config.provider ?? "codex"),
driver: String(config.driver ?? "codex_app_server"),
credentialName,
...(config.provider === "acpx" && config.acpxAgent === "grok"
? { authenticationMode: grokAuthenticationMode }
: {}),
cases,
});
}
@@ -185,6 +201,9 @@ export async function buildProtocolEvalCatalog({
}
}
if (rosters.length === 0) throw new Error("No live rosters were selected");
if (grokAuthenticationMode === "subscription" && !rosters.some((roster) => roster.authenticationMode === "subscription")) {
throw new Error("Subscription selection requires an explicit Grok roster");
}
const cells = rosters.flatMap((roster) =>
roster.cases.map((caseId) => ({
@@ -196,6 +215,7 @@ export async function buildProtocolEvalCatalog({
provider: roster.provider,
driver: roster.driver,
credentialName: roster.credentialName,
...(roster.authenticationMode ? { authenticationMode: roster.authenticationMode } : {}),
})),
);
const shards = [[], []];
@@ -209,7 +229,7 @@ export async function buildProtocolEvalCatalog({
schema: "paperclip.runner-protocol-eval.catalog/v1",
campaignId,
source,
selection: { kind: requested === null ? "maintained_full" : "subset", rosters: rosterSelection },
selection: { kind: requested === null ? "maintained_full" : "subset", rosters: rosterSelection, grokAuthenticationMode },
rosters,
cells,
matrices: shards.map((include) => ({ include })),
@@ -399,6 +419,10 @@ export async function aggregateProtocolEvalCampaign({
) {
throw new Error(`Downloaded cell metadata drifted for ${cellId}`);
}
if (expected.authenticationMode !== undefined &&
(status.authenticationMode !== expected.authenticationMode || status.authenticationEvidenceFailure !== undefined)) {
throw new Error(`Invalid Grok authentication evidence for ${cellId}; retained cell metadata and attempts require inspection`);
}
const attemptRoot = resolve(dirname(statusPath), "runs");
const attemptIds = [];
const attemptMetadata = await lstat(attemptRoot).catch(() => null);
@@ -473,6 +497,7 @@ export async function aggregateProtocolEvalCampaign({
model: cell.model,
provider: cell.provider,
driver: cell.driver,
...(cell.authenticationMode ? { authenticationMode: cell.authenticationMode } : {}),
attemptIds,
finalAttemptId,
disposition: score.disposition,
@@ -513,6 +538,7 @@ export async function aggregateProtocolEvalCampaign({
model: roster.model,
provider: roster.provider,
driver: roster.driver,
...(roster.authenticationMode ? { authenticationMode: roster.authenticationMode } : {}),
selected: roster.cases.length,
passed: results.filter(
(result) => result.rosterId === roster.rosterId && result.passed,
@@ -699,6 +725,7 @@ async function main() {
rosterSelection: argument(args, "--rosters", "all"),
campaignId: argument(args, "--campaign-id", `local-${Date.now()}`),
maxParallel: Number(argument(args, "--max-parallel", "100")),
grokAuthenticationMode: argument(args, "--grok-authentication", "api_key"),
source: {
paperclipSha: process.env.PAPERCLIP_PROTOCOL_EVAL_SOURCE_SHA ?? null,
evalsSha: process.env.PAPERCLIP_PROTOCOL_EVALS_SHA ?? null,
@@ -104,6 +104,71 @@ test("maps every qualified driver to one explicit credential boundary", () => {
);
});
async function grokFixture() {
const value = await fixture();
value.config = {
schema: "paperclip-runner/eval-config/v1", id: "live-grok",
provider: "acpx", driver: "acpx_runtime", acpxAgent: "grok", model: "grok-4.7",
};
value.roster.model = value.config.model;
await writeFile(join(value.program, "configs/live-opencode-model.json"), JSON.stringify(value.config));
await writeFile(join(value.program, "rosters/live-opencode-model.json"), JSON.stringify(value.roster));
return value;
}
test("selects exactly one Grok credential and preserves authentication provenance", async () => {
const { root } = await grokFixture();
for (const [mode, credential] of [
["api_key", "XAI_API_KEY"],
["subscription", "PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET"],
]) {
const catalog = await buildProtocolEvalCatalog({ evalsRoot: root, campaignId: "gha-42-1", grokAuthenticationMode: mode });
assert.equal(catalog.selection.grokAuthenticationMode, mode);
assert.equal(catalog.cells[0].credentialName, credential);
assert.equal(catalog.cells[0].authenticationMode, mode);
assert.equal(catalog.rosters[0].authenticationMode, mode);
assert.equal(catalog.matrices[0].include[0].credentialName, credential);
}
for (const mode of ["", "auto", "subscription,api_key", null]) {
await assert.rejects(buildProtocolEvalCatalog({ evalsRoot: root, campaignId: "gha-42-1", grokAuthenticationMode: mode }), /authentication mode/);
}
const other = await fixture();
await assert.rejects(buildProtocolEvalCatalog({ evalsRoot: other.root, campaignId: "gha-42-1", grokAuthenticationMode: "subscription" }), /requires an explicit Grok roster/);
});
test("subscription evidence cannot be substituted with an API or missing authentication record", async () => {
const { root, config, evalCase } = await grokFixture();
const catalog = await buildProtocolEvalCatalog({ evalsRoot: root, campaignId: "gha-42-1", grokAuthenticationMode: "subscription" });
const catalogPath = join(root, "catalog.json");
await writeFile(catalogPath, JSON.stringify(catalog));
const cell = catalog.cells[0];
const download = join(root, "downloads/cell");
const attemptId = "grok-attempt-01";
const attempt = join(download, "runs", attemptId);
await mkdir(attempt, { recursive: true });
for (const [file, value] of Object.entries({
"artifact.json": { attemptId, usage: null },
"score.json": { attemptId, caseId: evalCase.id, passed: true, disposition: "passed" },
"case.json": evalCase, "config.json": config,
})) await writeFile(join(attempt, file), JSON.stringify(value));
const aggregate = () => aggregateProtocolEvalCampaign({
catalogPath, downloadsRoot: join(root, "downloads"), evalsRoot: root,
runsOut: join(root, "merged"), campaignOut: join(root, "campaign.json"), source: {},
});
const status = { cellId: cell.cellId, rosterFile: cell.rosterFile, caseId: cell.caseId, exitCode: 0 };
await writeFile(join(download, "cell.json"), JSON.stringify({ ...status, authenticationMode: "subscription" }));
const passed = await aggregate();
assert.equal(passed.totals.passed, 1);
assert.equal(passed.results[0].authenticationMode, "subscription");
assert.equal(passed.rosters[0].authenticationMode, "subscription");
await writeFile(join(download, "cell.json"), JSON.stringify({ ...status, authenticationMode: "subscription", authenticationEvidenceFailure: "grok_authentication_evidence_unreadable" }));
await assert.rejects(aggregate(), /Invalid Grok authentication evidence/);
for (const authenticationMode of [undefined, "api_key", "auto"]) {
await writeFile(join(download, "cell.json"), JSON.stringify({ ...status, authenticationMode }));
await assert.rejects(aggregate(), /Invalid Grok authentication evidence/);
}
});
test("catalogs roster plus case cells and emits bounded balanced shards", async () => {
const { root } = await fixture();
const catalog = await buildProtocolEvalCatalog({
@@ -1,5 +1,7 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
import { spawnSync } from "node:child_process";
import { tmpdir } from "node:os";
import { resolve } from "node:path";
import test from "node:test";
@@ -13,6 +15,21 @@ const trustedPrWorkflowPath = resolve(
".github/workflows/pr-trusted.yml",
);
test("Grok subscription credentials require explicit catalog selection and observed auth evidence", async () => {
const workflow = await readFile(workflowPath, "utf8");
const paid = workflow.slice(workflow.indexOf(" steps: &direct_eval_steps"), workflow.indexOf(" eval_shard_1:"));
assert.match(workflow, /grok_authentication:\n[\s\S]*?type: choice\n[\s\S]*?default: api_key/u);
assert.match(workflow, /--grok-authentication "\$GROK_AUTHENTICATION"/u);
assert.ok(paid.includes("PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET: ${{ matrix.credentialName == 'PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET' && secrets.GROK_AUTH_JSON || '' }}"));
assert.ok(paid.includes("XAI_API_KEY: ${{ matrix.credentialName == 'XAI_API_KEY' && secrets.XAI_API_KEY || '' }}"));
assert.match(paid, /--summary-path cell-output\/roster-summary\.json/u);
assert.match(paid, /JSON\.parse\(readFileSync\("cell-output\/roster-summary\.json", "utf8"\)\)\.authenticationMode/u);
assert.match(paid, /authenticationMode !== expected/u);
for (const job of [workflow.slice(0, workflow.indexOf(" eval_shard_0:")), workflow.slice(workflow.indexOf(" report:"))]) {
assert.doesNotMatch(job, /secrets\.GROK_AUTH_JSON/u);
}
});
test("direct live eval workflow keeps paid execution behind stable actor authorization", async () => {
const workflow = await readFile(workflowPath, "utf8");
assert.match(workflow, /^\s{2}authorize:/mu);
@@ -228,3 +245,41 @@ test("trusted catalog, direct eval, and report orchestration stay on workflow re
assert.doesNotMatch(section, /ref: \$\{\{ needs\.authorize\.outputs\.target_sha \}\}/u, `${job} must not execute target orchestration code`);
}
});
test("authentication failures retain cell metadata without leaking malformed summary content", async () => {
const workflow = await readFile(workflowPath, "utf8");
const script = workflow.match(/CELL_EXIT_CODE="\$status" node --input-type=module <<'NODE'\n([\s\S]*?) NODE/u)?.[1];
assert.ok(script);
const root = await mkdtemp(resolve(tmpdir(), "grok-cell-evidence-"));
try {
await mkdir(resolve(root, "cell-output"));
const summary = resolve(root, "cell-output/roster-summary.json");
for (const [content, expectedFailure, expectedMode] of [
[undefined, "grok_authentication_evidence_unreadable", undefined],
["{SENSITIVE_SENTINEL", "grok_authentication_evidence_unreadable", undefined],
["null", "grok_authentication_evidence_unreadable", undefined],
['{"authenticationMode":"SENSITIVE_SENTINEL"}', "grok_authentication_evidence_mismatch", undefined],
['{"authenticationMode":"api_key"}', "grok_authentication_evidence_mismatch", "api_key"],
['{"authenticationMode":"subscription"}', undefined, "subscription"],
]) {
if (content === undefined) await rm(summary, { force: true });
else await writeFile(summary, content);
const result = spawnSync(process.execPath, ["--input-type=module", "-e", script], {
cwd: root, encoding: "utf8",
env: { CREDENTIAL_NAME: "PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET", CELL_ID: "cell-1", CASE_ID: "context", ROSTER_FILE: "grok.json", CELL_EXIT_CODE: "7" },
});
assert.equal(result.status, expectedFailure ? 1 : 0);
const retained = await readFile(resolve(root, "cell-output/cell.json"), "utf8");
const metadata = JSON.parse(retained);
assert.equal(metadata.cellId, "cell-1");
assert.equal(metadata.caseId, "context");
assert.equal(metadata.exitCode, 7);
assert.equal(metadata.authenticationEvidenceFailure, expectedFailure);
assert.equal(metadata.authenticationMode, expectedMode);
assert.doesNotMatch(retained + result.stdout + result.stderr, /SENSITIVE_SENTINEL/u);
}
} finally {
await rm(root, { recursive: true, force: true });
}
});
@@ -433,12 +433,13 @@ test("Runner eval workflows pin actions and gate paid live execution", () => {
});
test("direct Grok qualification installs the pinned binary and scopes its API key", () => {
test("direct Grok qualification installs the pinned binary and scopes the selected credential", () => {
const workflow = readWorkflow("runner-protocol-live-evals.yml");
assert.ok(workflow.includes("XAI_API_KEY: ${{ matrix.credentialName == 'XAI_API_KEY' && secrets.XAI_API_KEY || '' }}"));
assert.ok(workflow.includes("if [ -f packages/grok-acp/install.mjs ]; then"));
assert.ok(workflow.indexOf("node packages/grok-acp/install.mjs") < workflow.indexOf("pnpm --filter @paperclipai/paperclip-runner deploy --prod"));
assert.ok(!workflow.includes("secrets.GROK_AUTH_JSON"));
assert.ok(workflow.includes("PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET: ${{ matrix.credentialName == 'PAPERCLIP_ACPX_GROK_AUTH_JSON_SECRET' && secrets.GROK_AUTH_JSON || '' }}"));
assert.equal((workflow.match(/secrets\.GROK_AUTH_JSON/gu) ?? []).length, 1);
});
test("direct protocol concurrency override only lowers the configured ceiling", () => {