v1.91.186.0 fix(redact): pii.cc skips compact YYYYMMDDHHMMSS stamps so autoplan approval imports stop failing 1 in 10 (GSTA-66) (#3366)

* fix(redact): pii.cc skips a compact YYYYMMDDHHMMSS stamp, so an autoplan run id no longer refuses its approval row (GSTA-66)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.186.0 fix(redact): pii.cc skips compact YYYYMMDDHHMMSS stamps so autoplan approval imports stop failing 1 in 10 (GSTA-66) (#3366)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
Garry Tanandcapy-ai[bot] authored and GitHub committed 2026-10-24 14:04:54 +00:00
1 parent 6f7488a70f
commit 00100f1598
7 files changed
+53 -5

No files matched your search

+14
View File
@@ -1,5 +1,19 @@
# Changelog
## [1.91.186.0] - 2026-10-24
**Approving an autoplan run no longer fails one time in ten because its run id looks like a card number.** Today's daily flaky-fix pass found `test/capy-captain-flow.test.ts` failing once and passing on the serial retry in 7 of the 57 Free Tests runs from 2026-10-21 to 2026-10-23, one of them a push to main (39878113535). Every failure had the same assertion: `gstack-approvals import` refused the approval row with "field ask: pii.cc". The default autoplan run id is `run-YYYYMMDDHHMMSS`, the import writes it into the row's ask and source, and the credit-card rule saw those 14 digits as a card number whenever they passed the Luhn check, which a timestamp does about one time in ten. A real user's approval import failed the same way.
### Fixed
- **`lib/redact-patterns.ts`**: `pii.cc` skips a separator-free 14-digit span that reads as a valid YYYYMMDDHHMMSS stamp, using the `looksLikeCompactTimestamp` check that `pii.phone.e164` already uses. The only card numbers 14 digits long (Diners Club) start with 3, and an accepted stamp starts with 1 or 2 (years 1900–2999), so no real card loses coverage.
### Tests
- `test/approval-record.test.ts` imports an autoplan run whose run id `run-20261024131504` passes Luhn. It failed before the fix with the captain-flow error, and passes now.
- `test/redact-context-exemptions.test.ts` has a new `pii.cc` table. The ask, the source and a log line carrying a Luhn-valid stamp come back clean. These still report MEDIUM: a 14-digit Diners test number, a Luhn-valid 14-digit run that is not a date (month 13), a 15-digit stamp-prefixed run, the same stamp with spaces, and a 16-digit Visa test number.
### Gate integrity
- One accepted-input change to review: `pii.cc` no longer reports a separator-free 14-digit date-time stamp. The negative controls above are unchanged findings. No threshold, budget, timeout, trial count or case kind changed.
## [1.91.185.0] - 2026-10-23
**Three flaky paid eval cases get repairs: three harness gaps closed and one fixture rule moved to where the agent reads it.** Today's daily flaky-fix pass took the two repeat flakes and one periodic timeout from the flaky ledger. plan-design-with-ui-scope failed its first attempt in train gate 39852003387 (its fourth flake) because the Opus 5.5 agent rated the plan "4/10 on design" in plain words and the focus check wanted the words "design completeness". ship-docsync-completion failed in train gate 39904966815 and in GSTA-63's focused run with the same slip both times: the agent added `gstack-docs-candidate --help` to the end of its first line of reads, which the fixture interface forbids. plan-design-finding-floor timed out at 610 s in periodic run 39209106033 because nothing answered the owned plan-file Create menu after its title scrolled off screen; two focused trials then showed a second stall, at the Step 0D focus menu the floor actor answers only when it matches one captured wording.
+1 -1
View File
@@ -1 +1 @@
1.91.185.0
1.91.186.0
+1 -1
View File
@@ -1,4 +1,4 @@
# gstack digest v1.91.185.0 — regenerate/re-copy after upgrading gstack
# gstack digest v1.91.186.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,
+5 -2
View File
@@ -991,8 +991,11 @@ export const PATTERNS: RedactPattern[] = [
autoRedactable: true,
redactToken: "<REDACTED-CC>",
// A 13-19 digit slice of a digit-only UUID or of a decimal number passes
// Luhn often enough to matter; both context checks run before Luhn.
validate: (span, match) => !insideUuid(match) && !insideDecimalNumber(match) && luhnValid(span),
// Luhn often enough to matter, and so does a compact YYYYMMDDHHMMSS stamp
// (an autoplan run id); the only 14-digit cards start with 3, a stamp with
// 1 or 2. All three context checks run before Luhn.
validate: (span, match) =>
!insideUuid(match) && !insideDecimalNumber(match) && !looksLikeCompactTimestamp(span.replace(/[ -]$/, "")) && luhnValid(span),
},
{
id: "pii.ip_public",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "gstack",
"version": "1.91.185",
"version": "1.91.186",
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
"license": "MIT",
"type": "module",
+10
View File
@@ -135,6 +135,16 @@ describe('import --autoplan', () => {
expect(bin(['import', '--autoplan', run, '--by', 'Garry'], { cwd, env: { GSTACK_STATE_ROOT: state } }).out).toMatch(/^APPROVAL_IMPORTED: n=0 skipped=2 /);
});
test('a default run id whose YYYYMMDDHHMMSS stamp passes Luhn still imports (capy-captain-flow flake)', () => {
const run = tmp('appr-run-');
autoplanRun(run, [{ by: 'agent:GSTA-1', words: 'rec', at: '2026-10-24T13:15:04.000Z', p1: 'a' }]);
fs.writeFileSync(path.join(run, 'run.json'), JSON.stringify({ run: 'run-20261024131504', status: 'complete' }));
const rows = importAutoplan(run, 'b', 'Garry');
if ('code' in rows) throw new Error(rows.message);
expect(rows[0]!.ask).toContain('(autoplan run run-20261024131504, 2 decisions)');
expect(rows[0]!.source).toBe('autoplan:run-20261024131504@gate_rev=1');
});
test('an unanswered gate imports nothing and says why', () => {
const run = tmp('appr-run-');
fs.writeFileSync(path.join(run, 'decisions.jsonl'), JSON.stringify({ schema_version: 1, run: 'run-1', id: 'run-1-p1', label: 'P1', status: 'pending', gate_rev: 1 }) + '\n');
+21
View File
@@ -192,6 +192,27 @@ describe("db.url_with_password: postgres:postgres only on a loopback host (#2913
);
});
// Free Tests flaked test/capy-captain-flow.test.ts in 7 of 57 runs (2026-10-21..23): the autoplan run id
// run-YYYYMMDDHHMMSS put a 14-digit stamp in the approval row, and one stamp in ten passes Luhn.
describe("pii.cc: a separator-free YYYYMMDDHHMMSS stamp is not a card number", () => {
table(
"pii.cc",
"MEDIUM",
[
'Approve the plan "Retry backoff" (autoplan run run-20261024131504, 2 decisions)',
"autoplan:run-20261024131504@gate_rev=1",
"backup stamp 20261024131512 ran late",
],
[
"card 30569309025904",
"ref 20261324131501",
"stamp 202610241315045",
"card 2026 1024 1315 04",
"card 4111111111111111",
],
);
});
describe("pii.phone.e164: GitHub Actions run and job ids in their id positions", () => {
table(
"pii.phone.e164",