@zq-silk/yui 0.14.2 → 0.15.1
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/ARCHITECTURE.md +27 -12
- package/README.md +85 -61
- package/dist/cli/commandCatalog.js +6 -6
- package/dist/cli/updateCommand.js +17 -9
- package/dist/cli/updateOrchestrator.js +81 -15
- package/dist/cli/updatePorts.js +72 -10
- package/dist/cli/upgradeCommand.js +104 -19
- package/dist/cli.js +2 -2
- package/dist/commands/agentCommands.js +13 -6
- package/dist/commands/controllerCommands.js +1 -1
- package/dist/commands/globalRoleCommands.js +11 -3
- package/dist/commands/roleConfiguration.js +7 -0
- package/dist/commands/roleRuntimeGuard.js +30 -0
- package/dist/commands/taskCommands.js +10 -3
- package/dist/controller/fileSchedulerStoreAdapter.js +4 -4
- package/dist/controller/runtime.js +11 -25
- package/dist/controller/runtimeLaunchCoordinator.js +9 -30
- package/dist/controller/sessionNotify.js +5 -0
- package/dist/core/controllerServer.js +5 -5
- package/dist/doctor/doctor.js +37 -14
- package/dist/executor/agentExecutor.js +8 -11
- package/dist/executor/effectiveLaunch.js +34 -17
- package/dist/executor/fileRoleLaunchPlanner.js +11 -8
- package/dist/observability/runtimeIdentity.js +48 -50
- package/dist/release/runtimeRelease.js +9 -1
- package/dist/runtime/agentHost.js +7 -0
- package/dist/runtime/codexInteractiveHost.js +191 -0
- package/dist/runtime/exactControlPlane.js +20 -29
- package/dist/runtime/structuredProviderHost.js +35 -0
- package/dist/runtime/tmuxAdapters.js +51 -9
- package/dist/scheduler/activeRoleTurnDelivery.js +4 -4
- package/dist/scheduler/leaderWakeupProcessor.js +3 -4
- package/dist/storage/currentTaskStore.js +6 -4
- package/dist/storage/sqliteSchema.js +134 -59
- package/dist/storage/sqliteStore.js +7 -5
- package/dist/storage/storageSchema.js +92 -223
- package/dist/storage/storageVersions.js +12 -16
- package/dist/storage/upgrade/upgradeOrchestrator.js +224 -62
- package/dist/tmux/tmuxManager.js +43 -28
- package/dist/version.js +3 -3
- package/docs/task-local-identity.md +9 -9
- package/i18n/README.zh-CN.md +33 -17
- package/package.json +1 -1
- package/dist/storage/upgrade/recordVersions.js +0 -82
|
@@ -8,26 +8,20 @@
|
|
|
8
8
|
*
|
|
9
9
|
* - `global_sequences` (§5.3): global record ID high-water marks.
|
|
10
10
|
* - `outbox` (§5.4): durable outbox with `UNIQUE(request_id)` for exactly-once.
|
|
11
|
-
* - `config`: the `YuiConfig` singleton (
|
|
12
|
-
* identity/revision/versions; config is a separate singleton).
|
|
11
|
+
* - `config`: the `YuiConfig` singleton (`home_meta` keeps identity/revision).
|
|
13
12
|
*
|
|
14
13
|
* Record payloads are stored two ways, per §4: typed columns for fields that are
|
|
15
14
|
* queried/filtered/used-for-CAS, and a `payload` JSON column holding the full
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* current record. Record-local `schemaVersion` tags remain validation guards;
|
|
16
|
+
* they are not independent Home compatibility axes. Any historical payload
|
|
17
|
+
* rewrite belongs to the ordered Home migration that introduced the new shape.
|
|
18
18
|
*
|
|
19
|
-
* The migration runner is idempotent: it records
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* by SQLite (DDL is transactional) and re-applied on the next open.
|
|
19
|
+
* The migration runner is append-only and idempotent: it records one ordered
|
|
20
|
+
* Home version in `schema_migrations`. Re-running an already-current database
|
|
21
|
+
* is a no-op; a crash mid-upgrade rolls the whole migration transaction back.
|
|
23
22
|
*/
|
|
24
23
|
import { createHash } from "node:crypto";
|
|
25
|
-
|
|
26
|
-
export const SQLITE_LAYOUT_VERSION = 8;
|
|
27
|
-
/** The aggregate version of the normalized SQLite schema. */
|
|
28
|
-
export const SQLITE_AGGREGATE_VERSION = 2;
|
|
29
|
-
/** The current schema migration version. */
|
|
30
|
-
export const SQLITE_SCHEMA_VERSION = 1;
|
|
24
|
+
import { CURRENT_STORAGE_VERSION, MIN_SUPPORTED_STORAGE_VERSION } from "./storageVersions.js";
|
|
31
25
|
/** Telemetry retention bounds (§4.4). Open question 3 in §11; defaults from the design. */
|
|
32
26
|
export const TELEMETRY_KEEP_PER_GENERATION = 200;
|
|
33
27
|
export const TELEMETRY_TURN_CAP = 50_000;
|
|
@@ -38,20 +32,19 @@ export const TELEMETRY_TURN_CAP = 50_000;
|
|
|
38
32
|
* the store; `journal_mode=WAL` is a persistent database property set on open.
|
|
39
33
|
* The migration itself only contains schema objects.
|
|
40
34
|
*
|
|
41
|
-
* This is the
|
|
42
|
-
*
|
|
35
|
+
* This is the Yui 0.15.0 / storage-version-1 baseline. Future releases append
|
|
36
|
+
* migrations after it so fresh and upgraded databases converge on the same
|
|
37
|
+
* current contract.
|
|
43
38
|
*/
|
|
44
39
|
const BASELINE_CORE_SQL = `
|
|
45
40
|
-- Global catalog and coordination (§4.1) -------------------------------------
|
|
46
41
|
|
|
47
42
|
CREATE TABLE IF NOT EXISTS home_meta (
|
|
48
|
-
id
|
|
49
|
-
home_identity
|
|
50
|
-
revision
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
created_at TEXT NOT NULL,
|
|
54
|
-
updated_at TEXT NOT NULL
|
|
43
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
44
|
+
home_identity TEXT NOT NULL,
|
|
45
|
+
revision INTEGER NOT NULL,
|
|
46
|
+
created_at TEXT NOT NULL,
|
|
47
|
+
updated_at TEXT NOT NULL
|
|
55
48
|
);
|
|
56
49
|
|
|
57
50
|
CREATE TABLE IF NOT EXISTS config (
|
|
@@ -464,7 +457,7 @@ END;
|
|
|
464
457
|
* Session owner physical identity records.
|
|
465
458
|
*
|
|
466
459
|
* One row per runtime generation, keyed by runtime generation id. The payload column
|
|
467
|
-
* stores the full
|
|
460
|
+
* stores the full current JSON record; typed columns support the
|
|
468
461
|
* reconciliation queries (task/role lookup, PID liveness).
|
|
469
462
|
*/
|
|
470
463
|
const BASELINE_SESSION_OWNER_SQL = `
|
|
@@ -485,9 +478,8 @@ CREATE INDEX IF NOT EXISTS idx_session_owners_task
|
|
|
485
478
|
/**
|
|
486
479
|
* Resource GC registry.
|
|
487
480
|
*
|
|
488
|
-
* GC-owned table for resource lifecycle records.
|
|
489
|
-
* state
|
|
490
|
-
* versioning. Records are stored as full versioned JSON in `payload`, with
|
|
481
|
+
* GC-owned table for resource lifecycle records. The registry is GC's own
|
|
482
|
+
* state. Records are stored as full current JSON in `payload`, with
|
|
491
483
|
* typed columns for the fields GC queries (disposition, kind, task_id).
|
|
492
484
|
*/
|
|
493
485
|
const BASELINE_RESOURCE_REGISTRY_SQL = `
|
|
@@ -661,10 +653,26 @@ const MIGRATION_1_SQL = [
|
|
|
661
653
|
BASELINE_TASK_WAKE_SQL,
|
|
662
654
|
BASELINE_CONTEXT_SNAPSHOT_SQL
|
|
663
655
|
].join("\n");
|
|
664
|
-
/**
|
|
665
|
-
const MIGRATIONS = [
|
|
666
|
-
{
|
|
667
|
-
|
|
656
|
+
/** Released migrations are append-only and must never be rewritten. */
|
|
657
|
+
const MIGRATIONS = Object.freeze([
|
|
658
|
+
{
|
|
659
|
+
version: 1,
|
|
660
|
+
name: "v0.15.0-baseline",
|
|
661
|
+
introducedIn: "0.15.0",
|
|
662
|
+
sql: MIGRATION_1_SQL
|
|
663
|
+
}
|
|
664
|
+
]);
|
|
665
|
+
for (let index = 0; index < MIGRATIONS.length; index += 1) {
|
|
666
|
+
const expectedVersion = MIN_SUPPORTED_STORAGE_VERSION + index;
|
|
667
|
+
if (MIGRATIONS[index]?.version !== expectedVersion) {
|
|
668
|
+
throw new Error(`Storage migration registry must be contiguous from `
|
|
669
|
+
+ `${MIN_SUPPORTED_STORAGE_VERSION}; missing version ${expectedVersion}.`);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (MIGRATIONS.at(-1)?.version !== CURRENT_STORAGE_VERSION) {
|
|
673
|
+
throw new Error(`Storage migration registry head ${String(MIGRATIONS.at(-1)?.version)} does not match `
|
|
674
|
+
+ `CURRENT_STORAGE_VERSION ${CURRENT_STORAGE_VERSION}.`);
|
|
675
|
+
}
|
|
668
676
|
/** Current hot-path indexes whose absence would invalidate a current Home. */
|
|
669
677
|
const REQUIRED_SCHEMA_INDEXES = [
|
|
670
678
|
"idx_mailboxes_ready",
|
|
@@ -688,11 +696,10 @@ export class SqliteSchemaMigrationError extends Error {
|
|
|
688
696
|
}
|
|
689
697
|
const SCHEMA_MIGRATIONS_SQL = `
|
|
690
698
|
CREATE TABLE schema_migrations (
|
|
691
|
-
version
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
checksum TEXT NOT NULL
|
|
699
|
+
version INTEGER PRIMARY KEY,
|
|
700
|
+
name TEXT NOT NULL,
|
|
701
|
+
applied_at TEXT NOT NULL,
|
|
702
|
+
checksum TEXT NOT NULL
|
|
696
703
|
)
|
|
697
704
|
`;
|
|
698
705
|
/**
|
|
@@ -720,10 +727,20 @@ function ensureMigrationLedger(db, mode) {
|
|
|
720
727
|
}
|
|
721
728
|
return false;
|
|
722
729
|
}
|
|
723
|
-
|
|
730
|
+
function validateMigrationLedgerColumns(db) {
|
|
731
|
+
const columns = new Set(db.prepare("PRAGMA table_info(schema_migrations)").all()
|
|
732
|
+
.flatMap(({ name }) => typeof name === "string" ? [name] : []));
|
|
733
|
+
if (columns.size === 4
|
|
734
|
+
&& ["version", "name", "applied_at", "checksum"].every((name) => columns.has(name))) {
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
throw new SqliteSchemaMigrationError("schema_migrations columns do not match the storage-version-1 ledger");
|
|
738
|
+
}
|
|
739
|
+
/** Validate the applied linear prefix and return its current head. */
|
|
724
740
|
function validateAppliedMigrations(db, ledgerWasCreated) {
|
|
741
|
+
validateMigrationLedgerColumns(db);
|
|
725
742
|
const expected = new Map(MIGRATIONS.map((migration) => [migration.version, migration]));
|
|
726
|
-
const rows = db.prepare("SELECT version,
|
|
743
|
+
const rows = db.prepare("SELECT version, name, checksum FROM schema_migrations ORDER BY version").all();
|
|
727
744
|
if (rows.length === 0 && !ledgerWasCreated) {
|
|
728
745
|
throw new SqliteSchemaMigrationError("schema_migrations ledger is empty in an existing database");
|
|
729
746
|
}
|
|
@@ -734,19 +751,22 @@ function validateAppliedMigrations(db, ledgerWasCreated) {
|
|
|
734
751
|
}
|
|
735
752
|
const version = row.version;
|
|
736
753
|
const migration = expected.get(version);
|
|
737
|
-
if (migration === undefined) {
|
|
738
|
-
throw new SqliteSchemaMigrationError(`unknown migration version ${version}`);
|
|
739
|
-
}
|
|
740
754
|
if (applied.has(version)) {
|
|
741
755
|
throw new SqliteSchemaMigrationError(`duplicate migration version ${version}`);
|
|
742
756
|
}
|
|
743
757
|
applied.add(version);
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
758
|
+
if (migration === undefined) {
|
|
759
|
+
if (version <= CURRENT_STORAGE_VERSION) {
|
|
760
|
+
throw new SqliteSchemaMigrationError(`unknown migration version ${version}`);
|
|
761
|
+
}
|
|
762
|
+
if (typeof row.name !== "string" || row.name.length === 0
|
|
763
|
+
|| typeof row.checksum !== "string" || row.checksum.length === 0) {
|
|
764
|
+
throw new SqliteSchemaMigrationError(`future migration ${version} metadata is invalid`);
|
|
765
|
+
}
|
|
766
|
+
continue;
|
|
747
767
|
}
|
|
748
|
-
if (row.
|
|
749
|
-
throw new SqliteSchemaMigrationError(`migration ${version}
|
|
768
|
+
if (row.name !== migration.name) {
|
|
769
|
+
throw new SqliteSchemaMigrationError(`migration ${version} name ${String(row.name)} does not match ${migration.name}`);
|
|
750
770
|
}
|
|
751
771
|
const expectedChecksum = checksum(migration.sql);
|
|
752
772
|
if (row.checksum !== expectedChecksum) {
|
|
@@ -755,12 +775,18 @@ function validateAppliedMigrations(db, ledgerWasCreated) {
|
|
|
755
775
|
}
|
|
756
776
|
const versions = [...applied].sort((left, right) => left - right);
|
|
757
777
|
for (let index = 0; index < versions.length; index += 1) {
|
|
758
|
-
const expectedVersion =
|
|
778
|
+
const expectedVersion = MIN_SUPPORTED_STORAGE_VERSION + index;
|
|
759
779
|
if (versions[index] !== expectedVersion) {
|
|
760
780
|
throw new SqliteSchemaMigrationError(`migration ledger has a gap before version ${versions[index]}`);
|
|
761
781
|
}
|
|
762
782
|
}
|
|
763
|
-
|
|
783
|
+
const currentVersion = versions.at(-1) ?? 0;
|
|
784
|
+
const head = rows.at(-1);
|
|
785
|
+
return {
|
|
786
|
+
versions: applied,
|
|
787
|
+
currentVersion,
|
|
788
|
+
currentChecksum: typeof head?.checksum === "string" ? head.checksum : ""
|
|
789
|
+
};
|
|
764
790
|
}
|
|
765
791
|
/**
|
|
766
792
|
* Validate the physical objects promised by the migration ledger. Ledger
|
|
@@ -780,25 +806,63 @@ function validateSchemaObjects(db) {
|
|
|
780
806
|
throw new SqliteSchemaMigrationError(`required index '${index}' is missing or has the wrong type`, "schema object");
|
|
781
807
|
}
|
|
782
808
|
}
|
|
809
|
+
const homeMetaColumns = db.prepare("PRAGMA table_info(home_meta)").all().map(({ name }) => name);
|
|
810
|
+
const expectedHomeMetaColumns = [
|
|
811
|
+
"id",
|
|
812
|
+
"home_identity",
|
|
813
|
+
"revision",
|
|
814
|
+
"created_at",
|
|
815
|
+
"updated_at"
|
|
816
|
+
];
|
|
817
|
+
if (homeMetaColumns.length !== expectedHomeMetaColumns.length
|
|
818
|
+
|| homeMetaColumns.some((name, index) => name !== expectedHomeMetaColumns[index])) {
|
|
819
|
+
throw new SqliteSchemaMigrationError("home_meta columns do not match the current storage contract", "schema object");
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
/** Return the one linear upgrade path from a supported source to this release. */
|
|
823
|
+
export function storageMigrationPlan(currentVersion) {
|
|
824
|
+
if (!Number.isInteger(currentVersion)
|
|
825
|
+
|| currentVersion < MIN_SUPPORTED_STORAGE_VERSION
|
|
826
|
+
|| currentVersion > CURRENT_STORAGE_VERSION) {
|
|
827
|
+
return null;
|
|
828
|
+
}
|
|
829
|
+
return MIGRATIONS
|
|
830
|
+
.filter(({ version }) => version > currentVersion)
|
|
831
|
+
.map(({ version, name, introducedIn }) => ({
|
|
832
|
+
fromVersion: version - 1,
|
|
833
|
+
toVersion: version,
|
|
834
|
+
name,
|
|
835
|
+
introducedIn
|
|
836
|
+
}));
|
|
783
837
|
}
|
|
784
838
|
/** Inspect a recognized migration prefix without changing it. */
|
|
785
839
|
export function inspectSqliteSchemaMigrations(db) {
|
|
786
840
|
const ledgerWasCreated = ensureMigrationLedger(db, "validate");
|
|
787
841
|
const applied = validateAppliedMigrations(db, ledgerWasCreated);
|
|
842
|
+
if (applied.currentVersion > CURRENT_STORAGE_VERSION) {
|
|
843
|
+
return {
|
|
844
|
+
currentVersion: applied.currentVersion,
|
|
845
|
+
currentChecksum: applied.currentChecksum,
|
|
846
|
+
targetVersion: CURRENT_STORAGE_VERSION,
|
|
847
|
+
minimumSupportedVersion: MIN_SUPPORTED_STORAGE_VERSION,
|
|
848
|
+
targetChecksum: checksum(MIGRATIONS.at(-1).sql),
|
|
849
|
+
pendingVersions: []
|
|
850
|
+
};
|
|
851
|
+
}
|
|
788
852
|
const pendingVersions = MIGRATIONS
|
|
789
|
-
.filter((migration) => !applied.has(migration.version))
|
|
853
|
+
.filter((migration) => !applied.versions.has(migration.version))
|
|
790
854
|
.map((migration) => migration.version);
|
|
791
855
|
if (pendingVersions.length === 0)
|
|
792
856
|
validateSchemaObjects(db);
|
|
793
|
-
const current = MIGRATIONS[applied.size - 1];
|
|
794
857
|
const target = MIGRATIONS.at(-1);
|
|
795
|
-
if (
|
|
858
|
+
if (applied.currentVersion === 0) {
|
|
796
859
|
throw new SqliteSchemaMigrationError("schema_migrations ledger has no current head");
|
|
797
860
|
}
|
|
798
861
|
return {
|
|
799
|
-
currentVersion: applied.
|
|
800
|
-
currentChecksum:
|
|
801
|
-
targetVersion:
|
|
862
|
+
currentVersion: applied.currentVersion,
|
|
863
|
+
currentChecksum: applied.currentChecksum,
|
|
864
|
+
targetVersion: CURRENT_STORAGE_VERSION,
|
|
865
|
+
minimumSupportedVersion: MIN_SUPPORTED_STORAGE_VERSION,
|
|
802
866
|
targetChecksum: checksum(target.sql),
|
|
803
867
|
pendingVersions
|
|
804
868
|
};
|
|
@@ -819,15 +883,26 @@ export function migrateSqliteSchema(db, options) {
|
|
|
819
883
|
// prevents a manually altered or partially recorded ledger from silently
|
|
820
884
|
// skipping a later schema/data step.
|
|
821
885
|
const applied = validateAppliedMigrations(db, ledgerWasCreated);
|
|
822
|
-
|
|
886
|
+
if (applied.currentVersion > CURRENT_STORAGE_VERSION) {
|
|
887
|
+
throw new SqliteSchemaMigrationError(`storage version ${applied.currentVersion} is newer than supported `
|
|
888
|
+
+ `${CURRENT_STORAGE_VERSION}`, "admission");
|
|
889
|
+
}
|
|
890
|
+
if (applied.currentVersion !== 0
|
|
891
|
+
&& applied.currentVersion < MIN_SUPPORTED_STORAGE_VERSION) {
|
|
892
|
+
throw new SqliteSchemaMigrationError(`storage version ${applied.currentVersion} is older than the minimum supported `
|
|
893
|
+
+ `${MIN_SUPPORTED_STORAGE_VERSION}`, "admission");
|
|
894
|
+
}
|
|
895
|
+
const pending = MIGRATIONS.filter((migration) => !applied.versions.has(migration.version));
|
|
823
896
|
if (!ledgerWasCreated && pending.length > 0 && options.mode === "validate") {
|
|
824
|
-
throw new SqliteSchemaMigrationError(`
|
|
897
|
+
throw new SqliteSchemaMigrationError(`Storage version ${applied.currentVersion} requires an explicit upgrade to `
|
|
898
|
+
+ `${CURRENT_STORAGE_VERSION}`, "admission");
|
|
825
899
|
}
|
|
826
900
|
const newlyApplied = [];
|
|
827
901
|
for (const migration of pending) {
|
|
828
902
|
db.exec(migration.sql);
|
|
829
|
-
|
|
830
|
-
|
|
903
|
+
const appliedAt = new Date().toISOString();
|
|
904
|
+
db.prepare(`INSERT INTO schema_migrations (version, name, applied_at, checksum)
|
|
905
|
+
VALUES (?, ?, ?, ?)`).run(migration.version, migration.name, appliedAt, checksum(migration.sql));
|
|
831
906
|
newlyApplied.push(migration.version);
|
|
832
907
|
}
|
|
833
908
|
validateSchemaObjects(db);
|
|
@@ -836,7 +911,7 @@ export function migrateSqliteSchema(db, options) {
|
|
|
836
911
|
const newlyApplied = options.mode === "apply" && !db.inTransaction
|
|
837
912
|
? db.transaction(migrate)()
|
|
838
913
|
: migrate();
|
|
839
|
-
return { applied: newlyApplied, version:
|
|
914
|
+
return { applied: newlyApplied, version: CURRENT_STORAGE_VERSION };
|
|
840
915
|
}
|
|
841
916
|
/** The names of every table the schema creates (for tests/introspection). */
|
|
842
917
|
export const SQLITE_SCHEMA_TABLES = [
|
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
* on the durable outbox.
|
|
18
18
|
* - Crash recovery .............. WAL rollback of uncommitted transactions;
|
|
19
19
|
* outbox replay of committed-but-unacked effects.
|
|
20
|
-
* - Record
|
|
20
|
+
* - Record validation ........... current record (incl. local schemaVersion)
|
|
21
|
+
* in payload.
|
|
21
22
|
* - Evidence retention .......... events/review_rounds/change_sets/
|
|
22
23
|
* integration_attempts are never pruned.
|
|
23
24
|
*
|
|
24
|
-
* Records are stored as full
|
|
25
|
+
* Records are stored as full current JSON in `payload` columns, with typed
|
|
25
26
|
* columns for the fields that are queried/filtered/used-for-CAS (§4). A
|
|
26
27
|
* high-frequency runtime telemetry observation is a single-row upsert into
|
|
27
28
|
* `telemetry` scoped by its primary key — it never rewrites global
|
|
@@ -51,7 +52,7 @@ import { managedWorkspaceKey } from "../worktree/managedWorkspace.js";
|
|
|
51
52
|
import { CURRENT_CONFIG_SCHEMA_VERSION, CURRENT_WORK_MAILBOX_SCHEMA_VERSION, executionLaneActiveTurnKey, executionLaneActiveTurnKeyParts, StorageConflictError, StorageCancelledError, StorageRecordError, storedCapabilityGrant, storedPublicationReference, storedReleaseWorkflow, isValidCapabilityGrantTransition, isValidReleaseWorkflowTransition, pendingWakeupProjection, validateYuiConfig } from "./taskStore.js";
|
|
52
53
|
import { publicationExternalKey } from "../task/publicationReference.js";
|
|
53
54
|
import { gateArtifactKey, validateGateArtifact } from "../verification/gateArtifact.js";
|
|
54
|
-
import { inspectSqliteSchemaMigrations, migrateSqliteSchema, SqliteSchemaMigrationError,
|
|
55
|
+
import { inspectSqliteSchemaMigrations, migrateSqliteSchema, SqliteSchemaMigrationError, TELEMETRY_KEEP_PER_GENERATION, TELEMETRY_TURN_CAP } from "./sqliteSchema.js";
|
|
55
56
|
import { StorageSchemaError } from "./storageSchema.js";
|
|
56
57
|
/** Read the immutable Home identity without opening a writable Store connection. */
|
|
57
58
|
export function readSqliteHomeIdentity(rootDir, databaseFilename = "yui.db") {
|
|
@@ -192,8 +193,9 @@ export class SqliteTaskStore {
|
|
|
192
193
|
#seedHomeMeta() {
|
|
193
194
|
const now = new Date().toISOString();
|
|
194
195
|
const identity = generateHomeIdentity(new Date());
|
|
195
|
-
this.#db.prepare(`INSERT OR IGNORE INTO home_meta
|
|
196
|
-
|
|
196
|
+
this.#db.prepare(`INSERT OR IGNORE INTO home_meta
|
|
197
|
+
(id, home_identity, revision, created_at, updated_at)
|
|
198
|
+
VALUES (1, ?, 0, ?, ?)`).run(JSON.stringify(identity), now, now);
|
|
197
199
|
}
|
|
198
200
|
#seedConfig() {
|
|
199
201
|
this.#db.prepare(`INSERT OR IGNORE INTO config (id, payload, updated_at) VALUES (1, ?, ?)`).run(JSON.stringify(DEFAULT_CONFIG), new Date().toISOString());
|