v1.90.0.0 feat: make browser cookie imports explicit and safe (#2964)

* fix(browse): prepare reliable cookie import wave for validation

* ci: sequence quality and behavior for validation branch

* fix(browse): isolate Windows qualification and preserve native diagnostics

* test(browse): cover cookie workflow quality and isolate Windows user paths

* test(browse): trace native member startup and initialize fresh folders

* fix(browse): keep Windows member stdin alive through EOF

* fix(browse): latch native timeouts and compare contained Edge startup

* test(browse): verify native version metadata and actual Windows argv

* test(browse): qualify Dia import on isolated macOS CI

* fix(browse): require picker origin for session mutations

* fix(browse): bound credential reads through stream completion

* test(browse): inspect owned Windows process arguments natively

* test(evals): preserve passing coverage during cookie repair reruns

* test(browse): isolate Dia qualification in a fresh macOS account

* test(browse): pass bounded integer timeouts to native Mac probes

* test(browse): distinguish Windows profile initialization from containment

* test(browse): await descendant pipe readiness before parent exit

* test(browse): initialize and restore isolated macOS Keychain state

* test(browse): initialize Windows fixture folders before qualification

* test(ci): pin the same Node runtime across Windows checks

* test(browse): distinguish native macOS browser preflight stages

* test(browse): isolate Windows descendant console lifetime

* test(browse): preserve native receipts and identify fixture lock holders

* test(browse): prepare dependency resolution before native Mac worker startup

* test(ci): include lock and close checks in native diagnostics

* test(browse): preserve native owner probe stages and subprocess deadlines

* fix(browse): classify Chromium profile-in-use exit precisely

* test(browse): retain Mac qualification evidence through cleanup failures

* test(browse): bound Mac fixture paths and retire its owned user domain

* test(browse): accept vanished fixture entries without weakening cleanup

* test(browse): identify probe-created macOS user domains safely

* test(browse): observe Mac user domains without targeting them first

* test(browse): use passive fresh-user ownership throughout Mac qualification

* test(browse): distinguish profile and registered-home Keychain lookups

* test(browse): qualify Dia under one registered account home

* test(browse): identify Dia startup and owned process-group failures

* test(browse): classify bounded Dia startup diagnostics without leaking output

* fix(test): preserve native Mac sandboxing and reap owned browser children

* fix(browse): preserve Chromium sandboxing for native profile imports

* test(browse): inspect signed Mach-O architecture without launching Xcode tools

* test(browse): sample pending Dia startup and reap on all cleanup paths

* test(browse): compare protected Dia launches in fresh Bun and Node accounts

* test(browse): inspect isolated Mac GUI readiness without browser access

* v1.90.0.0 fix: bind cookie picker actions to their document

* test: validate cookie guards and fit nested launch fixtures

* ci: configure the bundled Chromium sandbox helper

* fix(browse): classify Playwright authentication timeouts

* test: retain bounded Windows lifecycle diagnostics

* test(cso): reuse bounded NTFS precision candidates

* test(review): handle explicit preservation choices safely

* test(browse): remove owned fixture directories with explicit primitives

* test(review): distinguish descriptive reuse from edit commitments

* test: admit only the approved unscored cookie workflow refusal

* test: keep the Office Hours judge mock export-complete

* fix: keep dependency-free CI planners independent of the model SDK

* test: observe the exact holder after a native fixture unlink failure

* fix: start seeded PTY observations at owned readiness

* test: acquire identity-bound Windows deletion admission before profile resets

* test: preserve qualified Git index bits without authorizing mutations
This commit is contained in:
Garry Tan
2026-09-25 12:06:45 -04:00
committed by GitHub
parent 730a1017d1
commit a84b0b5b6d
111 changed files with 14996 additions and 1057 deletions
+103
View File
@@ -0,0 +1,103 @@
import { afterEach, expect, test } from 'bun:test';
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { buildCookieWorkflowJudgeInput, COOKIE_WORKFLOW_JUDGE } from './helpers/cookie-workflow-judge-input';
import { COOKIE_MANUAL_REVIEW_FILE, getCookieWorkflowManualReview, isManualReviewEntry, manualReviewProblem } from './helpers/cookie-workflow-manual-review';
import { manualReviewFixture } from './helpers/manual-judge-review-fixture';
import { validWorkflowJudgeScore } from './helpers/workflow-judge-cache';
const ROOT = resolve(import.meta.dir, '..');
const roots: string[] = [];
afterEach(() => { for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true }); });
function fixture() {
const root = mkdtempSync(join(tmpdir(), 'cookie-policy-')); roots.push(root);
for (const file of [COOKIE_MANUAL_REVIEW_FILE, 'setup-browser-cookies/SKILL.md', 'BROWSER.md']) {
const target = join(root, file); mkdirSync(resolve(target, '..'), { recursive: true });
writeFileSync(target, readFileSync(join(ROOT, file)));
}
const entry = manualReviewFixture(root);
const approval = entry.manual_review!.approval;
const request = { testName: entry.name, prompt: entry.prompt!, model: entry.model!,
maxTokens: approval.max_tokens, thresholds: { ...approval.thresholds }, attempt: 1 };
return { root, entry, approval, request, refusal: entry.manual_review!.refusal };
}
test('the committed approval names precisely the complete reviewed request, not a numerical score', () => {
const f = fixture();
expect(buildCookieWorkflowJudgeInput(ROOT).sha256).toBe(f.approval.prompt_sha256);
expect(f.approval.thresholds).toEqual(COOKIE_WORKFLOW_JUDGE.thresholds);
expect(isManualReviewEntry(f.entry)).toBe(true);
expect(manualReviewProblem(f.entry, ROOT)).toBeNull();
expect(getCookieWorkflowManualReview(f.root, f.request, f.refusal)).toEqual(f.entry.manual_review);
expect(validWorkflowJudgeScore(f.entry as any, f.request.thresholds)).toBe(false);
expect(validWorkflowJudgeScore(f.entry.manual_review as any, f.request.thresholds)).toBe(false);
});
test.each(['case', 'prompt', 'model', 'budget', 'thresholds', 'source', 'approval', 'retry'])(
'admission rejects mismatched %s without changing the approval', mismatch => {
const f = fixture(); const original = readFileSync(join(f.root, COOKIE_MANUAL_REVIEW_FILE), 'utf8');
if (mismatch === 'case') f.request.testName = 'ship/SKILL.md workflow';
if (mismatch === 'prompt') f.request.prompt += '\n';
if (mismatch === 'model') f.request.model += '-other';
if (mismatch === 'budget') f.request.maxTokens++;
if (mismatch === 'thresholds') f.request.thresholds.clarity++;
if (mismatch === 'retry') f.request.attempt++;
if (mismatch === 'source') writeFileSync(join(f.root, 'BROWSER.md'), readFileSync(join(f.root, 'BROWSER.md'), 'utf8').replace('Storage stays intact', 'Changed storage stays intact'));
if (mismatch === 'approval') writeFileSync(join(f.root, COOKIE_MANUAL_REVIEW_FILE), JSON.stringify({ ...f.approval, prompt_sha256: 'a'.repeat(64) }));
expect(getCookieWorkflowManualReview(f.root, f.request, f.refusal)).toBeNull();
if (mismatch !== 'approval') expect(readFileSync(join(f.root, COOKIE_MANUAL_REVIEW_FILE), 'utf8')).toBe(original);
});
test.each(['passed', 'scores', 'reused', 'timeout', 'case', 'suite', 'prompt', 'model', 'refusal', 'missing-id', 'missing-response-id', 'output', 'text', 'tokens', 'schema', 'retry'])(
'malformed manual receipt %s cannot count as acceptance', invalid => {
const f = fixture(); const entry: any = f.entry;
if (invalid === 'passed') entry.passed = true;
if (invalid === 'retry') entry.attempt++;
if (invalid === 'scores') entry.judge_scores = { clarity: 1 };
if (invalid === 'reused') entry.execution = 'reused';
if (invalid === 'timeout') entry.exit_reason = 'timeout';
if (invalid === 'case') entry.name = 'ship/SKILL.md workflow';
if (invalid === 'suite') entry.suite = 'Unrelated suite';
if (invalid === 'prompt') entry.prompt += '\n';
if (invalid === 'model') entry.model = 'another-model';
if (invalid === 'refusal') entry.manual_review.refusal.stop_reason = 'end_turn';
if (invalid === 'missing-id') entry.manual_review.refusal.request_id = null;
if (invalid === 'missing-response-id') entry.manual_review.refusal.response_id = null;
if (invalid === 'output') entry.manual_review.refusal.output_tokens = 1;
if (invalid === 'text') entry.manual_review.refusal.text_blocks = 1;
if (invalid === 'tokens') entry.manual_review.refusal.input_tokens = -1;
if (invalid === 'schema') entry.manual_review.approval.schema_version = 2;
expect(isManualReviewEntry(entry)).toBe(false);
expect(manualReviewProblem(entry, f.root)).not.toBeNull();
});
test('reconciliation rejects changed source, approval provenance, missing approval and corrupt JSON', () => {
const f = fixture();
const modified = structuredClone(f.entry);
modified.manual_review!.approval.approved_by = 'unapproved-reviewer';
expect(manualReviewProblem(modified, f.root)).not.toBeNull();
const file = join(f.root, COOKIE_MANUAL_REVIEW_FILE);
writeFileSync(file, '{');
expect(manualReviewProblem(f.entry, f.root)).not.toBeNull();
rmSync(file);
expect(manualReviewProblem(f.entry, f.root)).not.toBeNull();
writeFileSync(file, JSON.stringify(f.approval));
writeFileSync(join(f.root, 'BROWSER.md'), readFileSync(join(f.root, 'BROWSER.md'), 'utf8').replace('Storage stays intact', 'Changed storage stays intact'));
expect(manualReviewProblem(f.entry, f.root)).not.toBeNull();
expect(isManualReviewEntry(f.entry)).toBe(true);
});
test('a current judge-model override cannot reuse the different approved model', () => {
const f = fixture();
const original = process.env.GSTACK_EVAL_MODEL_JUDGE;
try {
process.env.GSTACK_EVAL_MODEL_JUDGE = 'synthetic-unapproved-model';
expect(manualReviewProblem(f.entry, f.root)).toBe('Manual review model is not the current judge model');
expect(isManualReviewEntry(f.entry)).toBe(true);
} finally {
if (original === undefined) delete process.env.GSTACK_EVAL_MODEL_JUDGE;
else process.env.GSTACK_EVAL_MODEL_JUDGE = original;
}
});