@evident-ai/runner-synchroniser 3.4.1-dev.31006db → 3.4.1-dev.38181ff
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/dist/cli.js +27 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ build time.
|
|
|
56
56
|
| `env` | resolved config as shell-eval'able vars | `0` = ran; non-zero = tool broken |
|
|
57
57
|
| `litestream-config` | the generated `litestream.yml` | `0` = ran; non-zero = tool broken |
|
|
58
58
|
| `restore <claude\|opencode>` | — | `0` = ran; non-zero = tool broken |
|
|
59
|
-
| `sync-once <claude\|opencode>` | — | `0` =
|
|
59
|
+
| `sync-once <claude\|opencode>` | — | `0` = uploaded/unchanged/absent/disabled; `40` = not persisted; other = tool broken |
|
|
60
60
|
| `model-auth-ready` | — | `0` = ready, `10` = not ready; other = tool broken |
|
|
61
61
|
| `self-stop` | — | `0` = stopped, `20` = keep the task; other = tool broken |
|
|
62
62
|
| `session-db-classify <litestream-restore-exit-code> <attempt> [--on-unusable-replica=<prune\|leave\|clear\|crash>] [--recovery-occurred] [--fresh-db-fallback]` | — | `0` = restored/no-replica/disabled, `32` = re-run and ask again, `31` = unusable (booted fresh, replicates into the existing prefix), `30` = fatal; other = usage/tool broken |
|
|
@@ -250,8 +250,7 @@ and it can never repair corruption at a higher compaction level.
|
|
|
250
250
|
|
|
251
251
|
`EVIDENT_ON_UNUSABLE_REPLICA` is a `runner/docker-images/fargate` (entrypoint) variable translated into the flag above at boot — this CLI never reads it, so it has no row in this README's Configuration table below; see [the Fargate image README](../docker-images/fargate/README.md#when-the-replica-is-unusable-evident_on_unusable_replica). An unrecognised value (including wrong casing, e.g. `Prune`) exits `2`, outside `entrypoint.sh`'s `0|10|20|30|31|32|33` allow-list — a typo **crash-loops the task on attempt 1** rather than falling back to `prune`, and also logs the misleading "credential persistence is DEGRADED" ERROR.
|
|
252
252
|
|
|
253
|
-
|
|
254
|
-
the behavioural anchor (31 comes online, 30 does not).
|
|
253
|
+
The behavioural anchor is explicit: **31 comes online, 30 does not**.
|
|
255
254
|
|
|
256
255
|
### `session-db-verify`
|
|
257
256
|
|
|
@@ -327,15 +326,16 @@ same way it already reuses `SESSION-DB-REPLICA-UNUSABLE` for `session-db-classif
|
|
|
327
326
|
|
|
328
327
|
### Why the contract is asymmetric
|
|
329
328
|
|
|
330
|
-
`restore` and
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
329
|
+
`restore` logs domain outcomes and still exits `0`: a missing remote object or a
|
|
330
|
+
restore failure should not abort a boot, because a runner with no credentials yet
|
|
331
|
+
is a runner a human can still log into. `sync-once` returns `40` when the current
|
|
332
|
+
credential file is not persisted (`failed`, `hashFailed`, or `localInvalid`), while
|
|
333
|
+
`absent` and `disabled` remain legitimate `0` outcomes.
|
|
334
334
|
|
|
335
|
-
The consequence is the point: **any non-zero status from `restore
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
335
|
+
The consequence is the point: **any non-zero status from `restore` means the tool itself
|
|
336
|
+
broke** — and `sync-once` uses `40` for its typed persistence answer; other non-zero
|
|
337
|
+
statuses still mean bad arguments (`2`), an uncaught throw (`1`), or a bundle that would
|
|
338
|
+
not run at all. The shell keeps that distinction in one helper.
|
|
339
339
|
|
|
340
340
|
The **two predicates** — `model-auth-ready` and `self-stop` — each need to distinguish
|
|
341
341
|
"the answer is no" from "the tool is broken", so each answers no with its own dedicated
|
package/dist/cli.js
CHANGED
|
@@ -61819,7 +61819,14 @@ async function verifySessionDb(params) {
|
|
|
61819
61819
|
if (stat2 === null) return { kind: "skipped", localDb: "absent" };
|
|
61820
61820
|
if (stat2.size === 0) return { kind: "skipped", localDb: "empty" };
|
|
61821
61821
|
const result = await sqlite.check(dbPath);
|
|
61822
|
-
if (result.ok)
|
|
61822
|
+
if (result.ok) {
|
|
61823
|
+
if (result.migrationSummary !== void 0 && result.migrationSummary !== null) {
|
|
61824
|
+
log(
|
|
61825
|
+
`INFO: SESSION-DB-SCHEMA-PROVENANCE: ${result.migrationSummary.migrationCount} migrations, newest ${result.migrationSummary.newestMigrationId ?? "(none)"}`
|
|
61826
|
+
);
|
|
61827
|
+
}
|
|
61828
|
+
return { kind: "healthy", bytes: stat2.size };
|
|
61829
|
+
}
|
|
61823
61830
|
log(
|
|
61824
61831
|
`WARNING: SESSION-DB-INTEGRITY-FAILED: opencode.db at ${dbPath} failed its integrity check: ${result.detail}`
|
|
61825
61832
|
);
|
|
@@ -62062,6 +62069,19 @@ var MAX_DETAIL_LENGTH = 500;
|
|
|
62062
62069
|
function truncate(text) {
|
|
62063
62070
|
return text.length > MAX_DETAIL_LENGTH ? `${text.slice(0, MAX_DETAIL_LENGTH)}\u2026` : text;
|
|
62064
62071
|
}
|
|
62072
|
+
function readMigrationSummary(db) {
|
|
62073
|
+
try {
|
|
62074
|
+
const row = db.prepare("SELECT COUNT(*) AS migration_count, MAX(id) AS newest_migration_id FROM migration").get();
|
|
62075
|
+
const count = row?.migration_count;
|
|
62076
|
+
const newestId = row?.newest_migration_id;
|
|
62077
|
+
if (typeof count !== "number" || !Number.isSafeInteger(count) || count < 0) return null;
|
|
62078
|
+
if (newestId !== null && typeof newestId !== "string") return null;
|
|
62079
|
+
return { migrationCount: count, newestMigrationId: newestId ?? null };
|
|
62080
|
+
} catch (error) {
|
|
62081
|
+
void error;
|
|
62082
|
+
return null;
|
|
62083
|
+
}
|
|
62084
|
+
}
|
|
62065
62085
|
var nodeSqliteIntegrity = {
|
|
62066
62086
|
async check(path) {
|
|
62067
62087
|
let db;
|
|
@@ -62070,7 +62090,7 @@ var nodeSqliteIntegrity = {
|
|
|
62070
62090
|
const row = db.prepare("PRAGMA integrity_check").get();
|
|
62071
62091
|
const value = row?.integrity_check;
|
|
62072
62092
|
if (value === "ok") {
|
|
62073
|
-
return { ok: true };
|
|
62093
|
+
return { ok: true, migrationSummary: readMigrationSummary(db) };
|
|
62074
62094
|
}
|
|
62075
62095
|
return { ok: false, detail: truncate(String(value ?? "no result row")) };
|
|
62076
62096
|
} catch (err) {
|
|
@@ -62144,6 +62164,7 @@ var EXIT_SESSION_DB_UNUSABLE = 31;
|
|
|
62144
62164
|
var EXIT_SESSION_DB_RETRY = 32;
|
|
62145
62165
|
var EXIT_SESSION_DB_UNVERIFIABLE = 33;
|
|
62146
62166
|
var EXIT_SESSION_DB_UNSEPARATED = 34;
|
|
62167
|
+
var EXIT_SYNC_NOT_PERSISTED = 40;
|
|
62147
62168
|
var STATE_SUFFIX = ".synchash";
|
|
62148
62169
|
var COMMANDS = shell_contract_default.commands;
|
|
62149
62170
|
var USAGE = `Usage: runner-synchroniser <command> [args]
|
|
@@ -62294,6 +62315,7 @@ async function commandSyncOnce(name, config, deps) {
|
|
|
62294
62315
|
if (result.hash !== null && result.hash !== lastHash) {
|
|
62295
62316
|
await writeLastHash(fileOps, statePath, result.hash, log);
|
|
62296
62317
|
}
|
|
62318
|
+
return result.outcome.kind === "failed" || result.outcome.kind === "hashFailed" || result.outcome.kind === "localInvalid" ? EXIT_SYNC_NOT_PERSISTED : 0;
|
|
62297
62319
|
}
|
|
62298
62320
|
async function commandSessionDbClassify(args, config, deps) {
|
|
62299
62321
|
const { fileOps, log } = deps;
|
|
@@ -62431,10 +62453,10 @@ ${USAGE}`);
|
|
|
62431
62453
|
}
|
|
62432
62454
|
if (command12 === "restore") {
|
|
62433
62455
|
await commandRestore(name, config, deps);
|
|
62456
|
+
return 0;
|
|
62434
62457
|
} else {
|
|
62435
|
-
|
|
62458
|
+
return commandSyncOnce(name, config, deps);
|
|
62436
62459
|
}
|
|
62437
|
-
return 0;
|
|
62438
62460
|
}
|
|
62439
62461
|
function isEntryPoint() {
|
|
62440
62462
|
const entry = process.argv[1];
|
|
@@ -62467,6 +62489,7 @@ export {
|
|
|
62467
62489
|
EXIT_SESSION_DB_UNSEPARATED,
|
|
62468
62490
|
EXIT_SESSION_DB_UNUSABLE,
|
|
62469
62491
|
EXIT_SESSION_DB_UNVERIFIABLE,
|
|
62492
|
+
EXIT_SYNC_NOT_PERSISTED,
|
|
62470
62493
|
EXIT_USAGE,
|
|
62471
62494
|
main
|
|
62472
62495
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evident-ai/runner-synchroniser",
|
|
3
|
-
"version": "3.4.1-dev.
|
|
3
|
+
"version": "3.4.1-dev.38181ff",
|
|
4
4
|
"description": "Restores and syncs the Evident runner's OpenCode credential stores (and litestream config) to an object store, so a runner survives task replacement with almost no state loss.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
|
-
"build": "tsup",
|
|
14
|
+
"build": "tsup && node -e 'const m=require(\"./package.json\").main; if (!require(\"node:fs\").existsSync(m)) { console.error(`build produced no ${m}`); process.exit(1); }'",
|
|
15
15
|
"typecheck": "tsc --noEmit",
|
|
16
16
|
"lint": "eslint 'src/**/*.ts'",
|
|
17
17
|
"test": "vitest run",
|