mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-03 01:46:55 +02:00
v1.91.7.0 feat: add functional QA and pre-publication docs checks (#2983)
* feat: add surface-aware exploratory QA and ship documentation gates * test: preserve delegated QA setup authority after main integration * fix(qa): clarify exploration order and preserve report artifacts * test(qa): follow the shared setup reference directly * refactor(ship): make verification and recovery routes explicit * test(ship): align evidence and review guards with explicit routes * fix(workflows): clarify ship recovery and functional QA evidence * fix(workflows): clarify approval recovery and full QA coverage * refactor(workflows): order review transactions and clarify ship state * fix(ship): clarify final verification and fail closed at publication * fix(evals): attribute native atomic documentation writes * fix(ship): clarify recovery and documentation lifecycle guidance * fix(test): preserve observed native placeholder styling in CI * fix(codex): report watchdog timeouts without a process-exit race * Checkpoint functional QA implementation and workflow validation repairs * Fix documentation and shared-review fixture contracts * docs: clarify judge reuse and evaluation supervision * test: align review evidence and selected case contracts * test: verify append-only documentation checkpoints and recovery * fix: qualify QA workflows and CI validation repairs * fix: launch shared-libs fixture scripts on Windows * fix: qualify QA deadlines, fixture isolation, and shard cleanup * fix: preserve qualified QA and cancellation repairs * fix: enforce functional fixture authority and share strict event decoding * fix: retain free-test evidence and explain recovery * fix: reject malformed native evidence after decoder consolidation * test: use reliable capture for telemetry privacy filters * test: refresh measured quick coverage and document validation costs * Fix native fixture receipts and preserve VM validation evidence * Align negative judge controls with upstream clarity policy * Fix report-only QA preparation and public evidence handling * Clarify QA-only preparation and current-report preservation * Stream Ship quality judgments with an explicit 64k response contract * Validate compact judge reasoning locally with supported wire schema * Align functional QA fixture instructions with evidence acceptance * Bind native browser diagnostics to execution evidence and align review verdicts * Preserve native diagnostic line boundaries * Serialize functional QA evidence from native captures * Keep large QA evidence fixture payload out of Windows argv
This commit is contained in:
1 parent
65bfb0ce49
commit
dcaea52800
333 files changed
+41755
-7357
No files matched your search
@@ -4,6 +4,9 @@ import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
import native from './fixtures/shared-libs-resolved-reads-public.json';
|
||||
import { E2E_TOUCHFILES, GLOBAL_TOUCHFILES, selectTests } from './helpers/touchfiles';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { createSharedLibsFixture, fixtureGit } from './helpers/shared-libs-eval-fixture';
|
||||
import { seedPathReviewPrerequisites, checkPathReviewPrerequisites, hasPathReviewPrerequisiteReceipt } from './helpers/shared-libs-path-fixture';
|
||||
|
||||
const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-shared-libs-paths.test.ts'), 'utf8');
|
||||
const detectorStart = source.indexOf('function sourceReadTrace(');
|
||||
@@ -20,9 +23,9 @@ const aliases = ['src/retry-route.ts', 'src/retry-alias/retry.ts'];
|
||||
const targets = ['.fixture/first-party/direct-route.ts', '.fixture/first-party/routes/retry.ts'];
|
||||
|
||||
function fixture() {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-resolved-read-'));
|
||||
const f = createSharedLibsFixture('resolved-read');
|
||||
const { root, repo } = f;
|
||||
roots.push(root);
|
||||
const repo = path.join(root, 'repo');
|
||||
for (const file of ['src/retry-worker.ts', 'lib/retry-after.ts', ...targets]) {
|
||||
const body = nativeRead.content.split(`=== ${file} ===\n`)[1]?.split('\n=== ')[0];
|
||||
if (!body) throw new Error(`Missing native file contents: ${file}`);
|
||||
@@ -31,7 +34,7 @@ function fixture() {
|
||||
}
|
||||
fs.symlinkSync('../.fixture/first-party/direct-route.ts', path.join(repo, aliases[0]));
|
||||
fs.symlinkSync('../.fixture/first-party/routes', path.join(repo, 'src/retry-alias'));
|
||||
return { root, repo, state: path.join(root, 'state'), bin: path.join(root, 'bin') };
|
||||
return f;
|
||||
}
|
||||
|
||||
function capture() {
|
||||
@@ -45,6 +48,59 @@ function capture() {
|
||||
toolCalls: tools.map(tool => ({ tool: tool.name, input: tool.input, output: '' })) };
|
||||
}
|
||||
|
||||
test('fixture Git and child commands share a platform-safe empty global config', () => {
|
||||
const f = createSharedLibsFixture('git-config');
|
||||
roots.push(f.root);
|
||||
const config = f.env.GIT_CONFIG_GLOBAL;
|
||||
if (process.platform === 'win32') {
|
||||
expect(fs.statSync(config).isFile()).toBe(true);
|
||||
expect(path.dirname(fs.realpathSync(config))).toBe(fs.realpathSync(f.root));
|
||||
} else {
|
||||
expect(config).toBe(os.devNull);
|
||||
expect(fs.existsSync(path.join(f.root, 'gitconfig'))).toBe(false);
|
||||
}
|
||||
expect(fs.readFileSync(config, 'utf8')).toBe('');
|
||||
expect(f.env.GIT_CONFIG_NOSYSTEM).toBe('1');
|
||||
expect(fixtureGit(f, 'config', '--global', '--list')).toBe('');
|
||||
expect(fixtureGit(f, 'config', '--local', '--get', 'user.name')).toBe('Shared Libs Fixture');
|
||||
expect(fixtureGit(f, 'rev-parse', 'HEAD')).toBe(f.tip);
|
||||
const args = ['config', '--global', '--show-origin', '--list'];
|
||||
expect(execFileSync(Bun.which('git') || 'git', args, {
|
||||
cwd: f.repo, env: { ...process.env, ...f.env }, encoding: 'utf8', timeout: 10_000,
|
||||
}).trim()).toBe('');
|
||||
if (process.platform === 'win32') {
|
||||
fs.writeFileSync(config, '[fixture]\n\tconfig = owned\n');
|
||||
expect(fixtureGit(f, 'config', '--global', '--get', 'fixture.config')).toBe('owned');
|
||||
expect(execFileSync(Bun.which('git') || 'git', args, {
|
||||
cwd: f.repo, env: { ...process.env, ...f.env }, encoding: 'utf8', timeout: 10_000,
|
||||
}).trim()).toContain('fixture.config=owned');
|
||||
}
|
||||
});
|
||||
|
||||
test.each(['win32', 'linux', 'darwin'])('worktree fingerprint launches its Bash script on %s', platform => {
|
||||
const helper = fs.readFileSync(path.join(import.meta.dir, 'helpers/shared-libs-eval-fixture.ts'), 'utf8');
|
||||
const start = helper.indexOf('export function fixtureWorkingTree(');
|
||||
const end = helper.indexOf('\nexport async function runSharedCapture(', start);
|
||||
expect(start).toBeGreaterThan(0);
|
||||
expect(end).toBeGreaterThan(start);
|
||||
const calls: any[] = [];
|
||||
const paths = platform === 'win32' ? path.win32 : path.posix;
|
||||
const root = platform === 'win32' ? 'C:\\fixture root\\gstack' : '/fixture root/gstack';
|
||||
const script = paths.join(root, 'bin/gstack-wtree');
|
||||
const launch = new Function('execFileSync', 'path', 'SHARED_LIBS_ROOT', 'process',
|
||||
`${transpiler.transformSync(helper.slice(start, end).replace('export function', 'function'))}; return fixtureWorkingTree;`)(
|
||||
(command: string, args: string[], options: any) => { calls.push({ command, args, options }); return 'tree-hash\n'; },
|
||||
paths, root, { platform, env: { PATH: 'host-path', HOME: 'host-home' } });
|
||||
const f = { repo: paths.join(root, 'repo'), env: { GSTACK_HOME: 'isolated-state', PATH: 'fixture-path' } };
|
||||
expect(launch(f)).toBe('tree-hash');
|
||||
expect(calls).toEqual([{
|
||||
command: platform === 'win32' ? 'bash' : script,
|
||||
args: platform === 'win32' ? [script] : [],
|
||||
options: { cwd: f.repo, encoding: 'utf8', timeout: 30_000,
|
||||
env: { PATH: 'host-path', HOME: 'host-home', GSTACK_HOME: 'isolated-state' } },
|
||||
}]);
|
||||
});
|
||||
|
||||
test('the retained native resolved-path read proves both current authored callers', () => {
|
||||
const f = fixture();
|
||||
const result = capture();
|
||||
@@ -123,6 +179,46 @@ test.each(['Read', 'Bash'])('direct alias reads retain the existing %s contract'
|
||||
expect(detect(result, f, aliases)).toContain(aliases[0]);
|
||||
});
|
||||
|
||||
test.each(['valid', 'missing-result', 'failed-result', 'wrong-result-id', 'metadata-only', 'stale-content',
|
||||
'assistant-only', 'suffix', 'foreign-root', 'outside-target'])('Windows native-path replay preserves read evidence: %s', kind => {
|
||||
const f = fixture();
|
||||
const windowsRoot = 'C:\\shared-libs-fixture';
|
||||
const nativePath = (file: string) => path.resolve(f.root, ...path.win32.relative(windowsRoot, file).split('\\'));
|
||||
const windowsFs = {
|
||||
realpathSync: (file: string) => path.win32.resolve(windowsRoot, path.relative(f.root, fs.realpathSync(nativePath(file)))),
|
||||
readFileSync: (file: string, encoding: BufferEncoding) => fs.readFileSync(nativePath(file), encoding),
|
||||
};
|
||||
const windowsDetect = new Function('fs', 'path', `${transpiler.transformSync(source.slice(detectorStart, callbackStart))}; return sourceReadTrace;`)(windowsFs, path.win32);
|
||||
const result: any = capture();
|
||||
const event = result.events.find((row: any) => row.message.content[0].tool_use_id === readId);
|
||||
const block = event.message.content[0];
|
||||
if (kind === 'missing-result') result.events = result.events.filter((row: any) => row !== event);
|
||||
if (kind === 'failed-result') block.is_error = true;
|
||||
if (kind === 'wrong-result-id') block.tool_use_id = 'unrelated';
|
||||
if (kind === 'metadata-only') block.content = 'Both target files exist and are 738 bytes.';
|
||||
if (kind === 'stale-content') block.content = block.content.replaceAll('// Authored caller changed after the prior decision (symlinks).', '');
|
||||
if (kind === 'assistant-only') event.type = 'assistant';
|
||||
if (kind === 'suffix' || kind === 'foreign-root') {
|
||||
const tool = result.events.flatMap((row: any) => row.message.content).find((row: any) => row.id === readId);
|
||||
for (const target of targets) tool.input.command = tool.input.command.replaceAll(target,
|
||||
kind === 'suffix' ? `${target}.backup` : `/foreign-root/${target}`);
|
||||
}
|
||||
if (kind === 'outside-target') {
|
||||
const outside = path.join(f.root, 'outside.ts');
|
||||
fs.writeFileSync(outside, fs.readFileSync(path.join(f.repo, targets[0])));
|
||||
fs.unlinkSync(path.join(f.repo, aliases[0]));
|
||||
fs.symlinkSync(outside, path.join(f.repo, aliases[0]));
|
||||
const tool = result.events.flatMap((row: any) => row.message.content).find((row: any) => row.id === readId);
|
||||
tool.input.command = tool.input.command.replaceAll(targets[0], 'C:/shared-libs-fixture/outside.ts');
|
||||
}
|
||||
const reads = windowsDetect(result, { repo: path.win32.join(windowsRoot, 'repo') }, aliases);
|
||||
if (kind === 'valid') for (const alias of aliases) expect(reads).toContain(alias);
|
||||
else if (kind === 'outside-target') {
|
||||
expect(reads).not.toContain(aliases[0]);
|
||||
expect(reads).toContain(aliases[1]);
|
||||
} else for (const alias of aliases) expect(reads).not.toContain(alias);
|
||||
});
|
||||
|
||||
test.each(['test/shared-libs-source-reads.test.ts', 'test/fixtures/shared-libs-resolved-reads-public.json'])('%s selects every owning path callback without a global fallback', file => {
|
||||
expect(selectTests([file], E2E_TOUCHFILES, GLOBAL_TOUCHFILES).selected.sort()).toEqual([
|
||||
'shared-libs-review-index-flags', 'shared-libs-review-path-eligibility', 'shared-libs-review-prior-coverage',
|
||||
@@ -133,20 +229,32 @@ test.each([false, true])('the actual eligibility callback consumes the read dete
|
||||
const f = fixture();
|
||||
const result: any = capture();
|
||||
if (missingOutput) result.events = result.events.filter((event: any) => event.message.content[0].tool_use_id !== readId);
|
||||
const resumed = seedPathReviewPrerequisites(f);
|
||||
const prerequisiteOutput = execFileSync('bash', ['-c', resumed.checkCommand], {
|
||||
cwd: f.repo, env: { ...process.env, ...f.env }, encoding: 'utf8', timeout: 30_000,
|
||||
});
|
||||
const finish = result.events.findIndex((event: any) => event.type === 'assistant'
|
||||
&& event.message.content.some((block: any) => block.input?.command?.includes('--finish')));
|
||||
expect(finish).toBeGreaterThan(0);
|
||||
result.events.splice(finish, 0,
|
||||
{ type: 'assistant', message: { content: [{ type: 'tool_use', name: 'Bash', id: 'prerequisites', input: { command: resumed.checkCommand } }] } },
|
||||
{ type: 'user', message: { content: [{ type: 'tool_result', tool_use_id: 'prerequisites', content: prerequisiteOutput }] } });
|
||||
const rows: any[] = [];
|
||||
let detectorCalls = 0;
|
||||
const exercise = new Function('deps', `const { captures, preparePathEligibilityFixture, fs, path,
|
||||
reviewLifecycleInstructions, reviewRevalidationPrompt, runSharedInteractive, readRequests,
|
||||
toolCommandTrace, sourceReadTrace, fixtureWorkingTree, reviewRecords, expect, CAPTURE_LONG_MS } = deps;
|
||||
toolCommandTrace, sourceReadTrace, fixtureWorkingTree, reviewRecords, expect, CAPTURE_LONG_MS,
|
||||
checkPathReviewPrerequisites, hasPathReviewPrerequisiteReceipt } = deps;
|
||||
${transpiler.transformSync(source.slice(callbackStart, callbackEnd))}; return exerciseEligibility;`)({
|
||||
captures: { runAttempt: (_name: string, _kinds: string[], _timeout: number, work: any) => work({ add: (_kind: string, row: any) => rows.push(row) }) },
|
||||
preparePathEligibilityFixture: () => ({ fixture: f, sourcePaths: aliases, beforeTree: 'tree', current: { evidence_paths: ['src/retry-worker.ts', 'lib/retry-after.ts', ...aliases] } }),
|
||||
preparePathEligibilityFixture: () => ({ fixture: f, resumed, sourcePaths: aliases, beforeTree: 'tree', current: { evidence_paths: ['src/retry-worker.ts', 'lib/retry-after.ts', ...aliases] } }),
|
||||
fs, path, expect, CAPTURE_LONG_MS: 600_000,
|
||||
reviewLifecycleInstructions: () => 'read the authored sources', reviewRevalidationPrompt: () => 'revalidate',
|
||||
runSharedInteractive: async () => ({ result, questions: [{}] }), readRequests: () => [],
|
||||
toolCommandTrace: (value: any) => value.toolCalls.filter((call: any) => call.tool === 'Bash').map((call: any) => call.input.command),
|
||||
sourceReadTrace: (...args: any[]) => { detectorCalls++; return detect(...args); },
|
||||
fixtureWorkingTree: () => 'tree',
|
||||
checkPathReviewPrerequisites, hasPathReviewPrerequisiteReceipt,
|
||||
reviewRecords: () => [{ skill: 'review' }, { skill: 'review', status: 'clean', issues_found: 0, completed: true, converged: true,
|
||||
review_binding: { state: 'verified' }, findings: [{ advisory: true, action: 'skipped', helper_target: { path: 'lib/retry-after.ts', symbol: 'retrySeconds' },
|
||||
fingerprint: `shared-libs:${'a'.repeat(64)}`, evidence_paths: ['src/retry-worker.ts', ...aliases], snapshot_covered_paths: ['src/retry-worker.ts', 'lib/retry-after.ts'] }] }],
|
||||
|
||||
Reference in new issue
Block a user