From 1e798cd986c2aeedaf4c9f35b92cbe002871ad44 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sun, 18 Oct 2026 16:56:46 -0700 Subject: [PATCH] v1.91.140.0 fix(cso-eval): producer accepts dependency-closure names with the helper's 32-hex finding IDs (#3278) * fix(cso-eval): producer accepts dependency-closure names with the helper's 32-hex finding IDs * v1.91.140.0 fix(cso-eval): producer accepts dependency-closure names with the helper's 32-hex finding IDs --- CHANGELOG.md | 7 +++++++ VERSION | 2 +- agents-digest/gstack-AGENTS.md | 2 +- package.json | 2 +- scripts/cso-eval-producer.ts | 2 +- test/cso-eval.test.ts | 4 ++++ 6 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f23ffbb26..dedc67352 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.91.140.0] - 2026-10-18 + +**/cso evaluation cells that run a repair no longer fail on helper dependency-closure names that use the helper's own 32-character finding IDs.** In the third paid runtime qualification, one comprehensive cell failed with REDACTION_FAILED again, on `dependency-closures/-after-.json`. 1.91.135.0 taught the producer this name shape with a 64-character finding ID. The helper actually names closures with its 32-character finding IDs, so real names still fell through to the secret redactor, which reads some of them as wallet addresses. + +### Fixed +- **The eval producer recognizes dependency-closure names with 32- or 64-character finding IDs.** Any other word in the phase position still goes through the redactor. The test now uses a real-length, redactor-flagged 32-character name and fails on the 1.91.135.0 pattern. + ## [1.91.139.0] - 2026-10-18 **The docs-sync fixture's declared Git interface now includes read-only `git describe`, so `ship-docsync-store` no longer goes red when the /document-release child checks for release tags.** PR #3272's gate run 39153452209 failed that case on one command, `git describe --tags --always`, which the observer did not list. A focused paid rerun of `ship-docsync-store` on this tree passed ($3.83); the child ran the same command twice and the observer accepted it. diff --git a/VERSION b/VERSION index 46ba4c6df..bd17523e6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.91.139.0 +1.91.140.0 diff --git a/agents-digest/gstack-AGENTS.md b/agents-digest/gstack-AGENTS.md index 1c453e835..cabf876b8 100644 --- a/agents-digest/gstack-AGENTS.md +++ b/agents-digest/gstack-AGENTS.md @@ -1,4 +1,4 @@ -# gstack digest v1.91.139.0 — regenerate/re-copy after upgrading gstack +# gstack digest v1.91.140.0 — regenerate/re-copy after upgrading gstack Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed for agent hosts without a full skill install. The full skills add workflows, diff --git a/package.json b/package.json index 6efc1a9fa..39b5c15e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.91.139", + "version": "1.91.140", "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.", "license": "MIT", "type": "module", diff --git a/scripts/cso-eval-producer.ts b/scripts/cso-eval-producer.ts index 375f3eb68..d06c841e8 100644 --- a/scripts/cso-eval-producer.ts +++ b/scripts/cso-eval-producer.ts @@ -180,7 +180,7 @@ function emptyArtifactInventory(): ProducerArtifactInventory { } /** A whole path component that is one of the helper's own identifiers: `-` run and replay IDs, retired runs, hex artifact IDs with an optional lowercase-word prefix (`gitleaks--.json`), and dependency-closure files (`-before|after-.json`). */ -const HELPER_ID_COMPONENT = /^(?:\d{13}-[a-f0-9]{16}|\.retired-\d{13}-[a-f0-9]{16}-[a-f0-9]{32}|(?:[a-z]+-)*[a-f0-9]{16,64}(?:-[a-f0-9]{16})*(?:\.[a-z]+)?|[a-f0-9]{64}-(?:before|after)-[a-f0-9]{16}\.json)$/; +const HELPER_ID_COMPONENT = /^(?:\d{13}-[a-f0-9]{16}|\.retired-\d{13}-[a-f0-9]{16}-[a-f0-9]{32}|(?:[a-z]+-)*[a-f0-9]{16,64}(?:-[a-f0-9]{16})*(?:\.[a-z]+)?|(?:[a-f0-9]{32}){1,2}-(?:before|after)-[a-f0-9]{16}\.json)$/; /** * Helper artifact paths are `//...` plus the helper's public-cache/ and legacy-imports/. Components that diff --git a/test/cso-eval.test.ts b/test/cso-eval.test.ts index b64390551..9e01b2501 100644 --- a/test/cso-eval.test.ts +++ b/test/cso-eval.test.ts @@ -1218,8 +1218,11 @@ describe('CSO matched producer orchestration', () => { const repo = 'e'.repeat(24); let closure = ''; while (!closure) { const name = `${randomHex(32)}-before-${randomHex(8)}.json`; if (redact(name) !== name) closure = name; } + let helperFindingClosure = ''; + while (!helperFindingClosure) { const name = `${randomHex(16)}-after-${randomHex(8)}.json`; if (redact(name) !== name) helperFindingClosure = name; } const accepted = [`${repo}/${runId}/report.json`, `${repo}/${runId}/reviews/${walletShaped}.json`, `${repo}/${runId}/scanner-outcomes/gitleaks-${randomHex(8)}-${randomHex(8)}.json`, `${repo}/${runId}/dependency-closures/${closure}`, `${repo}/${runId}/dependency-closures/${closure.replace('-before-', '-after-')}`, + `${repo}/${runId}/dependency-closures/${helperFindingClosure}`, `${repo}/${runId}/dependency-closures/${helperFindingClosure.replace('-after-', '-before-')}`, `${repo}/${runId}/snapshot/test/fixtures/cso-canary-token.txt`, 'public-cache/osv/index.json']; for (const path of accepted) expect(() => assertProducerArtifactPath(path)).not.toThrow(); for (const [path, message] of [ @@ -1228,6 +1231,7 @@ describe('CSO matched producer orchestration', () => { [`${repo}/${runId}/bad name.json`, 'INVALID_PRODUCER_ARTIFACTS: an artifact path has a component outside'], ] as const) expect(() => assertProducerArtifactPath(path)).toThrow(message); expect(() => assertProducerArtifactPath(`${repo}/${runId}/dependency-closures/${closure.replace('-before-', '-during-')}`)).toThrow('looks like a secret'); + expect(() => assertProducerArtifactPath(`${repo}/${runId}/dependency-closures/${helperFindingClosure.replace('-after-', '-during-')}`)).toThrow('looks like a secret'); const planted = `sk-ant-api03-${randomHex(24)}`; expect(redact(planted)).not.toBe(planted); let failure: unknown;