Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e04a0bc
harness: bootstrap run test-e2e-sqlite-runtime-tier--1158 for #1158
rickylabs Aug 4, 2026
dd178da
harness: record PLAN-EVAL PASS for run test-e2e-sqlite-runtime-tier--…
rickylabs Aug 4, 2026
8d75809
harness: brief S1 for run test-e2e-sqlite-runtime-tier--1158
rickylabs Aug 4, 2026
76f3741
harness: rescope S1 to the permission-bearing generators (drift D-5)
rickylabs Aug 4, 2026
f012f01
fix(cli): sqlite --allow-ffi reaches background processors and plugin…
rickylabs Aug 4, 2026
d06e7c9
harness: sign off S1 — sqlite FFI permission reaches every generator …
rickylabs Aug 4, 2026
8d96057
feat(cli): e2e can scaffold a generated project with no cache resource
rickylabs Aug 4, 2026
47caa6b
harness: sign off S2 — the e2e can scaffold a project with no cache r…
rickylabs Aug 4, 2026
945f926
test(cli): capability suite defaults yield to CLI overrides
rickylabs Aug 4, 2026
d7460d7
harness: sign off S3 — a capability suite pins its own defaults while…
rickylabs Aug 4, 2026
a803ec3
harness: supervisor sign-off for S3, and record the self-certificatio…
rickylabs Aug 4, 2026
9982421
harness: record the owner-authorized adversarial-check lane (drift D-8)
rickylabs Aug 4, 2026
d5ba720
harness: prefer an Opus 5 sub-agent before the OpenRouter lanes (drif…
rickylabs Aug 4, 2026
b0c6ef8
test(cli): finalize sqlite runtime suite profile
rickylabs Aug 4, 2026
8e78dee
fix(cli): the sqlite runtime tier contends for the expensive-suite lease
rickylabs Aug 4, 2026
07f82d6
harness: sign off S4 + S4a — the sqlite runtime tier exists and conte…
rickylabs Aug 4, 2026
65988b4
fix(cli): tolerate missing Docker during E2E cleanup
rickylabs Aug 4, 2026
1335ab2
harness: sign off S5 — cleanup survives a host with no Docker
rickylabs Aug 4, 2026
fafbe2b
test(ci): run sqlite runtime tier under classifier policy
rickylabs Aug 4, 2026
6728529
fix(ci): the sqlite tier explains why it was skipped
rickylabs Aug 4, 2026
42c7377
harness: sign off S6 + S6a — CI runs the cheap tier and explains its …
rickylabs Aug 4, 2026
51e6b08
test(cli): finish reduced-container sqlite runtime
rickylabs Aug 4, 2026
02d9ae9
harness: sign off S7 — the sqlite tier is green, with an honest reduc…
rickylabs Aug 4, 2026
6dacb97
harness: record D-16 — postgres merge bar failed at behavior.service-…
rickylabs Aug 4, 2026
bdf8e80
harness: close the IMPL-EVAL FAIL_DEBT items and file the health-chec…
rickylabs Aug 4, 2026
ad05fb1
harness: resolve D-16 — the postgres merge-bar failure is pre-existin…
rickylabs Aug 4, 2026
c7557e6
harness: close the run — implementation complete, IMPL-EVAL PASS
rickylabs Aug 4, 2026
1a2c8cf
harness: correct D-16 — same-host A/B rules out the code delta, not t…
rickylabs Aug 4, 2026
34c535c
Merge origin/main into test/e2e-sqlite-runtime-tier-1158
rickylabs Aug 4, 2026
31c08f3
harness: record D-18 — cloud CI green, but the compute saving needs #…
rickylabs Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@
# release gates (publish / e2e-cli-prod*).
- name: "ci:full"
color: "d4c5f9"
description: "Force both expensive e2e-cli jobs to run (overrides docs-only + skip labels)"
description: "Force all expensive e2e-cli jobs to run (overrides docs-only + skip labels)"
- name: "ci:skip-e2e"
color: "d4c5f9"
description: "Skip the scaffold-runtime (aspire/docker/postgres) e2e job"
description: "Skip both scaffold-runtime e2e tiers (sqlite and aspire/docker/postgres)"
- name: "ci:skip-scaffold"
color: "d4c5f9"
description: "Skip the scaffold-static (deno-only) scaffold gate"
Expand Down
153 changes: 153 additions & 0 deletions .github/scripts/ci-classify-changes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ function vector(d: Decision) {
const ALL_TRUE = { deno: true, docker: true, desktop: true, docs: true, surface: true };
const ALL_FALSE = { deno: false, docker: false, desktop: false, docs: false, surface: false };

function workflowJob(source: string, id: string): string | undefined {
const lines = source.split('\n');
const start = lines.indexOf(` ${id}:`);
if (start < 0) return undefined;
let end = lines.length;
for (let index = start + 1; index < lines.length; index++) {
if (/^ {2}[a-z][a-z0-9-]*:$/.test(lines[index])) {
end = index;
break;
}
}
return lines.slice(start + 1, end).join('\n');
}

// ── rename-hole regression (adversarial review, defect 1) ────────────────────

Deno.test('regression: packages/cli/a.ts -> docs/a.md rename is NOT docs-only', () => {
Expand Down Expand Up @@ -184,6 +198,7 @@ Deno.test('SAFETY: an unrecognised path forces EVERY output true', () => {
}, `expected full escalation for: ${p}`);
const d = decide({ eventName: 'pull_request', files: [p], labels: [] });
assertEquals(d.runStatic, true, p);
assertEquals(d.runRuntimeSqlite, true, p);
assertEquals(d.runRuntime, true, p);
assertEquals(vector(d), ALL_TRUE, p);
}
Expand All @@ -196,6 +211,7 @@ Deno.test('SAFETY: the classifier own sources force everything (.github/scripts)
labels: [],
});
assertEquals(d.runStatic, true);
assertEquals(d.runRuntimeSqlite, true);
assertEquals(d.runRuntime, true);
assertEquals(vector(d), ALL_TRUE);
});
Expand Down Expand Up @@ -446,6 +462,7 @@ Deno.test('decide: docs-only PR skips both jobs', () => {
});
assertEquals(d.docsOnly, true);
assertEquals(d.runStatic, false);
assertEquals(d.runRuntimeSqlite, false);
assertEquals(d.runRuntime, false);
});

Expand Down Expand Up @@ -490,13 +507,15 @@ Deno.test('decide: one code file forces both jobs', () => {
});
assertEquals(d.docsOnly, false);
assertEquals(d.runStatic, true);
assertEquals(d.runRuntimeSqlite, true);
assertEquals(d.runRuntime, true);
});

Deno.test('decide: empty diff runs EVERYTHING (cannot classify)', () => {
const d = decide({ eventName: 'pull_request', files: [], labels: [] });
assertEquals(d.docsOnly, false);
assertEquals(d.runStatic, true);
assertEquals(d.runRuntimeSqlite, true);
assertEquals(d.runRuntime, true);
assertEquals(vector(d), ALL_TRUE);
});
Expand All @@ -508,7 +527,12 @@ Deno.test('decide: ci:skip-e2e skips runtime only', () => {
labels: ['ci:skip-e2e'],
});
assertEquals(d.runStatic, true);
assertEquals(d.runRuntimeSqlite, false);
assertEquals(d.runRuntime, false);
assertEquals(
d.reason.includes('scaffold-runtime-sqlite skipped by ci:skip-e2e'),
true,
);
});

Deno.test('decide: ci:skip-scaffold skips static only', () => {
Expand All @@ -518,7 +542,14 @@ Deno.test('decide: ci:skip-scaffold skips static only', () => {
labels: ['ci:skip-scaffold'],
});
assertEquals(d.runStatic, false);
// ci:skip-scaffold is not an independent sqlite-runtime override. The
// derived tier is false here because its run_static prerequisite is false.
assertEquals(d.runRuntimeSqlite, false);
assertEquals(d.runRuntime, true);
assertEquals(
d.reason.includes('scaffold-runtime-sqlite skipped: scaffold-static signal is off'),
true,
);
});

Deno.test('decide: both skip labels skip both jobs', () => {
Expand All @@ -528,6 +559,7 @@ Deno.test('decide: both skip labels skip both jobs', () => {
labels: ['ci:skip-scaffold', 'ci:skip-e2e'],
});
assertEquals(d.runStatic, false);
assertEquals(d.runRuntimeSqlite, false);
assertEquals(d.runRuntime, false);
});

Expand All @@ -551,8 +583,13 @@ Deno.test('decide: ci:full overrides docs-only and forces the ENTIRE vector', ()
labels: ['ci:full'],
});
assertEquals(d.runStatic, true);
assertEquals(d.runRuntimeSqlite, true);
assertEquals(d.runRuntime, true);
assertEquals(vector(d), ALL_TRUE);
assertEquals(
d.reason.includes('scaffold-runtime-sqlite forced by ci:full'),
true,
);
});

Deno.test('decide: ci:full overrides skip labels', () => {
Expand All @@ -562,12 +599,14 @@ Deno.test('decide: ci:full overrides skip labels', () => {
labels: ['ci:full', 'ci:skip-e2e', 'ci:skip-scaffold'],
});
assertEquals(d.runStatic, true);
assertEquals(d.runRuntimeSqlite, true);
assertEquals(d.runRuntime, true);
});

Deno.test('decide: workflow_dispatch runs everything (no diff)', () => {
const d = decide({ eventName: 'workflow_dispatch', files: [], labels: [] });
assertEquals(d.runStatic, true);
assertEquals(d.runRuntimeSqlite, true);
assertEquals(d.runRuntime, true);
assertEquals(vector(d), ALL_TRUE);
});
Expand All @@ -579,9 +618,123 @@ Deno.test('decide: workflow_dispatch honours skip labels', () => {
labels: ['ci:skip-e2e'],
});
assertEquals(d.runStatic, true);
assertEquals(d.runRuntimeSqlite, false);
assertEquals(d.runRuntime, false);
});

Deno.test('decide: workflow_dispatch honours ci:skip-scaffold for sqlite runtime', () => {
const d = decide({
eventName: 'workflow_dispatch',
files: [],
labels: ['ci:skip-scaffold'],
});
assertEquals(d.runStatic, false);
assertEquals(d.runRuntimeSqlite, false);
assertEquals(d.runRuntime, true);
assertEquals(
d.reason.includes('scaffold-runtime-sqlite skipped: scaffold-static signal is off'),
true,
);
});

Deno.test('decide: sqlite runtime reason follows the scaffold signal', () => {
const d = decide({
eventName: 'pull_request',
files: ['packages/cli/mod.ts'],
labels: [],
});
assertEquals(d.runRuntimeSqlite, true);
assertEquals(
d.reason.includes('scaffold-runtime-sqlite: scaffold-static signal is on'),
true,
);
});

Deno.test('workflow: sqlite runtime uses sibling diff guard and fails closed', async () => {
const workflow = await Deno.readTextFile('.github/workflows/e2e-cli.yml');
const cliSurface = await Deno.readTextFile(
'packages/cli/e2e/src/domain/cli-surface.ts',
);
const suiteId = /RUNTIME_SQLITE:\s*'([^']+)'/.exec(cliSurface)?.[1];
assertEquals(typeof suiteId, 'string');
const sqliteJob = workflowJob(workflow, 'scaffold-runtime-sqlite');
assertEquals(typeof sqliteJob, 'string');
assertEquals(
sqliteJob!.includes(
"if: ${{ !cancelled() && needs.classify.result != 'skipped' && needs.classify.outputs.diff_unavailable != 'true' }}",
),
true,
);
assertEquals(
sqliteJob!.includes(
"RUN: ${{ needs.classify.result != 'success' || needs.classify.outputs.run_runtime_sqlite == 'true' }}",
),
true,
);

const classifyJob = workflowJob(workflow, 'classify');
assertEquals(typeof classifyJob, 'string');
assertEquals(
classifyJob!.includes(
'run_runtime_sqlite: ${{ steps.decide.outputs.run_runtime_sqlite }}',
),
true,
);

assertEquals(
sqliteJob!.includes(
`deno task e2e:cli run ${suiteId} --cleanup --format pretty`,
),
true,
);
assertEquals(
sqliteJob!.includes('group: e2e-scaffold-runtime-sqlite-global'),
true,
);
assertEquals(
sqliteJob!.includes('name: e2e-cli-scaffold-runtime-sqlite-report'),
true,
);
assertEquals(
sqliteJob!.includes('.llm/tmp/**/report*.ndjson'),
true,
);

const postgresJob = workflowJob(workflow, 'scaffold-runtime');
assertEquals(typeof postgresJob, 'string');
assertEquals(
postgresJob!.includes('group: e2e-scaffold-runtime-global'),
true,
);
assertEquals(
postgresJob!.includes('name: e2e-cli-scaffold-runtime-report'),
true,
);
assertEquals(
sqliteJob!.includes('group: e2e-scaffold-runtime-global\n'),
false,
);
assertEquals(
sqliteJob!.includes('name: e2e-cli-scaffold-runtime-report\n'),
false,
);

const visibilityJob = workflowJob(workflow, 'lane-visibility');
assertEquals(typeof visibilityJob, 'string');
assertEquals(
visibilityJob!.includes(
'needs: [classify, scaffold-static, scaffold-runtime, scaffold-runtime-sqlite, desktop-native-linux]',
),
true,
);
assertEquals(
visibilityJob!.includes(
'printf \'| `scaffold-runtime-sqlite` | %s |\\n\' "$runtime_sqlite_outcome"',
),
true,
);
});

Deno.test('parseLabels: JSON array and comma forms', () => {
assertEquals(parseLabels('["a","b"]'), ['a', 'b']);
assertEquals(parseLabels('a, b ,c'), ['a', 'b', 'c']);
Expand Down
Loading
Loading