Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ jobs:
needs: changes
if: needs.changes.outputs.core_tests == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 60
steps:
- name: Check out repository
uses: actions/checkout@v7
Expand Down Expand Up @@ -213,9 +213,9 @@ jobs:
needs: changes
if: needs.changes.outputs.core_tests == 'true'
runs-on: ubuntu-latest
# The full public-minimum suite now runs beyond ten minutes on hosted runners.
# The full public-minimum suite has reached fifteen minutes on hosted runners.
# Keep a bounded margin above the measured workload without weakening coverage.
timeout-minutes: 15
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@ def test_goal_todo_add_uses_provider_at_override_root_when_promoted(
_engage_fence(runtime_override)
captured: dict[str, object] = {}

def missing_provider(method: str, params: dict[str, object]) -> dict[str, object]:
def missing_provider(
method: str, params: dict[str, object], **_kwargs: object
) -> dict[str, object]:
captured.update(method=method, params=params)
return {
"status": "missing",
Expand Down
4 changes: 2 additions & 2 deletions tests/control_plane/test_todo_projection_concurrency.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ def test_downlevel_runtime_cannot_acknowledge_delivery(
args, state, first, _ = canonical_projection
invoke = local_authority.effect_runtime_result

def without_confirmation(method, payload):
result = invoke(method, payload)
def without_confirmation(method, payload, **kwargs):
result = invoke(method, payload, **kwargs)
if payload.get("projection_readback") is not None:
result.pop("projection_readback", None)
return result
Expand Down
26 changes: 19 additions & 7 deletions tests/control_plane_ts/authority_archive.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@ import {join} from "node:path";
import test from "node:test";
import {FileAuthorityStore} from "../../loopx/control_plane/coordination/file_authority_store.ts";
import {SqliteAuthorityStore} from "../../loopx/control_plane/coordination/sqlite_authority_store.ts";
import {sqliteAuthorityRuntime} from "../../loopx/control_plane/coordination/sqlite_runtime.ts";
import {exportAuthorityArchive, verifyAuthorityArchive, restoreAuthorityArchive} from
"../../loopx/control_plane/coordination/authority_archive.ts";

function sqliteSkipReason(): string | undefined {
try { sqliteAuthorityRuntime(); return undefined; }
catch { return "requires a WAL-fixed SQLite runtime with finalized statements"; }
}
const sqliteSkip = sqliteSkipReason();

// Expectations come from the retained-journal contract: exact historical state,
// operation identities and receipts survive; physical revision tokens do not.
for (const sourceKind of ["file", "sqlite"] as const) {
test(`${sourceKind}: complete archive roundtrip preserves every transaction`, async () => {
test(`${sourceKind}: complete archive roundtrip preserves every transaction`,
{skip: sourceKind === "sqlite" ? sqliteSkip : undefined}, async () => {
const root = await mkdtemp(join(tmpdir(), "authority-archive-"));
try {
const source = sourceKind === "file" ? new FileAuthorityStore(join(root, "source"), "goal")
Expand All @@ -33,6 +41,7 @@ for (const sourceKind of ["file", "sqlite"] as const) {
assert.equal(result.commits, "7");
assert.deepEqual(await verifyAuthorityArchive(archive), result);
for (const kind of ["file", "sqlite"] as const) {
if (kind === "sqlite" && sqliteSkip !== undefined) continue;
const target = kind === "file" ? new FileAuthorityStore(join(root, kind), "goal")
: new SqliteAuthorityStore(join(root, kind), "goal");
const restored = await restoreAuthorityArchive(archive, target, result.archive_sha256);
Expand Down Expand Up @@ -95,7 +104,7 @@ async function seed(store: AuthorityStore, count = 3) {
return previous;
}

test("capture pins its original prefix while real source receives later commits", async () => {
test("capture pins its original prefix while real source receives later commits", {skip: sqliteSkip}, async () => {
const root = await mkdtemp(join(tmpdir(), "authority-archive-"));
try {
const source = new SqliteAuthorityStore(join(root, "source"), "goal");
Expand Down Expand Up @@ -148,7 +157,8 @@ for (const fault of ["gap", "missing-page", "identity", "changed-head"] as const
}

for (const kind of ["file", "sqlite"] as const) {
test(`${kind}: interrupted restore resumes the exact retained prefix; lost ack recovers`, async () => {
test(`${kind}: interrupted restore resumes the exact retained prefix; lost ack recovers`,
{skip: kind === "sqlite" ? sqliteSkip : undefined}, async () => {
const root = await mkdtemp(join(tmpdir(), "authority-archive-"));
try {
const source = new FileAuthorityStore(join(root, "source"), "goal");
Expand Down Expand Up @@ -180,7 +190,7 @@ for (const kind of ["file", "sqlite"] as const) {
});
}

test("restore rejects occupied divergent or longer target and changed reviewed digest", async () => {
test("restore rejects occupied divergent or longer target and changed reviewed digest", {skip: sqliteSkip}, async () => {
const root = await mkdtemp(join(tmpdir(), "authority-archive-"));
try {
const source = new SqliteAuthorityStore(join(root, "source"), "goal");
Expand Down Expand Up @@ -233,7 +243,8 @@ for (const corruption of ["order", "duplicate", "head", "goal", "unknown-field",
}

for (const schema of ["native", "legacy"] as const) {
test(`${schema}: mixed complete graph retains archived records, leases, ordering and unknown metadata`, async () => {
test(`${schema}: mixed complete graph retains archived records, leases, ordering and unknown metadata`,
{skip: sqliteSkip}, async () => {
const root = await mkdtemp(join(tmpdir(), "authority-archive-"));
try {
const source = new SqliteAuthorityStore(join(root, "source"), "goal");
Expand Down Expand Up @@ -263,7 +274,8 @@ for (const schema of ["native", "legacy"] as const) {
});
}

test("SQLite retained history crosses checkpoint windows and preserves an old same-key receipt", async () => {
test("SQLite retained history crosses checkpoint windows and preserves an old same-key receipt",
{skip: sqliteSkip}, async () => {
const root = await mkdtemp(join(tmpdir(), "authority-archive-history-"));
try {
const source = new SqliteAuthorityStore(join(root, "source"), "goal");
Expand All @@ -282,7 +294,7 @@ test("SQLite retained history crosses checkpoint windows and preserves an old sa
} finally { await rm(root, {recursive: true, force: true}); }
});

test("a changed archive during the second pass cannot claim a verified recovery", async () => {
test("a changed archive during the second pass cannot claim a verified recovery", {skip: sqliteSkip}, async () => {
const root = await mkdtemp(join(tmpdir(), "authority-archive-change-"));
try {
const source = new FileAuthorityStore(join(root, "source"), "goal");
Expand Down
2 changes: 1 addition & 1 deletion tests/test_python_ci_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_minimum_node_lane_keeps_full_coverage_with_runner_headroom() -> None:
" node-forward-compatibility:\n", 1,
)[0]

assert "timeout-minutes: 15" in minimum
assert "timeout-minutes: 20" in minimum
assert "for test in tests/control_plane_ts/*.test.ts" in minimum
assert 'node --no-warnings --experimental-sqlite --experimental-strip-types --test "${tests[@]}"' in minimum
assert "--test-name-pattern" not in minimum
Expand Down
Loading