@cleocode/core 2026.9.25 → 2026.9.26
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/dist/admin/import-tasks.d.ts.map +1 -1
- package/dist/admin/import-tasks.js +5 -2
- package/dist/admin/import-tasks.js.map +1 -1
- package/dist/admin/import.d.ts.map +1 -1
- package/dist/admin/import.js +7 -2
- package/dist/admin/import.js.map +1 -1
- package/dist/build-provenance.json +2 -2
- package/dist/cloud/index.d.ts +1 -0
- package/dist/cloud/index.d.ts.map +1 -1
- package/dist/cloud/index.js +1 -0
- package/dist/cloud/index.js.map +1 -1
- package/dist/cloud/nexus-auth.d.ts +26 -1
- package/dist/cloud/nexus-auth.d.ts.map +1 -1
- package/dist/cloud/nexus-auth.js +61 -32
- package/dist/cloud/nexus-auth.js.map +1 -1
- package/dist/cloud/nexus-credentials.js +2 -2
- package/dist/cloud/nexus-credentials.js.map +1 -1
- package/dist/cloud/nexus-device.d.ts +809 -0
- package/dist/cloud/nexus-device.d.ts.map +1 -0
- package/dist/cloud/nexus-device.js +1680 -0
- package/dist/cloud/nexus-device.js.map +1 -0
- package/dist/cloud/nexus-enrol.d.ts +210 -0
- package/dist/cloud/nexus-enrol.d.ts.map +1 -0
- package/dist/cloud/nexus-enrol.js +1023 -0
- package/dist/cloud/nexus-enrol.js.map +1 -0
- package/dist/cloud/nexus-link.d.ts +3 -0
- package/dist/cloud/nexus-link.d.ts.map +1 -1
- package/dist/cloud/nexus-link.js +38 -4
- package/dist/cloud/nexus-link.js.map +1 -1
- package/dist/cloud/signing.d.ts +20 -0
- package/dist/cloud/signing.d.ts.map +1 -1
- package/dist/cloud/signing.js +14 -0
- package/dist/cloud/signing.js.map +1 -1
- package/dist/crypto/credentials.d.ts +61 -0
- package/dist/crypto/credentials.d.ts.map +1 -1
- package/dist/crypto/credentials.js +154 -58
- package/dist/crypto/credentials.js.map +1 -1
- package/dist/docs/export-document.js +830 -190
- package/dist/docs/export-document.js.map +3 -3
- package/dist/doctor/dependency-cycles.d.ts +41 -0
- package/dist/doctor/dependency-cycles.d.ts.map +1 -0
- package/dist/doctor/dependency-cycles.js +39 -0
- package/dist/doctor/dependency-cycles.js.map +1 -0
- package/dist/doctor/index.d.ts +2 -0
- package/dist/doctor/index.d.ts.map +1 -1
- package/dist/doctor/index.js +1 -0
- package/dist/doctor/index.js.map +1 -1
- package/dist/doctor/row-identity.d.ts +11 -0
- package/dist/doctor/row-identity.d.ts.map +1 -1
- package/dist/doctor/row-identity.js +67 -9
- package/dist/doctor/row-identity.js.map +1 -1
- package/dist/error-catalog.d.ts.map +1 -1
- package/dist/error-catalog.js +4 -0
- package/dist/error-catalog.js.map +1 -1
- package/dist/error-registry.d.ts.map +1 -1
- package/dist/error-registry.js +8 -0
- package/dist/error-registry.js.map +1 -1
- package/dist/llm/plugin-facade.js +857 -217
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/nexus/workspace.d.ts.map +1 -1
- package/dist/nexus/workspace.js +54 -4
- package/dist/nexus/workspace.js.map +1 -1
- package/dist/orchestrate/lifecycle-ops.js +1 -1
- package/dist/orchestrate/lifecycle-ops.js.map +1 -1
- package/dist/orchestrate/pivot.d.ts.map +1 -1
- package/dist/orchestrate/pivot.js +4 -2
- package/dist/orchestrate/pivot.js.map +1 -1
- package/dist/orchestrate/query-ops.d.ts.map +1 -1
- package/dist/orchestrate/query-ops.js +3 -3
- package/dist/orchestrate/query-ops.js.map +1 -1
- package/dist/orchestrate/spawn-ops.js +1 -1
- package/dist/orchestrate/spawn-ops.js.map +1 -1
- package/dist/orchestration/index.js +1 -1
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/lead-rollup.d.ts.map +1 -1
- package/dist/orchestration/lead-rollup.js +3 -3
- package/dist/orchestration/lead-rollup.js.map +1 -1
- package/dist/orchestration/parallel.js +1 -1
- package/dist/orchestration/parallel.js.map +1 -1
- package/dist/orchestration/wave-topic.d.ts +4 -2
- package/dist/orchestration/wave-topic.d.ts.map +1 -1
- package/dist/orchestration/wave-topic.js +6 -4
- package/dist/orchestration/wave-topic.js.map +1 -1
- package/dist/orchestration/waves.d.ts +2 -1
- package/dist/orchestration/waves.d.ts.map +1 -1
- package/dist/orchestration/waves.js +4 -3
- package/dist/orchestration/waves.js.map +1 -1
- package/dist/phases/index.d.ts.map +1 -1
- package/dist/phases/index.js +4 -2
- package/dist/phases/index.js.map +1 -1
- package/dist/selfimprove/fix-gen.js +856 -216
- package/dist/selfimprove/fix-gen.js.map +3 -3
- package/dist/session/engine-ops.d.ts.map +1 -1
- package/dist/session/engine-ops.js +77 -49
- package/dist/session/engine-ops.js.map +1 -1
- package/dist/sessions/focus-state-store.d.ts +69 -23
- package/dist/sessions/focus-state-store.d.ts.map +1 -1
- package/dist/sessions/focus-state-store.js +113 -27
- package/dist/sessions/focus-state-store.js.map +1 -1
- package/dist/sessions/handoff.js +1 -1
- package/dist/sessions/handoff.js.map +1 -1
- package/dist/sessions/index.d.ts.map +1 -1
- package/dist/sessions/index.js +24 -13
- package/dist/sessions/index.js.map +1 -1
- package/dist/sessions/terminal-identity.d.ts +165 -17
- package/dist/sessions/terminal-identity.d.ts.map +1 -1
- package/dist/sessions/terminal-identity.js +341 -32
- package/dist/sessions/terminal-identity.js.map +1 -1
- package/dist/skills/orchestrator/startup.js +2 -2
- package/dist/skills/orchestrator/startup.js.map +1 -1
- package/dist/snapshot/index.d.ts +4 -0
- package/dist/snapshot/index.d.ts.map +1 -1
- package/dist/snapshot/index.js +50 -3
- package/dist/snapshot/index.js.map +1 -1
- package/dist/store/db-helpers.d.ts +15 -2
- package/dist/store/db-helpers.d.ts.map +1 -1
- package/dist/store/db-helpers.js +84 -3
- package/dist/store/db-helpers.js.map +1 -1
- package/dist/store/dependency-cycles.d.ts +164 -0
- package/dist/store/dependency-cycles.d.ts.map +1 -0
- package/dist/store/dependency-cycles.js +360 -0
- package/dist/store/dependency-cycles.js.map +1 -0
- package/dist/store/display-id-alias.d.ts +93 -37
- package/dist/store/display-id-alias.d.ts.map +1 -1
- package/dist/store/display-id-alias.js +590 -115
- package/dist/store/display-id-alias.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +34 -7
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/exodus/migrate.d.ts.map +1 -1
- package/dist/store/exodus/migrate.js +8 -1
- package/dist/store/exodus/migrate.js.map +1 -1
- package/dist/store/global-salt.d.ts +35 -0
- package/dist/store/global-salt.d.ts.map +1 -1
- package/dist/store/global-salt.js +136 -16
- package/dist/store/global-salt.js.map +1 -1
- package/dist/store/migration-sqlite.d.ts.map +1 -1
- package/dist/store/migration-sqlite.js +19 -11
- package/dist/store/migration-sqlite.js.map +1 -1
- package/dist/store/portable-bundle-scan.d.ts.map +1 -1
- package/dist/store/portable-bundle-scan.js +6 -0
- package/dist/store/portable-bundle-scan.js.map +1 -1
- package/dist/store/row-identity-registry.d.ts.map +1 -1
- package/dist/store/row-identity-registry.js +11 -3
- package/dist/store/row-identity-registry.js.map +1 -1
- package/dist/store/row-identity.d.ts +91 -1
- package/dist/store/row-identity.d.ts.map +1 -1
- package/dist/store/row-identity.js +276 -7
- package/dist/store/row-identity.js.map +1 -1
- package/dist/store/safety-data-accessor.d.ts +3 -2
- package/dist/store/safety-data-accessor.d.ts.map +1 -1
- package/dist/store/safety-data-accessor.js +5 -2
- package/dist/store/safety-data-accessor.js.map +1 -1
- package/dist/store/session-store.d.ts +63 -3
- package/dist/store/session-store.d.ts.map +1 -1
- package/dist/store/session-store.js +121 -8
- package/dist/store/session-store.js.map +1 -1
- package/dist/store/split-brain-import.d.ts.map +1 -1
- package/dist/store/split-brain-import.js +36 -0
- package/dist/store/split-brain-import.js.map +1 -1
- package/dist/store/sqlite-data-accessor.d.ts +50 -3
- package/dist/store/sqlite-data-accessor.d.ts.map +1 -1
- package/dist/store/sqlite-data-accessor.js +246 -13
- package/dist/store/sqlite-data-accessor.js.map +1 -1
- package/dist/store/tasks-sqlite.d.ts.map +1 -1
- package/dist/store/tasks-sqlite.js +14 -2
- package/dist/store/tasks-sqlite.js.map +1 -1
- package/dist/store/umbrella-data-accessor.d.ts +3 -2
- package/dist/store/umbrella-data-accessor.d.ts.map +1 -1
- package/dist/store/umbrella-data-accessor.js +5 -2
- package/dist/store/umbrella-data-accessor.js.map +1 -1
- package/dist/system/health.d.ts +2 -0
- package/dist/system/health.d.ts.map +1 -1
- package/dist/system/health.js +54 -0
- package/dist/system/health.js.map +1 -1
- package/dist/task-work/index.d.ts.map +1 -1
- package/dist/task-work/index.js +9 -6
- package/dist/task-work/index.js.map +1 -1
- package/dist/tasks/analyze.d.ts.map +1 -1
- package/dist/tasks/analyze.js +3 -2
- package/dist/tasks/analyze.js.map +1 -1
- package/dist/tasks/evidence.d.ts +19 -1
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +79 -18
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/infer-add-params.js +1 -1
- package/dist/tasks/infer-add-params.js.map +1 -1
- package/dist/tasks/task-context.d.ts.map +1 -1
- package/dist/tasks/task-context.js +3 -1
- package/dist/tasks/task-context.js.map +1 -1
- package/dist/tasks/task-import.d.ts.map +1 -1
- package/dist/tasks/task-import.js +11 -3
- package/dist/tasks/task-import.js.map +1 -1
- package/dist/tasks/task-next.d.ts +5 -1
- package/dist/tasks/task-next.d.ts.map +1 -1
- package/dist/tasks/task-next.js +7 -2
- package/dist/tasks/task-next.js.map +1 -1
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +3 -2
- package/dist/validation/engine-ops.js.map +1 -1
- package/dist/workgraph/scaffold-apply.d.ts.map +1 -1
- package/dist/workgraph/scaffold-apply.js +14 -5
- package/dist/workgraph/scaffold-apply.js.map +1 -1
- package/migrations/drizzle-cleo-project/20260930160000_t12886-dependency-cycle-guard/migration.sql +76 -0
- package/migrations/drizzle-cleo-project/20260930160000_t12886-dependency-cycle-guard/revert.sql +7 -0
- package/package.json +13 -13
- package/templates/CLEO-INJECTION.md +2 -2
- package/templates/CLEO-REFERENCE.md +1 -1
|
@@ -2009,7 +2009,7 @@ var init_output_contracts_data = __esm({
|
|
|
2009
2009
|
// T12503: the optimistic-concurrency version agents pass to --if-match.
|
|
2010
2010
|
updatedAt: {
|
|
2011
2011
|
type: ["string", "null"],
|
|
2012
|
-
description: "Task version for optimistic concurrency: pass it to `cleo update|complete --if-match`."
|
|
2012
|
+
description: "Task version for optimistic concurrency: pass it to `cleo update|complete --if-match`. A stale version fails with E_CONFLICT (23); E_TASK_RENAMED (26) when sync re-numbered the task you read (details.expected is its new id)."
|
|
2013
2013
|
},
|
|
2014
2014
|
// T12502: the human assignee and the agent claim lease are separate.
|
|
2015
2015
|
assignee: {
|
|
@@ -13270,6 +13270,7 @@ var init_exit_codes = __esm({
|
|
|
13270
13270
|
ExitCode2[ExitCode2["VERSION_CONFLICT"] = 23] = "VERSION_CONFLICT";
|
|
13271
13271
|
ExitCode2[ExitCode2["SESSION_UNBOUND"] = 24] = "SESSION_UNBOUND";
|
|
13272
13272
|
ExitCode2[ExitCode2["WORKTREE_LOCKED"] = 25] = "WORKTREE_LOCKED";
|
|
13273
|
+
ExitCode2[ExitCode2["TASK_RENAMED"] = 26] = "TASK_RENAMED";
|
|
13273
13274
|
ExitCode2[ExitCode2["SESSION_EXISTS"] = 30] = "SESSION_EXISTS";
|
|
13274
13275
|
ExitCode2[ExitCode2["SESSION_NOT_FOUND"] = 31] = "SESSION_NOT_FOUND";
|
|
13275
13276
|
ExitCode2[ExitCode2["SCOPE_CONFLICT"] = 32] = "SCOPE_CONFLICT";
|
|
@@ -18059,6 +18060,19 @@ var init_error_catalog = __esm({
|
|
|
18059
18060
|
`Bind a session: run 'cleo session start --scope global --name "<name>"', 'cleo session resume <id>', or set CLEO_SESSION_ID=<id>.`
|
|
18060
18061
|
)
|
|
18061
18062
|
],
|
|
18063
|
+
[
|
|
18064
|
+
26 /* TASK_RENAMED */,
|
|
18065
|
+
def(
|
|
18066
|
+
26 /* TASK_RENAMED */,
|
|
18067
|
+
"TASK_RENAMED",
|
|
18068
|
+
"CONFLICT",
|
|
18069
|
+
"Task was re-numbered by sync",
|
|
18070
|
+
409,
|
|
18071
|
+
true,
|
|
18072
|
+
"E_TASK_RENAMED",
|
|
18073
|
+
"The task you addressed now has another id (a display-id collision re-numbered it). Re-read it with 'cleo show <new id>' and retry against that id."
|
|
18074
|
+
)
|
|
18075
|
+
],
|
|
18062
18076
|
[
|
|
18063
18077
|
25 /* WORKTREE_LOCKED */,
|
|
18064
18078
|
def(
|
|
@@ -20006,10 +20020,10 @@ var init_table2 = __esm({
|
|
|
20006
20020
|
[IsDrizzleTable] = true;
|
|
20007
20021
|
/** @internal */
|
|
20008
20022
|
[ExtraConfigBuilder] = void 0;
|
|
20009
|
-
constructor(name15, schema,
|
|
20023
|
+
constructor(name15, schema, baseName2) {
|
|
20010
20024
|
this[TableName] = this[OriginalName] = name15;
|
|
20011
20025
|
this[TableSchema] = schema;
|
|
20012
|
-
this[BaseName] =
|
|
20026
|
+
this[BaseName] = baseName2;
|
|
20013
20027
|
}
|
|
20014
20028
|
};
|
|
20015
20029
|
}
|
|
@@ -21939,9 +21953,9 @@ var init_casing = __esm({
|
|
|
21939
21953
|
});
|
|
21940
21954
|
|
|
21941
21955
|
// node_modules/.pnpm/drizzle-orm@1.0.0-rc.4_@opentelemetry+api@1.9.0_@sinclair+typebox@0.34.49_@types+mssql@_b4e81f2ea693a7363d3e5dc2205249c6/node_modules/drizzle-orm/sqlite-core/table.js
|
|
21942
|
-
function sqliteTableBase(name15, columns, extraConfig, schema, casing,
|
|
21956
|
+
function sqliteTableBase(name15, columns, extraConfig, schema, casing, baseName2 = name15) {
|
|
21943
21957
|
const casingFn = getCasingFn(casing);
|
|
21944
|
-
const rawTable = new SQLiteTable(name15, schema,
|
|
21958
|
+
const rawTable = new SQLiteTable(name15, schema, baseName2);
|
|
21945
21959
|
const parsedColumns = typeof columns === "function" ? columns(getSQLiteColumnBuilders()) : columns;
|
|
21946
21960
|
const builtColumns = Object.fromEntries(Object.entries(parsedColumns).map(([name16, colBuilderBase]) => {
|
|
21947
21961
|
const colBuilder = colBuilderBase;
|
|
@@ -25707,6 +25721,10 @@ function decisionFor(dbPath) {
|
|
|
25707
25721
|
if (!decisions.has(key)) decisions.set(key, schemaWriteRefusal(key));
|
|
25708
25722
|
return decisions.get(key) ?? null;
|
|
25709
25723
|
}
|
|
25724
|
+
function schemaWritesAllowed(nativeDb) {
|
|
25725
|
+
const dbPath = nativeDb.location();
|
|
25726
|
+
return !dbPath || decisionFor(dbPath) === null;
|
|
25727
|
+
}
|
|
25710
25728
|
function isWorktreeBuildSchemaError(error48) {
|
|
25711
25729
|
return error48 instanceof Error && error48.message.includes(E_WORKTREE_BUILD_SCHEMA);
|
|
25712
25730
|
}
|
|
@@ -26745,7 +26763,10 @@ var init_row_identity_registry = __esm({
|
|
|
26745
26763
|
key: ["id"],
|
|
26746
26764
|
birth: "recorded_at",
|
|
26747
26765
|
content: ["ac_id", "previous_text", "reason"],
|
|
26748
|
-
|
|
26766
|
+
// v2 (T12802): no @refFp: the criterion's fingerprint is unknowable when
|
|
26767
|
+
// it was gone before this row got its identity, so it made the value
|
|
26768
|
+
// depend on fill timing. ac_id is always known.
|
|
26769
|
+
birthFacts: ["ac_id", "previous_text", "reason"],
|
|
26749
26770
|
storedRefUids: [{ column: "ac_uid", from: "ac_id", table: ACS }],
|
|
26750
26771
|
task: "T12341"
|
|
26751
26772
|
},
|
|
@@ -26754,7 +26775,10 @@ var init_row_identity_registry = __esm({
|
|
|
26754
26775
|
kind: "minted",
|
|
26755
26776
|
key: ["id"],
|
|
26756
26777
|
birth: "created_at",
|
|
26757
|
-
|
|
26778
|
+
// v2 (T12802): ac_id in place of @refFp:ac_uid and ac_text_hash. Both
|
|
26779
|
+
// were filled from the criterion, so a backfilled binding whose
|
|
26780
|
+
// criterion was already gone got a different value (see AC history).
|
|
26781
|
+
birthFacts: ["evidence_atom_id", "binding_type", "ac_id"],
|
|
26758
26782
|
storedRefUids: [
|
|
26759
26783
|
{ column: "ac_uid", from: "ac_id", table: ACS },
|
|
26760
26784
|
{ column: "ac_text_hash", from: "ac_id", table: ACS, source: "text_hash" }
|
|
@@ -26796,7 +26820,9 @@ var init_row_identity_registry = __esm({
|
|
|
26796
26820
|
// The uid IS the primary key: display-id-alias.ts computes it on write.
|
|
26797
26821
|
table: "tasks_display_id_aliases",
|
|
26798
26822
|
kind: "natural",
|
|
26799
|
-
|
|
26823
|
+
// T12800: the reason is part of the key (collision-remint and
|
|
26824
|
+
// remint-assigned of one id and row are distinct facts).
|
|
26825
|
+
key: ["entity_table", "display_id", "entity_uid", "reason"],
|
|
26800
26826
|
task: "T12341"
|
|
26801
26827
|
},
|
|
26802
26828
|
{
|
|
@@ -27378,6 +27404,20 @@ function installRowUidTriggers(db, scope) {
|
|
|
27378
27404
|
);
|
|
27379
27405
|
}
|
|
27380
27406
|
}
|
|
27407
|
+
function v1ReleaseBirthFp(db, table, row) {
|
|
27408
|
+
const col = (c) => row[c] ?? null;
|
|
27409
|
+
const facts = table === "tasks_task_acceptance_criteria_history" ? [col("ac_id"), col("previous_text"), col("reason")] : table === "tasks_evidence_ac_bindings" ? [col("evidence_atom_id"), col("binding_type"), col("ac_text_hash")] : [];
|
|
27410
|
+
if (facts.length === 0) return null;
|
|
27411
|
+
const acUid = col("ac_uid");
|
|
27412
|
+
let ref = "ref:none";
|
|
27413
|
+
if (acUid !== null) {
|
|
27414
|
+
const ac = db.prepare("SELECT birth_fp AS fp FROM main.tasks_task_acceptance_criteria WHERE uid = ?").get(acUid);
|
|
27415
|
+
ref = ac === void 0 ? "ref:missing" : ac.fp;
|
|
27416
|
+
if (ref === null) return null;
|
|
27417
|
+
}
|
|
27418
|
+
const spec = rowIdentitySpec("project", table);
|
|
27419
|
+
return birthFingerprint(table, spec?.birth ? col(spec.birth) : null, [...facts, ref]);
|
|
27420
|
+
}
|
|
27381
27421
|
function hasObject(db, type, name15) {
|
|
27382
27422
|
return db.prepare("SELECT 1 FROM main.sqlite_master WHERE type = ? AND name = ?").get(type, name15) !== void 0;
|
|
27383
27423
|
}
|
|
@@ -27461,24 +27501,41 @@ function preReleaseBirthFp(db, table, row) {
|
|
|
27461
27501
|
function resetStaleIdentity(db, scope, writers) {
|
|
27462
27502
|
if (scope !== "project" || !hasTable(db, ROW_IDENTITY_META_TABLE)) return "none";
|
|
27463
27503
|
if (readMeta(db, ROW_IDENTITY_RECIPE_KEY) === ROW_IDENTITY_RECIPE) return "none";
|
|
27464
|
-
const minted = ROW_IDENTITY.project.filter(
|
|
27465
|
-
(spec) =>
|
|
27504
|
+
const minted = fingerprintOrder("project", ROW_IDENTITY.project).filter(
|
|
27505
|
+
(spec) => hasTable(db, spec.table) && columnsOf(db, spec.table).has(BIRTH_FP_COLUMN)
|
|
27466
27506
|
);
|
|
27467
27507
|
const stale = [];
|
|
27508
|
+
const cleared = /* @__PURE__ */ new Map();
|
|
27509
|
+
const mark = (table, column, value) => {
|
|
27510
|
+
if (value === null || value === void 0) return;
|
|
27511
|
+
const key = `${table}.${column}`;
|
|
27512
|
+
const set2 = cleared.get(key) ?? /* @__PURE__ */ new Set();
|
|
27513
|
+
set2.add(String(value));
|
|
27514
|
+
cleared.set(key, set2);
|
|
27515
|
+
};
|
|
27468
27516
|
for (const spec of minted) {
|
|
27517
|
+
const deps = (spec.birthFacts ?? []).map((fact) => fingerprintRef("project", spec, fact)).filter((d) => d !== null);
|
|
27518
|
+
const keyColumn = targetKey("project", spec.table);
|
|
27469
27519
|
const rows = db.prepare(
|
|
27470
27520
|
`SELECT rowid AS _rowid, * FROM main.${q(spec.table)} WHERE ${q(BIRTH_FP_COLUMN)} IS NOT NULL`
|
|
27471
27521
|
).all();
|
|
27472
27522
|
for (const row of rows) {
|
|
27473
|
-
|
|
27523
|
+
const derivedFromStale = deps.some(
|
|
27524
|
+
(d) => cleared.get(`${d.table}.${d.key}`)?.has(String(row[d.column] ?? ""))
|
|
27525
|
+
);
|
|
27526
|
+
if (derivedFromStale || row[BIRTH_FP_COLUMN] === preReleaseBirthFp(db, spec.table, row) || row[BIRTH_FP_COLUMN] === v1ReleaseBirthFp(db, spec.table, row)) {
|
|
27474
27527
|
stale.push({ table: spec.table, rowid: row._rowid });
|
|
27528
|
+
mark(spec.table, keyColumn, row[keyColumn]);
|
|
27529
|
+
mark(spec.table, UID_COLUMN, row[UID_COLUMN]);
|
|
27475
27530
|
}
|
|
27476
27531
|
}
|
|
27477
27532
|
}
|
|
27478
|
-
|
|
27533
|
+
const graveyardRows = scope === "project" && hasTable(db, AC_UID_GRAVEYARD) ? db.prepare(`SELECT count(*) AS n FROM main.${AC_UID_GRAVEYARD}`).get().n : 0;
|
|
27534
|
+
if (stale.length === 0 && graveyardRows === 0) return "none";
|
|
27479
27535
|
if (readMeta(db, ROW_IDENTITY_SYNCED_KEY) !== void 0) return "refused";
|
|
27480
27536
|
db.exec("SAVEPOINT row_identity_reset");
|
|
27481
27537
|
try {
|
|
27538
|
+
if (graveyardRows > 0) writers.clearAcUidGraveyardNative(db);
|
|
27482
27539
|
for (const { table, rowid } of stale) {
|
|
27483
27540
|
writers.clearBirthFpNative(db, table, rowid);
|
|
27484
27541
|
}
|
|
@@ -27494,6 +27551,106 @@ function writeRecipeMarker(db, writers = requireWriters()) {
|
|
|
27494
27551
|
if (!hasTable(db, ROW_IDENTITY_META_TABLE)) return;
|
|
27495
27552
|
writers.writeRowIdentityMetaNative(db, ROW_IDENTITY_RECIPE_KEY, ROW_IDENTITY_RECIPE);
|
|
27496
27553
|
}
|
|
27554
|
+
function rowIdentityShared(db) {
|
|
27555
|
+
return readMeta(db, ROW_IDENTITY_SYNCED_KEY) !== void 0;
|
|
27556
|
+
}
|
|
27557
|
+
function healRowIdentitySchema(db, scope, writers = registeredWriters) {
|
|
27558
|
+
const log15 = getLogger("row-identity");
|
|
27559
|
+
if (ROW_IDENTITY[scope].length === 0) {
|
|
27560
|
+
return [];
|
|
27561
|
+
}
|
|
27562
|
+
if (!schemaWritesAllowed(db)) {
|
|
27563
|
+
log15.debug({ scope }, "row identity schema heal skipped: schema writes refused for this build");
|
|
27564
|
+
return [];
|
|
27565
|
+
}
|
|
27566
|
+
try {
|
|
27567
|
+
db.exec("SAVEPOINT row_identity_heal");
|
|
27568
|
+
try {
|
|
27569
|
+
const healed = [
|
|
27570
|
+
...scope === "project" ? ensureIdentityTables(db) : [],
|
|
27571
|
+
...ensureRowIdentitySchema(db, scope)
|
|
27572
|
+
];
|
|
27573
|
+
if (healed.length > 0) recordHealReceipt(db, scope, healed, writers);
|
|
27574
|
+
db.exec("RELEASE SAVEPOINT row_identity_heal");
|
|
27575
|
+
if (healed.length > 0)
|
|
27576
|
+
log15.info({ scope, healed: healed.length }, "row identity schema healed");
|
|
27577
|
+
return healed;
|
|
27578
|
+
} catch (error48) {
|
|
27579
|
+
db.exec("ROLLBACK TO SAVEPOINT row_identity_heal");
|
|
27580
|
+
db.exec("RELEASE SAVEPOINT row_identity_heal");
|
|
27581
|
+
throw error48;
|
|
27582
|
+
}
|
|
27583
|
+
} catch (error48) {
|
|
27584
|
+
log15.error({ scope, error: error48 }, "row identity schema heal failed");
|
|
27585
|
+
return [];
|
|
27586
|
+
}
|
|
27587
|
+
}
|
|
27588
|
+
function recordHealReceipt(db, scope, healed, writers) {
|
|
27589
|
+
const table = HEAL_RECEIPT_TABLE[scope];
|
|
27590
|
+
const log15 = getLogger("row-identity");
|
|
27591
|
+
if (table === null || !hasTable(db, table) || !writers) {
|
|
27592
|
+
log15.warn({ scope, healed: healed.length }, "row identity schema healed; no receipt table");
|
|
27593
|
+
return;
|
|
27594
|
+
}
|
|
27595
|
+
const objects = healed.map((stmt) => {
|
|
27596
|
+
const col = /ALTER TABLE main\.("?)(\w+)\1 ADD COLUMN ("?)(\w+)\3/.exec(stmt);
|
|
27597
|
+
if (col) return `${col[2]}.${col[4]}`;
|
|
27598
|
+
const obj = /(TABLE|INDEX|TRIGGER) IF NOT EXISTS main\.("?)(\w+)\2/.exec(stmt);
|
|
27599
|
+
return obj ? `${obj[1].toLowerCase()} ${obj[3]}` : stmt.slice(0, 60);
|
|
27600
|
+
});
|
|
27601
|
+
const receipt2 = {
|
|
27602
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27603
|
+
scope,
|
|
27604
|
+
statements: healed.length,
|
|
27605
|
+
objects
|
|
27606
|
+
};
|
|
27607
|
+
const history = [...readRowIdentityHealHistory(db), receipt2].slice(-HEAL_RECEIPTS_KEPT);
|
|
27608
|
+
writers.writeRowIdentityMetaNative(db, ROW_IDENTITY_HEAL_KEY, JSON.stringify(history));
|
|
27609
|
+
}
|
|
27610
|
+
function readRowIdentityHealHistory(db) {
|
|
27611
|
+
const raw = readMeta(db, ROW_IDENTITY_HEAL_KEY);
|
|
27612
|
+
if (raw === void 0) return [];
|
|
27613
|
+
try {
|
|
27614
|
+
const parsed = JSON.parse(raw);
|
|
27615
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
27616
|
+
} catch {
|
|
27617
|
+
return [];
|
|
27618
|
+
}
|
|
27619
|
+
}
|
|
27620
|
+
function missingRowIdentitySchema(db) {
|
|
27621
|
+
if (!hasTable(db, "tasks_task_acceptance_criteria")) return [];
|
|
27622
|
+
const missing = [];
|
|
27623
|
+
for (const table of Object.keys(IDENTITY_TABLE_DDL)) {
|
|
27624
|
+
if (!hasTable(db, table)) missing.push(`table ${table}`);
|
|
27625
|
+
}
|
|
27626
|
+
for (const [table, column] of [
|
|
27627
|
+
["tasks_display_id_aliases", "displaced_hlc"],
|
|
27628
|
+
["tasks_display_id_aliases", "entity_birth_fp"],
|
|
27629
|
+
[AC_UID_GRAVEYARD, "birth_fp"]
|
|
27630
|
+
]) {
|
|
27631
|
+
if (hasTable(db, table) && !columnsOf(db, table).has(column)) {
|
|
27632
|
+
missing.push(`column ${table}.${column}`);
|
|
27633
|
+
}
|
|
27634
|
+
}
|
|
27635
|
+
if (!hasObject(db, "trigger", "trg_tasks_ac_uid_graveyard")) {
|
|
27636
|
+
missing.push("trigger trg_tasks_ac_uid_graveyard");
|
|
27637
|
+
}
|
|
27638
|
+
for (const spec of ROW_IDENTITY.project) {
|
|
27639
|
+
if (!hasTable(db, spec.table)) continue;
|
|
27640
|
+
const cols = columnsOf(db, spec.table);
|
|
27641
|
+
for (const column of rowIdentityColumns("project", spec.table)) {
|
|
27642
|
+
if (!cols.has(column)) missing.push(`column ${spec.table}.${column}`);
|
|
27643
|
+
}
|
|
27644
|
+
if (!uidIsPrimaryKey(db, spec.table) && !hasObject(db, "index", `uq_${spec.table}_uid`)) {
|
|
27645
|
+
missing.push(`index uq_${spec.table}_uid`);
|
|
27646
|
+
}
|
|
27647
|
+
for (const ref of spec.storedRefUids ?? []) {
|
|
27648
|
+
const index2 = `idx_${spec.table}_${ref.column}`;
|
|
27649
|
+
if (!hasObject(db, "index", index2)) missing.push(`index ${index2}`);
|
|
27650
|
+
}
|
|
27651
|
+
}
|
|
27652
|
+
return missing;
|
|
27653
|
+
}
|
|
27497
27654
|
function prepareRowIdentity(db, scope, options = {}) {
|
|
27498
27655
|
if (ROW_IDENTITY[scope].length === 0) return null;
|
|
27499
27656
|
if (!rowUidFillEnabled()) return null;
|
|
@@ -27532,7 +27689,7 @@ function prepareRowIdentity(db, scope, options = {}) {
|
|
|
27532
27689
|
return null;
|
|
27533
27690
|
}
|
|
27534
27691
|
}
|
|
27535
|
-
var ROW_UID_DOMAIN, ROW_BIRTH_DOMAIN, ROW_UID_SQL_FUNCTION, ROW_BIRTH_FP_SQL_FUNCTION, ROW_RANDOM_UID_SQL_FUNCTION, AC_TEXT_HASH_SQL_FUNCTION, AC_UID_GRAVEYARD, registeredWriters, STORE_TIMESTAMP, MAX_UUID_MS, ROW_IDENTITY_RECIPE, ROW_IDENTITY_META_TABLE, ROW_IDENTITY_RECIPE_KEY, ROW_IDENTITY_SYNCED_KEY, IDENTITY_TABLE_DDL, AC_UID_GRAVEYARD_TRIGGER;
|
|
27692
|
+
var ROW_UID_DOMAIN, ROW_BIRTH_DOMAIN, ROW_UID_SQL_FUNCTION, ROW_BIRTH_FP_SQL_FUNCTION, ROW_RANDOM_UID_SQL_FUNCTION, AC_TEXT_HASH_SQL_FUNCTION, AC_UID_GRAVEYARD, registeredWriters, STORE_TIMESTAMP, MAX_UUID_MS, ROW_IDENTITY_RECIPE, ROW_IDENTITY_META_TABLE, ROW_IDENTITY_RECIPE_KEY, ROW_IDENTITY_SYNCED_KEY, IDENTITY_TABLE_DDL, AC_UID_GRAVEYARD_TRIGGER, ROW_IDENTITY_HEAL_KEY, HEAL_RECEIPT_TABLE, HEAL_RECEIPTS_KEPT;
|
|
27536
27693
|
var init_row_identity = __esm({
|
|
27537
27694
|
"packages/core/src/store/row-identity.ts"() {
|
|
27538
27695
|
"use strict";
|
|
@@ -27541,6 +27698,7 @@ var init_row_identity = __esm({
|
|
|
27541
27698
|
init_ac_table();
|
|
27542
27699
|
init_row_identity_flag();
|
|
27543
27700
|
init_row_identity_registry();
|
|
27701
|
+
init_worktree_build_guard();
|
|
27544
27702
|
ROW_UID_DOMAIN = "cleo/row-uid/v1";
|
|
27545
27703
|
ROW_BIRTH_DOMAIN = "cleo/row-birth/v1";
|
|
27546
27704
|
ROW_UID_SQL_FUNCTION = "cleo_row_uid";
|
|
@@ -27550,7 +27708,7 @@ var init_row_identity = __esm({
|
|
|
27550
27708
|
AC_UID_GRAVEYARD = "tasks_ac_uid_graveyard";
|
|
27551
27709
|
STORE_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?)?(Z|[+-]\d{2}:?\d{2})?$/;
|
|
27552
27710
|
MAX_UUID_MS = 2 ** 48 - 1;
|
|
27553
|
-
ROW_IDENTITY_RECIPE = "cleo/row-identity/
|
|
27711
|
+
ROW_IDENTITY_RECIPE = "cleo/row-identity/v2";
|
|
27554
27712
|
ROW_IDENTITY_META_TABLE = "tasks_row_identity_meta";
|
|
27555
27713
|
ROW_IDENTITY_RECIPE_KEY = "row_identity_recipe";
|
|
27556
27714
|
ROW_IDENTITY_SYNCED_KEY = "row_identity_synced";
|
|
@@ -27595,6 +27753,15 @@ BEGIN
|
|
|
27595
27753
|
INSERT INTO ${AC_UID_GRAVEYARD} (ac_id, uid, task_id, ordinal, text, birth_fp, deleted_at)
|
|
27596
27754
|
VALUES (OLD.id, OLD.uid, OLD.task_id, OLD.ordinal, OLD.text, OLD.birth_fp, strftime('%Y-%m-%dT%H:%M:%fZ', 'now'));
|
|
27597
27755
|
END`;
|
|
27756
|
+
ROW_IDENTITY_HEAL_KEY = "row_identity_schema_healed";
|
|
27757
|
+
HEAL_RECEIPT_TABLE = {
|
|
27758
|
+
project: ROW_IDENTITY_META_TABLE,
|
|
27759
|
+
// The global store declares no identity table yet (ROW_IDENTITY.global is
|
|
27760
|
+
// empty, so its heal never runs); the change that declares one adds its
|
|
27761
|
+
// meta table here.
|
|
27762
|
+
global: null
|
|
27763
|
+
};
|
|
27764
|
+
HEAL_RECEIPTS_KEPT = 20;
|
|
27598
27765
|
}
|
|
27599
27766
|
});
|
|
27600
27767
|
|
|
@@ -41141,12 +41308,12 @@ var init_safety_data_accessor = __esm({
|
|
|
41141
41308
|
this.getSafetyOptions()
|
|
41142
41309
|
);
|
|
41143
41310
|
}
|
|
41144
|
-
async insertNewTask(task) {
|
|
41311
|
+
async insertNewTask(task, identity) {
|
|
41145
41312
|
this.logVerbose(`Inserting new task ${task.id}`);
|
|
41146
41313
|
await safeSingleTaskWrite(
|
|
41147
41314
|
this.inner,
|
|
41148
41315
|
task.id,
|
|
41149
|
-
() => this.inner.insertNewTask(task),
|
|
41316
|
+
() => this.inner.insertNewTask(task, identity),
|
|
41150
41317
|
this.cwd,
|
|
41151
41318
|
this.getSafetyOptions()
|
|
41152
41319
|
);
|
|
@@ -41194,6 +41361,9 @@ var init_safety_data_accessor = __esm({
|
|
|
41194
41361
|
return this.inner.findOrphanAcBindings();
|
|
41195
41362
|
}
|
|
41196
41363
|
// ---- Metadata (pass-through to inner) ----
|
|
41364
|
+
async getTaskIdentities(taskIds) {
|
|
41365
|
+
return await this.inner.getTaskIdentities?.(taskIds) ?? [];
|
|
41366
|
+
}
|
|
41197
41367
|
async getMetaValue(key) {
|
|
41198
41368
|
return this.inner.getMetaValue(key);
|
|
41199
41369
|
}
|
|
@@ -41567,13 +41737,147 @@ var init_cross_db_cleanup = __esm({
|
|
|
41567
41737
|
}
|
|
41568
41738
|
});
|
|
41569
41739
|
|
|
41740
|
+
// packages/core/src/store/dependency-cycles.ts
|
|
41741
|
+
function formatDependencyCycle(cycle) {
|
|
41742
|
+
return cycle.join(" \u2192 ");
|
|
41743
|
+
}
|
|
41744
|
+
function buildAdjacency(edges) {
|
|
41745
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
41746
|
+
for (const { taskId, dependsOn } of edges) {
|
|
41747
|
+
const next = adjacency.get(taskId);
|
|
41748
|
+
if (next) next.push(dependsOn);
|
|
41749
|
+
else adjacency.set(taskId, [dependsOn]);
|
|
41750
|
+
}
|
|
41751
|
+
for (const next of adjacency.values()) next.sort();
|
|
41752
|
+
return adjacency;
|
|
41753
|
+
}
|
|
41754
|
+
function shortestPath(adjacency, from, to) {
|
|
41755
|
+
if (from === to) return [from];
|
|
41756
|
+
const previous = /* @__PURE__ */ new Map([[from, from]]);
|
|
41757
|
+
const queue = [from];
|
|
41758
|
+
for (let head = 0; head < queue.length; head++) {
|
|
41759
|
+
const id = queue[head];
|
|
41760
|
+
for (const next of adjacency.get(id) ?? []) {
|
|
41761
|
+
if (previous.has(next)) continue;
|
|
41762
|
+
previous.set(next, id);
|
|
41763
|
+
if (next === to) {
|
|
41764
|
+
const path = [to];
|
|
41765
|
+
let cursor = id;
|
|
41766
|
+
while (cursor !== from) {
|
|
41767
|
+
path.push(cursor);
|
|
41768
|
+
cursor = previous.get(cursor);
|
|
41769
|
+
}
|
|
41770
|
+
path.push(from);
|
|
41771
|
+
return path.reverse();
|
|
41772
|
+
}
|
|
41773
|
+
queue.push(next);
|
|
41774
|
+
}
|
|
41775
|
+
}
|
|
41776
|
+
return null;
|
|
41777
|
+
}
|
|
41778
|
+
function findClosedCycle(existing, edge) {
|
|
41779
|
+
if (edge.taskId === edge.dependsOn) return [edge.taskId, edge.taskId];
|
|
41780
|
+
const path = shortestPath(buildAdjacency(existing), edge.dependsOn, edge.taskId);
|
|
41781
|
+
return path ? [edge.taskId, ...path] : null;
|
|
41782
|
+
}
|
|
41783
|
+
function dependencyCycleError(edge, cycle) {
|
|
41784
|
+
const self = edge.taskId === edge.dependsOn;
|
|
41785
|
+
const message = self ? `${DEPENDENCY_CYCLE_CODE}: task ${edge.taskId} cannot depend on itself` : `${DEPENDENCY_CYCLE_CODE}: ${edge.taskId} depends on ${edge.dependsOn} would close a dependency cycle: ${formatDependencyCycle(cycle)}`;
|
|
41786
|
+
const closing = cycle.length >= 3 ? cycle[cycle.length - 2] : void 0;
|
|
41787
|
+
const fix = self ? `Drop ${edge.taskId} from its own --depends list` : `Drop this dependency, or first remove another edge of the cycle, e.g. cleo update ${closing} --remove-depends ${edge.taskId}`;
|
|
41788
|
+
return new CleoError(14 /* CIRCULAR_REFERENCE */, message, {
|
|
41789
|
+
fix,
|
|
41790
|
+
details: {
|
|
41791
|
+
field: "depends",
|
|
41792
|
+
actual: edge.dependsOn,
|
|
41793
|
+
taskId: edge.taskId,
|
|
41794
|
+
cycle: [...cycle]
|
|
41795
|
+
}
|
|
41796
|
+
});
|
|
41797
|
+
}
|
|
41798
|
+
function isDependencyCycleAbort(err) {
|
|
41799
|
+
for (let e = err, depth = 0; e instanceof Error && depth < 8; depth++) {
|
|
41800
|
+
if (e.message.includes(DEPENDENCY_CYCLE_CODE)) return true;
|
|
41801
|
+
e = e.cause;
|
|
41802
|
+
}
|
|
41803
|
+
return false;
|
|
41804
|
+
}
|
|
41805
|
+
function readDependencyEdges(db) {
|
|
41806
|
+
return db.select({
|
|
41807
|
+
taskId: tasksTaskDependencies.taskId,
|
|
41808
|
+
dependsOn: tasksTaskDependencies.dependsOn
|
|
41809
|
+
}).from(tasksTaskDependencies).all();
|
|
41810
|
+
}
|
|
41811
|
+
function rethrowDependencyCycle(db, err, attempted) {
|
|
41812
|
+
if (!isDependencyCycleAbort(err)) throw err;
|
|
41813
|
+
const edges = readDependencyEdges(db);
|
|
41814
|
+
for (const edge of attempted) {
|
|
41815
|
+
const cycle = findClosedCycle(edges, edge);
|
|
41816
|
+
if (cycle) throw dependencyCycleError(edge, cycle);
|
|
41817
|
+
edges.push(edge);
|
|
41818
|
+
}
|
|
41819
|
+
throw err;
|
|
41820
|
+
}
|
|
41821
|
+
var DEPENDENCY_CYCLE_CODE;
|
|
41822
|
+
var init_dependency_cycles = __esm({
|
|
41823
|
+
"packages/core/src/store/dependency-cycles.ts"() {
|
|
41824
|
+
"use strict";
|
|
41825
|
+
init_src();
|
|
41826
|
+
init_errors2();
|
|
41827
|
+
init_tasks_schema();
|
|
41828
|
+
DEPENDENCY_CYCLE_CODE = "E_TASK_DEPENDENCY_CYCLE";
|
|
41829
|
+
}
|
|
41830
|
+
});
|
|
41831
|
+
|
|
41570
41832
|
// packages/core/src/store/db-helpers.ts
|
|
41571
41833
|
import { and as and5, eq as eq7, inArray as inArray3, sql as sql27 } from "drizzle-orm";
|
|
41572
41834
|
async function upsertTask(db, row, archiveFields, allowOrphanParent = false) {
|
|
41573
41835
|
await writeTaskRow(db, row, archiveFields, allowOrphanParent, false);
|
|
41574
41836
|
}
|
|
41575
|
-
async function insertNewTask(db, row) {
|
|
41576
|
-
await writeTaskRow(
|
|
41837
|
+
async function insertNewTask(db, row, identity = { origin: "new" }) {
|
|
41838
|
+
await writeTaskRow(
|
|
41839
|
+
db,
|
|
41840
|
+
{ ...row, ...await importedIdentity(db, identity, row) },
|
|
41841
|
+
void 0,
|
|
41842
|
+
false,
|
|
41843
|
+
true
|
|
41844
|
+
);
|
|
41845
|
+
}
|
|
41846
|
+
async function tableExists2(db, table) {
|
|
41847
|
+
const rows = await db.all(
|
|
41848
|
+
sql27`SELECT 1 AS x FROM sqlite_master WHERE type = 'table' AND name = ${table}`
|
|
41849
|
+
);
|
|
41850
|
+
return rows.length > 0;
|
|
41851
|
+
}
|
|
41852
|
+
async function importedIdentity(db, identity, row) {
|
|
41853
|
+
if (identity.origin === "new" || !rowUidFillEnabled()) return {};
|
|
41854
|
+
const fp = identity.birthFp ?? null;
|
|
41855
|
+
const carried2 = identity.uid ?? null;
|
|
41856
|
+
if (carried2 !== null && fp !== null) {
|
|
41857
|
+
let uid = carried2;
|
|
41858
|
+
if (await tableExists2(db, "tasks_uid_aliases")) {
|
|
41859
|
+
for (let hop = 0; hop < 32; hop++) {
|
|
41860
|
+
const found = await db.all(
|
|
41861
|
+
sql27`SELECT new_uid AS uid FROM tasks_uid_aliases
|
|
41862
|
+
WHERE entity_table = 'tasks_tasks' AND old_uid = ${uid} AND old_birth_fp = ${fp}`
|
|
41863
|
+
);
|
|
41864
|
+
const next = found[0];
|
|
41865
|
+
if (!next) break;
|
|
41866
|
+
uid = next.uid;
|
|
41867
|
+
}
|
|
41868
|
+
}
|
|
41869
|
+
const [holder] = await db.select({ id: tasksTasks.id, birthFp: tasksTasks.birthFp }).from(tasksTasks).where(eq7(tasksTasks.uid, uid)).limit(1).all();
|
|
41870
|
+
if (holder && holder.birthFp === fp) throw new SameRowPresentError(row.id, holder.id);
|
|
41871
|
+
if (await tableExists2(db, "tasks_identity_quarantine")) {
|
|
41872
|
+
const [held] = await db.all(
|
|
41873
|
+
sql27`SELECT 1 AS x FROM tasks_identity_quarantine
|
|
41874
|
+
WHERE entity_table = 'tasks_tasks' AND uid = ${uid} AND birth_fp = ${fp}`
|
|
41875
|
+
);
|
|
41876
|
+
if (held) throw new SameRowPresentError(row.id, "held");
|
|
41877
|
+
}
|
|
41878
|
+
if (!holder) return { uid, birthFp: fp };
|
|
41879
|
+
}
|
|
41880
|
+
return { uid: null, birthFp: null };
|
|
41577
41881
|
}
|
|
41578
41882
|
async function writeTaskRow(db, row, archiveFields, allowOrphanParent, insertOnly) {
|
|
41579
41883
|
if (row.parentId && row.parentId === row.id) {
|
|
@@ -41724,7 +42028,11 @@ async function batchUpdateDependencies(db, tasks2, validIds) {
|
|
|
41724
42028
|
for (const depId of want) if (!have.has(depId)) added.push({ taskId, dependsOn: depId });
|
|
41725
42029
|
}
|
|
41726
42030
|
if (added.length > 0) {
|
|
41727
|
-
|
|
42031
|
+
try {
|
|
42032
|
+
await db.insert(tasksTaskDependencies).values(added).onConflictDoNothing().run();
|
|
42033
|
+
} catch (err) {
|
|
42034
|
+
rethrowDependencyCycle(db, err, added);
|
|
42035
|
+
}
|
|
41728
42036
|
}
|
|
41729
42037
|
}
|
|
41730
42038
|
async function loadDependenciesForTasks(db, tasks2, _validationIds) {
|
|
@@ -41769,15 +42077,29 @@ async function loadRelationsForTasks(db, tasks2) {
|
|
|
41769
42077
|
task.relates = relations && relations.length > 0 ? relations : [];
|
|
41770
42078
|
}
|
|
41771
42079
|
}
|
|
41772
|
-
var log6;
|
|
42080
|
+
var log6, SameRowPresentError;
|
|
41773
42081
|
var init_db_helpers = __esm({
|
|
41774
42082
|
"packages/core/src/store/db-helpers.ts"() {
|
|
41775
42083
|
"use strict";
|
|
41776
42084
|
init_src();
|
|
41777
42085
|
init_errors2();
|
|
41778
42086
|
init_logger();
|
|
42087
|
+
init_dependency_cycles();
|
|
42088
|
+
init_row_identity_flag();
|
|
41779
42089
|
init_tasks_schema();
|
|
41780
42090
|
log6 = getLogger("db-helpers");
|
|
42091
|
+
SameRowPresentError = class extends CleoError {
|
|
42092
|
+
/** Where the row already is: its display id, or `held` when quarantined. */
|
|
42093
|
+
presentAs;
|
|
42094
|
+
constructor(taskId, presentAs) {
|
|
42095
|
+
super(
|
|
42096
|
+
22 /* ID_COLLISION */,
|
|
42097
|
+
`Task ${taskId} is already in this store (${presentAs === "held" ? "held for sync" : `as ${presentAs}`}): same uid and birth fingerprint; not written again`,
|
|
42098
|
+
{ details: { field: "taskId", actual: taskId, expected: presentAs } }
|
|
42099
|
+
);
|
|
42100
|
+
this.presentAs = presentAs;
|
|
42101
|
+
}
|
|
42102
|
+
};
|
|
41781
42103
|
}
|
|
41782
42104
|
});
|
|
41783
42105
|
|
|
@@ -41862,46 +42184,133 @@ function readProcessEntry(pid) {
|
|
|
41862
42184
|
return null;
|
|
41863
42185
|
}
|
|
41864
42186
|
}
|
|
41865
|
-
function
|
|
42187
|
+
function readProcessArgs(pid) {
|
|
42188
|
+
if (process.platform === "win32" || !Number.isInteger(pid) || pid <= 1) return null;
|
|
42189
|
+
try {
|
|
42190
|
+
const out = execFileSync("ps", ["-o", "args=", "-p", String(pid)], {
|
|
42191
|
+
encoding: "utf8",
|
|
42192
|
+
timeout: 1e3,
|
|
42193
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
42194
|
+
env: { ...process.env, ...PS_STABLE_ENV }
|
|
42195
|
+
}).trim();
|
|
42196
|
+
return out === "" ? null : out;
|
|
42197
|
+
} catch {
|
|
42198
|
+
return null;
|
|
42199
|
+
}
|
|
42200
|
+
}
|
|
42201
|
+
function baseName(token) {
|
|
42202
|
+
return token.slice(token.lastIndexOf("/") + 1).replace(/^-/, "");
|
|
42203
|
+
}
|
|
42204
|
+
function programName(commandLine) {
|
|
42205
|
+
const tokens = commandLine.trim().split(/\s+/);
|
|
42206
|
+
const head = baseName(tokens[0] ?? "");
|
|
42207
|
+
if (!RUNTIME_PATTERN.test(head)) return head;
|
|
42208
|
+
for (let i = 1; i < tokens.length; i++) {
|
|
42209
|
+
const token = tokens[i] ?? "";
|
|
42210
|
+
if (token === "-m") return (tokens[i + 1] ?? head).split(".")[0] ?? head;
|
|
42211
|
+
if (token.startsWith("-")) continue;
|
|
42212
|
+
return baseName(token).replace(/\.(c|m)?(js|ts)$|\.py$/, "");
|
|
42213
|
+
}
|
|
42214
|
+
return head;
|
|
42215
|
+
}
|
|
42216
|
+
function isCommandStringShell(args) {
|
|
42217
|
+
const tokens = args.trim().split(/\s+/);
|
|
42218
|
+
const shell = programName(args);
|
|
42219
|
+
let first = 1;
|
|
42220
|
+
if (RUNTIME_PATTERN.test(baseName(tokens[0] ?? ""))) {
|
|
42221
|
+
while (first < tokens.length && (tokens[first] ?? "").startsWith("-")) first++;
|
|
42222
|
+
first++;
|
|
42223
|
+
}
|
|
42224
|
+
const rest = tokens.slice(first);
|
|
42225
|
+
if (shell === "pwsh" || shell === "powershell") {
|
|
42226
|
+
return rest.some((t) => PWSH_COMMAND_SWITCHES.has(t.toLowerCase()));
|
|
42227
|
+
}
|
|
42228
|
+
for (let i = 0; i < rest.length; i++) {
|
|
42229
|
+
const token = rest[i] ?? "";
|
|
42230
|
+
if (token === "--") return false;
|
|
42231
|
+
if (token === "--command" || token === "--commands") return true;
|
|
42232
|
+
if (SHELL_OPTIONS_WITH_ARGUMENT.has(token)) {
|
|
42233
|
+
i++;
|
|
42234
|
+
continue;
|
|
42235
|
+
}
|
|
42236
|
+
if (token.startsWith("--")) continue;
|
|
42237
|
+
if (!/^[-+][A-Za-z]+$/.test(token)) return false;
|
|
42238
|
+
if (token.startsWith("-") && token.slice(1).includes("c")) return true;
|
|
42239
|
+
}
|
|
42240
|
+
return false;
|
|
42241
|
+
}
|
|
42242
|
+
function resolveAncestor(ppid, lookupProcess, lookupArgs, agentId = null) {
|
|
41866
42243
|
let pid = ppid;
|
|
41867
|
-
for (let depth = 0; depth < PPID_CHAIN_MAX_DEPTH
|
|
42244
|
+
for (let depth = 0; depth < PPID_CHAIN_MAX_DEPTH; depth++) {
|
|
42245
|
+
if (pid <= 1) return null;
|
|
41868
42246
|
const entry = lookupProcess(pid);
|
|
41869
|
-
if (!entry) return null;
|
|
41870
|
-
|
|
41871
|
-
|
|
42247
|
+
if (!entry || entry.pid <= 1) return null;
|
|
42248
|
+
const args = lookupArgs(entry.pid);
|
|
42249
|
+
const program = programName(args ?? entry.command);
|
|
42250
|
+
if (INIT_PROCESSES.has(program) || INIT_PROCESSES.has(entry.command)) return null;
|
|
42251
|
+
if (OWNER_PROCESS_SHELLS.has(program)) {
|
|
42252
|
+
if (args === null) return null;
|
|
42253
|
+
if (!isCommandStringShell(args)) return { entry, program, type: "shell" };
|
|
42254
|
+
} else if (!ANCESTOR_WRAPPERS.has(program)) {
|
|
42255
|
+
if (KNOWN_HARNESSES.has(program)) return { entry, program, type: "harness" };
|
|
42256
|
+
return agentId ? { entry, program, type: "host" } : null;
|
|
41872
42257
|
}
|
|
41873
42258
|
pid = entry.ppid;
|
|
41874
42259
|
}
|
|
41875
42260
|
return null;
|
|
41876
42261
|
}
|
|
42262
|
+
function anchorKey(anchor, agentId, under) {
|
|
42263
|
+
const proc = `${anchor.entry.pid}@${anchor.entry.startedAt}`;
|
|
42264
|
+
if (anchor.type === "shell" && !agentId) {
|
|
42265
|
+
return { key: `proc:${proc}`, source: "process", kind: "process" };
|
|
42266
|
+
}
|
|
42267
|
+
const agent = agentId ? `#agent=${agentId}` : "";
|
|
42268
|
+
const scope = under ? `|${under.key}` : "";
|
|
42269
|
+
return {
|
|
42270
|
+
key: `harness:${anchor.program}:${proc}${agent}${scope}`,
|
|
42271
|
+
source: "process",
|
|
42272
|
+
kind: "harness"
|
|
42273
|
+
};
|
|
42274
|
+
}
|
|
41877
42275
|
function resolveTerminalKeys(options = {}) {
|
|
41878
42276
|
const env = options.env ?? process.env;
|
|
41879
42277
|
const keys = [];
|
|
41880
42278
|
for (const source of TERMINAL_KEY_SOURCES) {
|
|
41881
42279
|
const value = envValue(env, source.envVar);
|
|
41882
42280
|
if (value === null) continue;
|
|
41883
|
-
const
|
|
42281
|
+
const qualifiers = [source.qualifierEnvVar, ...source.extraQualifierEnvVars ?? []].map((name15) => envValue(env, name15)).filter((q2) => q2 !== null);
|
|
41884
42282
|
keys.push({
|
|
41885
|
-
key: `env:${source.envVar}=${
|
|
42283
|
+
key: `env:${source.envVar}=${[...qualifiers, value].join("|")}`,
|
|
41886
42284
|
source: source.envVar,
|
|
41887
42285
|
kind: source.kind
|
|
41888
42286
|
});
|
|
41889
42287
|
}
|
|
41890
|
-
if (keys.
|
|
41891
|
-
const
|
|
41892
|
-
|
|
42288
|
+
if (keys.some((k) => k.kind === "provider")) return keys;
|
|
42289
|
+
const agentId = envValue(env, "CLEO_AGENT_ID");
|
|
42290
|
+
const live = options.ppid === void 0 && options.lookupProcess === void 0 && options.lookupArgs === void 0;
|
|
42291
|
+
let anchor;
|
|
41893
42292
|
if (live) {
|
|
41894
|
-
|
|
41895
|
-
|
|
42293
|
+
const memoKey2 = agentId ?? "";
|
|
42294
|
+
if (!liveAnchors.has(memoKey2))
|
|
42295
|
+
liveAnchors.set(
|
|
42296
|
+
memoKey2,
|
|
42297
|
+
resolveAncestor(process.ppid, readProcessEntry, readProcessArgs, agentId)
|
|
42298
|
+
);
|
|
42299
|
+
anchor = liveAnchors.get(memoKey2) ?? null;
|
|
41896
42300
|
} else {
|
|
41897
|
-
|
|
42301
|
+
anchor = resolveAncestor(
|
|
41898
42302
|
options.ppid ?? process.ppid,
|
|
41899
|
-
options.lookupProcess ?? readProcessEntry
|
|
42303
|
+
options.lookupProcess ?? readProcessEntry,
|
|
42304
|
+
options.lookupArgs ?? readProcessArgs,
|
|
42305
|
+
agentId
|
|
41900
42306
|
);
|
|
41901
42307
|
}
|
|
41902
|
-
|
|
42308
|
+
if (!anchor) return keys;
|
|
42309
|
+
if (keys.length === 0) return [anchorKey(anchor, agentId, void 0)];
|
|
42310
|
+
if (anchor.type === "shell" && !agentId) return keys;
|
|
42311
|
+
return [...keys, anchorKey(anchor, agentId, keys[0])];
|
|
41903
42312
|
}
|
|
41904
|
-
var TERMINAL_KEY_SOURCES,
|
|
42313
|
+
var TERMINAL_KEY_SOURCES, PPID_CHAIN_MAX_DEPTH, KNOWN_HARNESSES, RUNTIME_PATTERN, ANCESTOR_WRAPPERS, INIT_PROCESSES, SHELL_OPTIONS_WITH_ARGUMENT, PWSH_COMMAND_SWITCHES, OWNER_PROCESS_SHELLS, liveAnchors;
|
|
41905
42314
|
var init_terminal_identity = __esm({
|
|
41906
42315
|
"packages/core/src/sessions/terminal-identity.ts"() {
|
|
41907
42316
|
"use strict";
|
|
@@ -41933,24 +42342,100 @@ var init_terminal_identity = __esm({
|
|
|
41933
42342
|
kind: "terminal",
|
|
41934
42343
|
origin: "konsole",
|
|
41935
42344
|
qualifierEnvVar: "KONSOLE_DBUS_SERVICE"
|
|
42345
|
+
},
|
|
42346
|
+
// T12864 — non-terminal callers whose platform exports a per-job / per-login id.
|
|
42347
|
+
// GitHub Actions: GITHUB_RUN_ID is per run and shared by its jobs, so it is
|
|
42348
|
+
// qualified by GITHUB_RUN_ATTEMPT and GITHUB_JOB ("Variables reference",
|
|
42349
|
+
// docs.github.com/en/actions/reference/workflows-and-actions/variables).
|
|
42350
|
+
// Every step of one job shares the key; the steps run sequentially.
|
|
42351
|
+
{
|
|
42352
|
+
envVar: "GITHUB_RUN_ID",
|
|
42353
|
+
kind: "terminal",
|
|
42354
|
+
origin: "github-actions",
|
|
42355
|
+
qualifierEnvVar: "GITHUB_RUN_ATTEMPT",
|
|
42356
|
+
extraQualifierEnvVars: ["GITHUB_JOB"]
|
|
42357
|
+
},
|
|
42358
|
+
// GitLab CI: CI_JOB_ID is unique per job across the instance ("Predefined
|
|
42359
|
+
// CI/CD variables reference", docs.gitlab.com/ci/variables/predefined_variables).
|
|
42360
|
+
{ envVar: "CI_JOB_ID", kind: "terminal", origin: "gitlab-ci" },
|
|
42361
|
+
// OpenSSH login with a tty: SSH_TTY names the login's tty and is set only
|
|
42362
|
+
// when one was allocated; SSH_CONNECTION ("client-ip client-port server-ip
|
|
42363
|
+
// server-port", ssh(1) ENVIRONMENT) disambiguates it across connections. A
|
|
42364
|
+
// one-shot `ssh host 'cmd'` has no tty and falls through to the ancestor walk.
|
|
42365
|
+
{
|
|
42366
|
+
envVar: "SSH_TTY",
|
|
42367
|
+
kind: "terminal",
|
|
42368
|
+
origin: "openssh",
|
|
42369
|
+
qualifierEnvVar: "SSH_CONNECTION"
|
|
41936
42370
|
}
|
|
41937
42371
|
];
|
|
41938
|
-
|
|
41939
|
-
|
|
42372
|
+
PPID_CHAIN_MAX_DEPTH = 12;
|
|
42373
|
+
KNOWN_HARNESSES = /* @__PURE__ */ new Set([
|
|
42374
|
+
"claude",
|
|
42375
|
+
"codex",
|
|
42376
|
+
"aider",
|
|
42377
|
+
"gemini",
|
|
42378
|
+
"kimi",
|
|
42379
|
+
"cursor-agent",
|
|
42380
|
+
"amp"
|
|
42381
|
+
]);
|
|
42382
|
+
RUNTIME_PATTERN = /^(node|nodejs|bun|deno|python[0-9.]*|pypy[0-9.]*|ruby|java|php|perl)$/;
|
|
42383
|
+
ANCESTOR_WRAPPERS = /* @__PURE__ */ new Set([
|
|
42384
|
+
"env",
|
|
42385
|
+
"timeout",
|
|
42386
|
+
"gtimeout",
|
|
42387
|
+
"nohup",
|
|
42388
|
+
"nice",
|
|
42389
|
+
"time",
|
|
42390
|
+
"xargs",
|
|
42391
|
+
"stdbuf",
|
|
42392
|
+
"sudo",
|
|
42393
|
+
"doas",
|
|
41940
42394
|
"npm",
|
|
42395
|
+
"npm-cli",
|
|
41941
42396
|
"npx",
|
|
42397
|
+
"npx-cli",
|
|
41942
42398
|
"pnpm",
|
|
41943
42399
|
"pnpx",
|
|
41944
42400
|
"yarn",
|
|
41945
|
-
"bun",
|
|
41946
42401
|
"bunx",
|
|
41947
|
-
"tsx",
|
|
41948
42402
|
"corepack",
|
|
41949
42403
|
"mise",
|
|
41950
|
-
"env",
|
|
41951
42404
|
"cleo"
|
|
41952
42405
|
]);
|
|
41953
|
-
|
|
42406
|
+
INIT_PROCESSES = /* @__PURE__ */ new Set(["launchd", "systemd", "init"]);
|
|
42407
|
+
SHELL_OPTIONS_WITH_ARGUMENT = /* @__PURE__ */ new Set([
|
|
42408
|
+
"-o",
|
|
42409
|
+
"+o",
|
|
42410
|
+
"-O",
|
|
42411
|
+
"+O",
|
|
42412
|
+
"--rcfile",
|
|
42413
|
+
"--init-file"
|
|
42414
|
+
]);
|
|
42415
|
+
PWSH_COMMAND_SWITCHES = /* @__PURE__ */ new Set([
|
|
42416
|
+
"-c",
|
|
42417
|
+
"-command",
|
|
42418
|
+
"-commandwithargs",
|
|
42419
|
+
"-cwa",
|
|
42420
|
+
"-e",
|
|
42421
|
+
"-ec",
|
|
42422
|
+
"-encodedcommand"
|
|
42423
|
+
]);
|
|
42424
|
+
OWNER_PROCESS_SHELLS = /* @__PURE__ */ new Set([
|
|
42425
|
+
"sh",
|
|
42426
|
+
"bash",
|
|
42427
|
+
"zsh",
|
|
42428
|
+
"dash",
|
|
42429
|
+
"fish",
|
|
42430
|
+
"ksh",
|
|
42431
|
+
"tcsh",
|
|
42432
|
+
"csh",
|
|
42433
|
+
"pwsh",
|
|
42434
|
+
"powershell",
|
|
42435
|
+
"nu",
|
|
42436
|
+
"xonsh"
|
|
42437
|
+
]);
|
|
42438
|
+
liveAnchors = /* @__PURE__ */ new Map();
|
|
41954
42439
|
}
|
|
41955
42440
|
});
|
|
41956
42441
|
|
|
@@ -41990,7 +42475,8 @@ var init_session_binding_schema = __esm({
|
|
|
41990
42475
|
});
|
|
41991
42476
|
|
|
41992
42477
|
// packages/core/src/store/session-store.ts
|
|
41993
|
-
import {
|
|
42478
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
42479
|
+
import { and as and6, desc as desc2, eq as eq8, inArray as inArray4, isNull as isNull3, lte as lte2, or as or4 } from "drizzle-orm";
|
|
41994
42480
|
async function getSession(sessionId, cwd) {
|
|
41995
42481
|
const scope = captureProjectScope(cwd ?? getProjectRoot(), worktreeScope.getStore());
|
|
41996
42482
|
return worktreeScope.run(scope, async () => {
|
|
@@ -42012,8 +42498,9 @@ async function getActiveSession(cwd) {
|
|
|
42012
42498
|
function splitTerminalKeys(keys) {
|
|
42013
42499
|
return {
|
|
42014
42500
|
provider: keys.find((k) => k.kind === "provider"),
|
|
42015
|
-
|
|
42016
|
-
|
|
42501
|
+
// A harness / CLEO_AGENT_ID agent (T12864) is more specific than a pane.
|
|
42502
|
+
pane: keys.find((k) => k.kind === "harness") ?? keys.find((k) => k.kind === "multiplexer"),
|
|
42503
|
+
tab: keys.find((k) => k.kind === "terminal" || k.kind === "process" || k.kind === "ppid")
|
|
42017
42504
|
};
|
|
42018
42505
|
}
|
|
42019
42506
|
async function readBinding(db, key) {
|
|
@@ -42093,6 +42580,7 @@ async function resolveCurrentSession(cwd) {
|
|
|
42093
42580
|
async function resolveBoundSession(cwd) {
|
|
42094
42581
|
const scope = captureProjectScope(cwd ?? getProjectRoot(), worktreeScope.getStore());
|
|
42095
42582
|
return worktreeScope.run(scope, async () => {
|
|
42583
|
+
if (!existsSync20(getDbPath(scope.worktreeRoot))) return null;
|
|
42096
42584
|
const connId = getCurrentConnectionSessionId();
|
|
42097
42585
|
if (connId) {
|
|
42098
42586
|
const byConn = await getSession(connId, scope.worktreeRoot);
|
|
@@ -42244,7 +42732,7 @@ __export(registry_exports2, {
|
|
|
42244
42732
|
updateAgentStatus: () => updateAgentStatus
|
|
42245
42733
|
});
|
|
42246
42734
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
42247
|
-
import { and as and7, eq as eq9, inArray as
|
|
42735
|
+
import { and as and7, eq as eq9, inArray as inArray5, lt as lt2, sql as sql29 } from "drizzle-orm";
|
|
42248
42736
|
function generateAgentId() {
|
|
42249
42737
|
const now = /* @__PURE__ */ new Date();
|
|
42250
42738
|
const ts = now.toISOString().replace(/[-:T]/g, "").substring(0, 14);
|
|
@@ -42333,11 +42821,11 @@ async function listAgentInstances(filters, cwd) {
|
|
|
42333
42821
|
const conditions = [];
|
|
42334
42822
|
if (filters?.status) {
|
|
42335
42823
|
const statuses = Array.isArray(filters.status) ? filters.status : [filters.status];
|
|
42336
|
-
conditions.push(
|
|
42824
|
+
conditions.push(inArray5(agentInstances.status, statuses));
|
|
42337
42825
|
}
|
|
42338
42826
|
if (filters?.agentType) {
|
|
42339
42827
|
const types = Array.isArray(filters.agentType) ? filters.agentType : [filters.agentType];
|
|
42340
|
-
conditions.push(
|
|
42828
|
+
conditions.push(inArray5(agentInstances.agentType, types));
|
|
42341
42829
|
}
|
|
42342
42830
|
if (filters?.sessionId) {
|
|
42343
42831
|
conditions.push(eq9(agentInstances.sessionId, filters.sessionId));
|
|
@@ -42374,7 +42862,7 @@ async function checkAgentHealth(thresholdMs = 3e4, cwd) {
|
|
|
42374
42862
|
const cutoff = new Date(Date.now() - thresholdMs).toISOString();
|
|
42375
42863
|
return db.select().from(agentInstances).where(
|
|
42376
42864
|
and7(
|
|
42377
|
-
|
|
42865
|
+
inArray5(agentInstances.status, ["active", "idle", "starting"]),
|
|
42378
42866
|
lt2(agentInstances.lastHeartbeat, cutoff)
|
|
42379
42867
|
)
|
|
42380
42868
|
).all();
|
|
@@ -42469,12 +42957,14 @@ var init_registry2 = __esm({
|
|
|
42469
42957
|
// packages/core/src/store/sqlite-data-accessor.ts
|
|
42470
42958
|
var sqlite_data_accessor_exports = {};
|
|
42471
42959
|
__export(sqlite_data_accessor_exports, {
|
|
42960
|
+
RENAMED_RECENT_MS: () => RENAMED_RECENT_MS,
|
|
42472
42961
|
addTaskLabelsNative: () => addTaskLabelsNative,
|
|
42473
42962
|
advanceTaskIdSequence: () => advanceTaskIdSequence,
|
|
42474
42963
|
bindTaskAccessorScope: () => bindTaskAccessorScope,
|
|
42475
42964
|
captureTaskAccessorScope: () => captureProjectScope,
|
|
42476
42965
|
clearAcUidGraveyardNative: () => clearAcUidGraveyardNative,
|
|
42477
42966
|
clearBirthFpNative: () => clearBirthFpNative,
|
|
42967
|
+
clearReplacedTaskIdentityNative: () => clearReplacedTaskIdentityNative,
|
|
42478
42968
|
clearRowUidNative: () => clearRowUidNative,
|
|
42479
42969
|
createSqliteDataAccessor: () => createSqliteDataAccessor,
|
|
42480
42970
|
deleteDisplayIdAliasNative: () => deleteDisplayIdAliasNative,
|
|
@@ -42485,6 +42975,7 @@ __export(sqlite_data_accessor_exports, {
|
|
|
42485
42975
|
insertIdentityRowNative: () => insertIdentityRowNative,
|
|
42486
42976
|
insertQuarantineNative: () => insertQuarantineNative,
|
|
42487
42977
|
insertUidAliasNative: () => insertUidAliasNative,
|
|
42978
|
+
readReplacedTaskBirthNative: () => readReplacedTaskBirthNative,
|
|
42488
42979
|
rederiveAcIdsNative: () => rederiveAcIdsNative,
|
|
42489
42980
|
rekeyQuarantineNative: () => rekeyQuarantineNative,
|
|
42490
42981
|
relinkAcUidNative: () => relinkAcUidNative,
|
|
@@ -42501,7 +42992,7 @@ import {
|
|
|
42501
42992
|
and as and8,
|
|
42502
42993
|
eq as eq10,
|
|
42503
42994
|
getTableColumns as getTableColumns2,
|
|
42504
|
-
inArray as
|
|
42995
|
+
inArray as inArray6,
|
|
42505
42996
|
isNull as isNull4,
|
|
42506
42997
|
like as like2,
|
|
42507
42998
|
lte as lte3,
|
|
@@ -42525,8 +43016,8 @@ async function selectAcBindings(db, acIds) {
|
|
|
42525
43016
|
bindingType: b.bindingType,
|
|
42526
43017
|
createdAt: b.createdAt
|
|
42527
43018
|
};
|
|
42528
|
-
const byUid = await db.select(columns).from(b).innerJoin(ac, eq10(ac.uid, b.acUid)).where(
|
|
42529
|
-
const byId = await db.select(columns).from(b).leftJoin(ac, eq10(ac.uid, b.acUid)).where(
|
|
43019
|
+
const byUid = await db.select(columns).from(b).innerJoin(ac, eq10(ac.uid, b.acUid)).where(inArray6(ac.id, ids)).all();
|
|
43020
|
+
const byId = await db.select(columns).from(b).leftJoin(ac, eq10(ac.uid, b.acUid)).where(inArray6(b.acId, ids)).all();
|
|
42530
43021
|
const rows = [...byUid, ...byId];
|
|
42531
43022
|
const wanted = new Set(ids);
|
|
42532
43023
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -42619,6 +43110,7 @@ function renameTaskDisplayIdNative(nativeDb, uid, toId, refs, guard = {}) {
|
|
|
42619
43110
|
if (Number(changed) !== 1) {
|
|
42620
43111
|
throw taskConflictError(current.id, taskVersion(current), null);
|
|
42621
43112
|
}
|
|
43113
|
+
recordLocalRename(nativeDb, uid, current.id, toId, taskVersion(current));
|
|
42622
43114
|
const rewritten = {};
|
|
42623
43115
|
const q2 = (name15) => `"${name15.replaceAll('"', '""')}"`;
|
|
42624
43116
|
for (const ref of refs) {
|
|
@@ -42674,23 +43166,39 @@ function rederiveAcIdsNative(nativeDb, fromId, toId) {
|
|
|
42674
43166
|
}
|
|
42675
43167
|
return count;
|
|
42676
43168
|
}
|
|
42677
|
-
function insertDisplayIdAliasNative(nativeDb, row) {
|
|
43169
|
+
function insertDisplayIdAliasNative(nativeDb, row, precedes) {
|
|
43170
|
+
const stored = nativeDb.prepare(
|
|
43171
|
+
`SELECT uid, entity_table AS entityTable, display_id AS displayId, entity_uid AS entityUid,
|
|
43172
|
+
reason, origin, displaced_hlc AS displacedHlc, created_at AS createdAt,
|
|
43173
|
+
entity_birth_fp AS entityBirthFp
|
|
43174
|
+
FROM tasks_display_id_aliases WHERE uid = ?`
|
|
43175
|
+
).get(row.uid);
|
|
43176
|
+
if (!stored) {
|
|
43177
|
+
nativeDb.prepare(
|
|
43178
|
+
`INSERT INTO tasks_display_id_aliases
|
|
43179
|
+
(uid, entity_table, display_id, entity_uid, reason, origin, displaced_hlc, created_at,
|
|
43180
|
+
entity_birth_fp)
|
|
43181
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
43182
|
+
).run(
|
|
43183
|
+
row.uid,
|
|
43184
|
+
row.entityTable,
|
|
43185
|
+
row.displayId,
|
|
43186
|
+
row.entityUid,
|
|
43187
|
+
row.reason,
|
|
43188
|
+
row.origin,
|
|
43189
|
+
row.displacedHlc,
|
|
43190
|
+
row.createdAt,
|
|
43191
|
+
row.entityBirthFp
|
|
43192
|
+
);
|
|
43193
|
+
return;
|
|
43194
|
+
}
|
|
43195
|
+
if (!precedes(row, stored)) return;
|
|
42678
43196
|
nativeDb.prepare(
|
|
42679
|
-
`
|
|
42680
|
-
|
|
42681
|
-
|
|
42682
|
-
|
|
42683
|
-
).run(
|
|
42684
|
-
row.uid,
|
|
42685
|
-
row.entityTable,
|
|
42686
|
-
row.displayId,
|
|
42687
|
-
row.entityUid,
|
|
42688
|
-
row.reason,
|
|
42689
|
-
row.origin,
|
|
42690
|
-
row.displacedHlc,
|
|
42691
|
-
row.createdAt,
|
|
42692
|
-
row.entityBirthFp
|
|
42693
|
-
);
|
|
43197
|
+
`UPDATE tasks_display_id_aliases
|
|
43198
|
+
SET origin = ?, displaced_hlc = ?, created_at = ?,
|
|
43199
|
+
entity_birth_fp = coalesce(entity_birth_fp, ?)
|
|
43200
|
+
WHERE uid = ?`
|
|
43201
|
+
).run(row.origin, row.displacedHlc, row.createdAt, row.entityBirthFp, row.uid);
|
|
42694
43202
|
}
|
|
42695
43203
|
function deleteDisplayIdAliasNative(nativeDb, uid) {
|
|
42696
43204
|
nativeDb.prepare("DELETE FROM tasks_display_id_aliases WHERE uid = ?").run(uid);
|
|
@@ -42752,6 +43260,63 @@ function relinkAcUidNative(nativeDb, acId, uid, birthFp) {
|
|
|
42752
43260
|
function clearAcUidGraveyardNative(nativeDb) {
|
|
42753
43261
|
nativeDb.exec("DELETE FROM tasks_ac_uid_graveyard");
|
|
42754
43262
|
}
|
|
43263
|
+
function readReplacedTaskBirthNative(nativeDb, taskId) {
|
|
43264
|
+
return nativeDb.prepare("SELECT created_at AS createdAt, uid FROM tasks_tasks WHERE id = ?").get(taskId);
|
|
43265
|
+
}
|
|
43266
|
+
function clearReplacedTaskIdentityNative(nativeDb, taskId, before) {
|
|
43267
|
+
const row = nativeDb.prepare("SELECT uid, birth_fp AS fp, created_at AS createdAt FROM tasks_tasks WHERE id = ?").get(taskId);
|
|
43268
|
+
if (!row || row.uid === null && row.fp === null) return;
|
|
43269
|
+
if (before) {
|
|
43270
|
+
const was = parseStoreTimestamp(before.createdAt);
|
|
43271
|
+
if (was !== null && was === parseStoreTimestamp(row.createdAt)) {
|
|
43272
|
+
return;
|
|
43273
|
+
}
|
|
43274
|
+
}
|
|
43275
|
+
if (rowIdentityShared(nativeDb)) {
|
|
43276
|
+
throw new CleoError(
|
|
43277
|
+
6 /* VALIDATION_ERROR */,
|
|
43278
|
+
`Task ${taskId} cannot be overwritten by an import: its identity is shared with other devices`,
|
|
43279
|
+
{
|
|
43280
|
+
fix: "Import it under a new id (the default duplicate strategy), or edit the task instead of overwriting it.",
|
|
43281
|
+
details: { field: "taskId", actual: taskId }
|
|
43282
|
+
}
|
|
43283
|
+
);
|
|
43284
|
+
}
|
|
43285
|
+
const has = (table) => nativeDb.prepare("SELECT 1 AS x FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) !== void 0;
|
|
43286
|
+
nativeDb.prepare("UPDATE tasks_tasks SET uid = NULL, birth_fp = NULL WHERE id = ?").run(taskId);
|
|
43287
|
+
for (const spec of ROW_IDENTITY.project) {
|
|
43288
|
+
if (spec.kind !== "natural" || !has(spec.table)) continue;
|
|
43289
|
+
const cols = (spec.keyRefs ?? []).filter((r) => r.table === "tasks_tasks").map((r) => r.column);
|
|
43290
|
+
if (cols.length === 0) continue;
|
|
43291
|
+
nativeDb.prepare(
|
|
43292
|
+
`UPDATE main.${quoteIdent2(spec.table)} SET uid = NULL WHERE ${cols.map((c) => `${quoteIdent2(c)} = ?`).join(" OR ")}`
|
|
43293
|
+
).run(...cols.map(() => taskId));
|
|
43294
|
+
}
|
|
43295
|
+
const children = ["tasks_task_acceptance_criteria_history", "tasks_evidence_ac_bindings"].filter(
|
|
43296
|
+
has
|
|
43297
|
+
);
|
|
43298
|
+
const criteria = has("tasks_task_acceptance_criteria") ? nativeDb.prepare("SELECT id, uid FROM tasks_task_acceptance_criteria WHERE task_id = ?").all(taskId) : [];
|
|
43299
|
+
if (criteria.length > 0) {
|
|
43300
|
+
nativeDb.prepare(
|
|
43301
|
+
"UPDATE tasks_task_acceptance_criteria SET uid = NULL, birth_fp = NULL WHERE task_id = ?"
|
|
43302
|
+
).run(taskId);
|
|
43303
|
+
}
|
|
43304
|
+
fillRowUids(nativeDb, "project");
|
|
43305
|
+
const newUid = nativeDb.prepare("SELECT uid FROM tasks_task_acceptance_criteria WHERE id = ?");
|
|
43306
|
+
let rekeyed = 0;
|
|
43307
|
+
for (const ac of criteria) {
|
|
43308
|
+
const now = newUid.get(ac.id)?.uid ?? null;
|
|
43309
|
+
for (const table of children) {
|
|
43310
|
+
rekeyed += Number(
|
|
43311
|
+
nativeDb.prepare(
|
|
43312
|
+
`UPDATE main.${quoteIdent2(table)} SET ac_uid = ?, birth_fp = NULL
|
|
43313
|
+
WHERE ac_id = ? OR (? IS NOT NULL AND ac_uid = ?)`
|
|
43314
|
+
).run(now, ac.id, ac.uid, ac.uid).changes
|
|
43315
|
+
);
|
|
43316
|
+
}
|
|
43317
|
+
}
|
|
43318
|
+
if (rekeyed > 0) fillRowUids(nativeDb, "project");
|
|
43319
|
+
}
|
|
42755
43320
|
function quoteIdent2(name15) {
|
|
42756
43321
|
return `"${name15.replaceAll('"', '""')}"`;
|
|
42757
43322
|
}
|
|
@@ -42839,10 +43404,50 @@ function claimPredicate(guard, allowedHolders) {
|
|
|
42839
43404
|
if (guard.mode === "force") return void 0;
|
|
42840
43405
|
const mine = guard.sessionId === null ? void 0 : eq10(holder, guard.sessionId);
|
|
42841
43406
|
if (guard.mode === "renew" || guard.mode === "release") return mine ?? sql30`0`;
|
|
42842
|
-
const related = allowedHolders.length > 0 ?
|
|
43407
|
+
const related = allowedHolders.length > 0 ? inArray6(holder, [...allowedHolders]) : void 0;
|
|
42843
43408
|
const expired = guard.mode === "take-over" ? or5(isNull4(tasksTasks.leaseExpiresAt), lte3(tasksTasks.leaseExpiresAt, guard.now)) : void 0;
|
|
42844
43409
|
return or5(isNull4(holder), mine, related, expired);
|
|
42845
43410
|
}
|
|
43411
|
+
function renameRecordKey(fromId) {
|
|
43412
|
+
return `renamed_from:tasks_tasks:${fromId}`;
|
|
43413
|
+
}
|
|
43414
|
+
function hasIdentityMeta(nativeDb) {
|
|
43415
|
+
return nativeDb.prepare(
|
|
43416
|
+
"SELECT 1 AS x FROM sqlite_master WHERE type = 'table' AND name = 'tasks_row_identity_meta'"
|
|
43417
|
+
).get() !== void 0;
|
|
43418
|
+
}
|
|
43419
|
+
function recordLocalRename(nativeDb, uid, fromId, toId, fromVersion) {
|
|
43420
|
+
if (!hasIdentityMeta(nativeDb)) return;
|
|
43421
|
+
const record2 = { uid, fromVersion, toId, at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
43422
|
+
writeRowIdentityMetaNative(nativeDb, renameRecordKey(fromId), JSON.stringify(record2));
|
|
43423
|
+
}
|
|
43424
|
+
function assertNotRenamed(nativeDb, taskId, guard, current) {
|
|
43425
|
+
if (!nativeDb || !hasIdentityMeta(nativeDb)) return;
|
|
43426
|
+
const raw = nativeDb.prepare("SELECT value FROM tasks_row_identity_meta WHERE key = ?").get(renameRecordKey(taskId));
|
|
43427
|
+
if (!raw) return;
|
|
43428
|
+
let record2;
|
|
43429
|
+
try {
|
|
43430
|
+
record2 = JSON.parse(raw.value);
|
|
43431
|
+
} catch {
|
|
43432
|
+
return;
|
|
43433
|
+
}
|
|
43434
|
+
if (Date.now() - Date.parse(record2.at) > RENAMED_RECENT_MS) return;
|
|
43435
|
+
const renamed = nativeDb.prepare("SELECT id, claimed_by_session AS claimedBySession FROM tasks_tasks WHERE uid = ?").get(record2.uid);
|
|
43436
|
+
if (!renamed || renamed.id === taskId) return;
|
|
43437
|
+
const expected = guard.expectedUpdatedAt;
|
|
43438
|
+
const session = guard.claim?.sessionId ?? null;
|
|
43439
|
+
const holdsRenamedClaim = session !== null && (guard.claim?.mode === "renew" || guard.claim?.mode === "release") && renamed.claimedBySession === session && current?.claimedBySession !== session;
|
|
43440
|
+
const readRenamed = expected !== void 0 && expected === record2.fromVersion && (current === void 0 || taskVersion(current) !== expected);
|
|
43441
|
+
if (!(current === void 0 || holdsRenamedClaim || readRenamed)) return;
|
|
43442
|
+
throw new CleoError(
|
|
43443
|
+
26 /* TASK_RENAMED */,
|
|
43444
|
+
`Task ${taskId} is now ${renamed.id}: sync re-numbered it after a display-id collision, and ${taskId} ${current ? "names another task" : "names no task"}; nothing was written`,
|
|
43445
|
+
{
|
|
43446
|
+
fix: `Re-read it with 'cleo show ${renamed.id}' and retry against ${renamed.id}.`,
|
|
43447
|
+
details: { field: "taskId", actual: taskId, expected: renamed.id }
|
|
43448
|
+
}
|
|
43449
|
+
);
|
|
43450
|
+
}
|
|
42846
43451
|
function assertClaimAllowed(taskId, row, guard, allowedHolders) {
|
|
42847
43452
|
const stored = claimFromColumns(row);
|
|
42848
43453
|
if (claimAllows(stored, guard.mode, guard.sessionId, guard.now, allowedHolders)) return;
|
|
@@ -43017,13 +43622,13 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43017
43622
|
const db = await getDb(cwd);
|
|
43018
43623
|
const conditions = [];
|
|
43019
43624
|
if (query.ids && query.ids.length > 0) {
|
|
43020
|
-
conditions.push(
|
|
43625
|
+
conditions.push(inArray6(tasksAuditLog.id, [...query.ids]));
|
|
43021
43626
|
}
|
|
43022
43627
|
if (query.taskIds && query.taskIds.length > 0) {
|
|
43023
|
-
conditions.push(
|
|
43628
|
+
conditions.push(inArray6(tasksAuditLog.taskId, [...query.taskIds]));
|
|
43024
43629
|
}
|
|
43025
43630
|
if (query.actions && query.actions.length > 0) {
|
|
43026
|
-
conditions.push(
|
|
43631
|
+
conditions.push(inArray6(tasksAuditLog.action, [...query.actions]));
|
|
43027
43632
|
}
|
|
43028
43633
|
if (query.since) {
|
|
43029
43634
|
conditions.push(sql30`${tasksAuditLog.timestamp} >= ${query.since}`);
|
|
@@ -43056,8 +43661,13 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43056
43661
|
async upsertSingleTask(task) {
|
|
43057
43662
|
await accessor.transaction((tx) => tx.upsertSingleTask(task));
|
|
43058
43663
|
},
|
|
43059
|
-
async insertNewTask(task) {
|
|
43060
|
-
await accessor.transaction((tx) => tx.insertNewTask(task));
|
|
43664
|
+
async insertNewTask(task, identity) {
|
|
43665
|
+
await accessor.transaction((tx) => tx.insertNewTask(task, identity));
|
|
43666
|
+
},
|
|
43667
|
+
async getTaskIdentities(taskIds) {
|
|
43668
|
+
if (taskIds.length === 0) return [];
|
|
43669
|
+
const db = await getDb(cwd);
|
|
43670
|
+
return db.select({ id: tasksTasks.id, uid: tasksTasks.uid, birthFp: tasksTasks.birthFp }).from(tasksTasks).where(inArray6(tasksTasks.id, taskIds)).all();
|
|
43061
43671
|
},
|
|
43062
43672
|
async addRelation(taskId, relatedTo, relationType, reason) {
|
|
43063
43673
|
return accessor.transaction(async () => {
|
|
@@ -43234,7 +43844,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43234
43844
|
if (!statuses.includes("archived")) {
|
|
43235
43845
|
conditions.push(ne2(tasksTasks.status, "archived"));
|
|
43236
43846
|
}
|
|
43237
|
-
conditions.push(
|
|
43847
|
+
conditions.push(inArray6(tasksTasks.status, statuses));
|
|
43238
43848
|
} else if (filters.excludeStatus) {
|
|
43239
43849
|
const excluded = Array.isArray(filters.excludeStatus) ? filters.excludeStatus : [filters.excludeStatus];
|
|
43240
43850
|
for (const s of excluded) {
|
|
@@ -43248,11 +43858,11 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43248
43858
|
if (filters.phase) conditions.push(eq10(tasksTasks.phase, filters.phase));
|
|
43249
43859
|
if (filters.severity) {
|
|
43250
43860
|
const severities = Array.isArray(filters.severity) ? filters.severity : [filters.severity];
|
|
43251
|
-
conditions.push(
|
|
43861
|
+
conditions.push(inArray6(tasksTasks.severity, severities));
|
|
43252
43862
|
}
|
|
43253
43863
|
if (filters.kind) {
|
|
43254
43864
|
const kinds = Array.isArray(filters.kind) ? filters.kind : [filters.kind];
|
|
43255
|
-
conditions.push(
|
|
43865
|
+
conditions.push(inArray6(tasksTasks.kind, kinds));
|
|
43256
43866
|
}
|
|
43257
43867
|
if (filters.parentId !== void 0) {
|
|
43258
43868
|
if (filters.parentId === null) {
|
|
@@ -43273,7 +43883,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43273
43883
|
}
|
|
43274
43884
|
if (filters.label) {
|
|
43275
43885
|
const labelMatchIds = db.select({ taskId: tasksTaskLabels.taskId }).from(tasksTaskLabels).where(eq10(tasksTaskLabels.label, filters.label));
|
|
43276
|
-
conditions.push(
|
|
43886
|
+
conditions.push(inArray6(tasksTasks.id, labelMatchIds));
|
|
43277
43887
|
}
|
|
43278
43888
|
const where = conditions.length > 0 ? and8(...conditions) : void 0;
|
|
43279
43889
|
const countResult = await db.select({ count: sql30`count(*)` }).from(tasksTasks).where(where).get();
|
|
@@ -43316,7 +43926,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43316
43926
|
const conditions = [];
|
|
43317
43927
|
if (filters?.status) {
|
|
43318
43928
|
const statuses = Array.isArray(filters.status) ? filters.status : [filters.status];
|
|
43319
|
-
conditions.push(
|
|
43929
|
+
conditions.push(inArray6(tasksTasks.status, statuses));
|
|
43320
43930
|
} else {
|
|
43321
43931
|
conditions.push(ne2(tasksTasks.status, "archived"));
|
|
43322
43932
|
}
|
|
@@ -43381,7 +43991,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43381
43991
|
if (idRows.length === 0) return [];
|
|
43382
43992
|
const db = await getDb(cwd);
|
|
43383
43993
|
const ids = idRows.map((r) => r.id);
|
|
43384
|
-
const taskRows = await db.select().from(tasksTasks).where(
|
|
43994
|
+
const taskRows = await db.select().from(tasksTasks).where(inArray6(tasksTasks.id, ids)).all();
|
|
43385
43995
|
const tasks2 = taskRows.map(rowToTask);
|
|
43386
43996
|
if (tasks2.length > 0) {
|
|
43387
43997
|
const allIds = await getAllTaskIds();
|
|
@@ -43410,7 +44020,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43410
44020
|
if (idRows.length === 0) return [];
|
|
43411
44021
|
const db = await getDb(cwd);
|
|
43412
44022
|
const ids = idRows.map((r) => r.id);
|
|
43413
|
-
const rows = await db.select().from(tasksTasks).where(
|
|
44023
|
+
const rows = await db.select().from(tasksTasks).where(inArray6(tasksTasks.id, ids)).all();
|
|
43414
44024
|
const tasks2 = rows.map(rowToTask);
|
|
43415
44025
|
if (tasks2.length > 0) {
|
|
43416
44026
|
const allIds = await getAllTaskIds();
|
|
@@ -43424,7 +44034,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43424
44034
|
const depRows = await db.select().from(tasksTaskDependencies).where(eq10(tasksTaskDependencies.dependsOn, taskId)).all();
|
|
43425
44035
|
if (depRows.length === 0) return [];
|
|
43426
44036
|
const dependentIds = depRows.map((r) => r.taskId);
|
|
43427
|
-
const rows = await db.select().from(tasksTasks).where(
|
|
44037
|
+
const rows = await db.select().from(tasksTasks).where(inArray6(tasksTasks.id, dependentIds)).all();
|
|
43428
44038
|
const tasks2 = rows.map(rowToTask);
|
|
43429
44039
|
if (tasks2.length > 0) {
|
|
43430
44040
|
const allIds = await getAllTaskIds();
|
|
@@ -43454,7 +44064,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43454
44064
|
async loadTasks(taskIds) {
|
|
43455
44065
|
if (taskIds.length === 0) return [];
|
|
43456
44066
|
const db = await getDb(cwd);
|
|
43457
|
-
const rows = await db.select().from(tasksTasks).where(
|
|
44067
|
+
const rows = await db.select().from(tasksTasks).where(inArray6(tasksTasks.id, taskIds)).all();
|
|
43458
44068
|
const tasks2 = rows.map(rowToTask);
|
|
43459
44069
|
if (tasks2.length > 0) {
|
|
43460
44070
|
const allIds = await getAllTaskIds();
|
|
@@ -43508,6 +44118,9 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43508
44118
|
createdAt: tasksTasks.createdAt,
|
|
43509
44119
|
...CLAIM_COLUMNS
|
|
43510
44120
|
}).from(tasksTasks).where(eq10(tasksTasks.id, taskId)).limit(1).all();
|
|
44121
|
+
if (guard?.claim || guard?.expectedUpdatedAt !== void 0) {
|
|
44122
|
+
assertNotRenamed(getNativeTasksDb(cwd), taskId, guard, current);
|
|
44123
|
+
}
|
|
43511
44124
|
if (!current) throw new Error(`Task not found: ${taskId}`);
|
|
43512
44125
|
const claimGuard = guard?.claim;
|
|
43513
44126
|
const allowedHolders = claimGuard ? await claimAllowedHolders(db, claimGuard) : [];
|
|
@@ -43585,24 +44198,37 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43585
44198
|
nativeDb.prepare(`SAVEPOINT ${spName}`).run();
|
|
43586
44199
|
}
|
|
43587
44200
|
try {
|
|
44201
|
+
const replacedBirths = /* @__PURE__ */ new Map();
|
|
43588
44202
|
const tx = {
|
|
43589
44203
|
async upsertSingleTask(task) {
|
|
43590
44204
|
scope.assertActive();
|
|
43591
44205
|
return accessor.transaction(async () => {
|
|
43592
44206
|
scope.assertActive();
|
|
44207
|
+
if (rowUidFillEnabled() && !replacedBirths.has(task.id)) {
|
|
44208
|
+
const before = readReplacedTaskBirthNative(nativeDb, task.id);
|
|
44209
|
+
if (before) replacedBirths.set(task.id, before);
|
|
44210
|
+
}
|
|
43593
44211
|
const row = taskToRow(task);
|
|
43594
44212
|
await upsertTask(db, row);
|
|
43595
44213
|
await updateDependencies(db, task.id, task.depends ?? []);
|
|
43596
44214
|
});
|
|
43597
44215
|
},
|
|
43598
|
-
async insertNewTask(task) {
|
|
44216
|
+
async insertNewTask(task, identity) {
|
|
43599
44217
|
scope.assertActive();
|
|
43600
44218
|
return accessor.transaction(async () => {
|
|
43601
44219
|
scope.assertActive();
|
|
43602
|
-
await insertNewTask(db, taskToRow(task));
|
|
44220
|
+
await insertNewTask(db, taskToRow(task), identity);
|
|
43603
44221
|
await updateDependencies(db, task.id, task.depends ?? []);
|
|
43604
44222
|
});
|
|
43605
44223
|
},
|
|
44224
|
+
async clearTaskIdentity(taskId) {
|
|
44225
|
+
scope.assertActive();
|
|
44226
|
+
if (!rowUidFillEnabled()) return;
|
|
44227
|
+
return accessor.transaction(async () => {
|
|
44228
|
+
scope.assertActive();
|
|
44229
|
+
clearReplacedTaskIdentityNative(nativeDb, taskId, replacedBirths.get(taskId));
|
|
44230
|
+
});
|
|
44231
|
+
},
|
|
43606
44232
|
async archiveSingleTask(taskId, fields) {
|
|
43607
44233
|
scope.assertActive();
|
|
43608
44234
|
return accessor.transaction(async () => {
|
|
@@ -43749,7 +44375,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43749
44375
|
const owned = await db.select({ id: tasksTaskAcceptanceCriteria.id }).from(tasksTaskAcceptanceCriteria).where(
|
|
43750
44376
|
and8(
|
|
43751
44377
|
eq10(tasksTaskAcceptanceCriteria.taskId, taskId),
|
|
43752
|
-
|
|
44378
|
+
inArray6(tasksTaskAcceptanceCriteria.id, ids)
|
|
43753
44379
|
)
|
|
43754
44380
|
).all();
|
|
43755
44381
|
await pruneAcBindingsForAcIds(
|
|
@@ -43762,7 +44388,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
43762
44388
|
await db.delete(tasksTaskAcceptanceCriteria).where(
|
|
43763
44389
|
and8(
|
|
43764
44390
|
eq10(tasksTaskAcceptanceCriteria.taskId, taskId),
|
|
43765
|
-
|
|
44391
|
+
inArray6(tasksTaskAcceptanceCriteria.id, ids)
|
|
43766
44392
|
)
|
|
43767
44393
|
).run();
|
|
43768
44394
|
});
|
|
@@ -44021,7 +44647,7 @@ async function createOwnedSqliteDataAccessor(cwd, accessorScope) {
|
|
|
44021
44647
|
};
|
|
44022
44648
|
return accessor;
|
|
44023
44649
|
}
|
|
44024
|
-
var _txSavepointCounter, taskTransactionQueue, TaskTransactionScope, taskTransactionContext, CLAIM_COLUMNS;
|
|
44650
|
+
var _txSavepointCounter, taskTransactionQueue, TaskTransactionScope, taskTransactionContext, CLAIM_COLUMNS, RENAMED_RECENT_MS;
|
|
44025
44651
|
var init_sqlite_data_accessor = __esm({
|
|
44026
44652
|
"packages/core/src/store/sqlite-data-accessor.ts"() {
|
|
44027
44653
|
"use strict";
|
|
@@ -44035,6 +44661,8 @@ var init_sqlite_data_accessor = __esm({
|
|
|
44035
44661
|
init_cross_db_cleanup();
|
|
44036
44662
|
init_db_helpers();
|
|
44037
44663
|
init_row_identity();
|
|
44664
|
+
init_row_identity_flag();
|
|
44665
|
+
init_row_identity_registry();
|
|
44038
44666
|
init_audit2();
|
|
44039
44667
|
init_session_store();
|
|
44040
44668
|
init_sqlite3();
|
|
@@ -44067,6 +44695,7 @@ var init_sqlite_data_accessor = __esm({
|
|
|
44067
44695
|
claimedAt: tasksTasks.claimedAt,
|
|
44068
44696
|
leaseExpiresAt: tasksTasks.leaseExpiresAt
|
|
44069
44697
|
};
|
|
44698
|
+
RENAMED_RECENT_MS = 24 * 60 * 60 * 1e3;
|
|
44070
44699
|
registerRowIdentityWriters({
|
|
44071
44700
|
relinkAcUidNative,
|
|
44072
44701
|
clearAcUidGraveyardNative,
|
|
@@ -44537,7 +45166,7 @@ __export(governor_exports, {
|
|
|
44537
45166
|
resolveGovernorMode: () => resolveGovernorMode,
|
|
44538
45167
|
slotFileCount: () => slotFileCount
|
|
44539
45168
|
});
|
|
44540
|
-
import { existsSync as
|
|
45169
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync6, readdirSync as readdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
44541
45170
|
import { availableParallelism, totalmem } from "node:os";
|
|
44542
45171
|
import { join as join27 } from "node:path";
|
|
44543
45172
|
import lockfile2 from "proper-lockfile";
|
|
@@ -44611,11 +45240,11 @@ function governorSlotDir(cls) {
|
|
|
44611
45240
|
return join27(getCleoHome(), "locks", `resource-${cls}`);
|
|
44612
45241
|
}
|
|
44613
45242
|
function ensureSlotFiles(dir, count) {
|
|
44614
|
-
if (!
|
|
45243
|
+
if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
|
|
44615
45244
|
const paths = [];
|
|
44616
45245
|
for (let i = 0; i < count; i++) {
|
|
44617
45246
|
const p = join27(dir, `slot-${i}.lock`);
|
|
44618
|
-
if (!
|
|
45247
|
+
if (!existsSync21(p)) writeFileSync5(p, "", { flag: "a" });
|
|
44619
45248
|
paths.push(p);
|
|
44620
45249
|
}
|
|
44621
45250
|
return paths;
|
|
@@ -44655,7 +45284,7 @@ function shuffledIndices(n) {
|
|
|
44655
45284
|
}
|
|
44656
45285
|
async function countHeldSlots(cls, budget) {
|
|
44657
45286
|
const dir = governorSlotDir(cls);
|
|
44658
|
-
if (!
|
|
45287
|
+
if (!existsSync21(dir)) return 0;
|
|
44659
45288
|
const slots = ensureSlotFiles(dir, budget);
|
|
44660
45289
|
let held = 0;
|
|
44661
45290
|
for (const path of slots) {
|
|
@@ -44670,7 +45299,7 @@ async function countHeldSlots(cls, budget) {
|
|
|
44670
45299
|
}
|
|
44671
45300
|
function slotFileCount(cls) {
|
|
44672
45301
|
const dir = governorSlotDir(cls);
|
|
44673
|
-
if (!
|
|
45302
|
+
if (!existsSync21(dir)) return 0;
|
|
44674
45303
|
return readdirSync5(dir).filter((f) => f.startsWith("slot-") && f.endsWith(".lock")).length;
|
|
44675
45304
|
}
|
|
44676
45305
|
var _log2, _cachedMode2, _supervisorDegradeLogged, MB, STALE_MS, _supervisorHolderSeq, ResourceGovernor, governor;
|
|
@@ -45168,7 +45797,7 @@ var init_recovery = __esm({
|
|
|
45168
45797
|
// packages/core/src/store/exodus/archive.ts
|
|
45169
45798
|
import {
|
|
45170
45799
|
copyFileSync as copyFileSync5,
|
|
45171
|
-
existsSync as
|
|
45800
|
+
existsSync as existsSync22,
|
|
45172
45801
|
mkdirSync as mkdirSync7,
|
|
45173
45802
|
readFileSync as readFileSync9,
|
|
45174
45803
|
renameSync as renameSync7,
|
|
@@ -45196,7 +45825,7 @@ function hasExodusCompleteMarker(scope, cwd, targetDbPath, nativeDb) {
|
|
|
45196
45825
|
if (targetDbPath) throw error48;
|
|
45197
45826
|
return false;
|
|
45198
45827
|
}
|
|
45199
|
-
if (!
|
|
45828
|
+
if (!existsSync22(markerPath)) return false;
|
|
45200
45829
|
const marker16 = markerIdentity.parse(JSON.parse(readFileSync9(markerPath, "utf8")));
|
|
45201
45830
|
if (nativeDb && (!marker16.databaseIdentity || !hasExodusDatabaseIdentity(nativeDb, marker16.databaseIdentity)))
|
|
45202
45831
|
throw new Error(
|
|
@@ -45226,7 +45855,7 @@ function writeExodusCompleteMarker(scope, archivedSources, cwd, targetDbPath, da
|
|
|
45226
45855
|
function moveFileInto(srcPath, destDir) {
|
|
45227
45856
|
mkdirSync7(destDir, { recursive: true });
|
|
45228
45857
|
let dest = join28(destDir, basename9(srcPath));
|
|
45229
|
-
if (
|
|
45858
|
+
if (existsSync22(dest)) {
|
|
45230
45859
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/Z$/, "Z");
|
|
45231
45860
|
dest = join28(destDir, `${basename9(srcPath)}.${stamp}`);
|
|
45232
45861
|
}
|
|
@@ -45239,14 +45868,14 @@ function moveFileInto(srcPath, destDir) {
|
|
|
45239
45868
|
return dest;
|
|
45240
45869
|
}
|
|
45241
45870
|
function archiveSourceDb(source, cwd, targetDbPath) {
|
|
45242
|
-
if (!
|
|
45871
|
+
if (!existsSync22(source.path)) {
|
|
45243
45872
|
return { name: source.name, sourcePath: source.path, archivedTo: null, action: "absent" };
|
|
45244
45873
|
}
|
|
45245
45874
|
const destDir = exodusArchiveDir(source.targetScope, cwd, targetDbPath);
|
|
45246
45875
|
const archivedTo = moveFileInto(source.path, destDir);
|
|
45247
45876
|
for (const suffix of SIDECAR_SUFFIXES) {
|
|
45248
45877
|
const sidecar = `${source.path}${suffix}`;
|
|
45249
|
-
if (
|
|
45878
|
+
if (existsSync22(sidecar)) {
|
|
45250
45879
|
try {
|
|
45251
45880
|
moveFileInto(sidecar, destDir);
|
|
45252
45881
|
} catch (err) {
|
|
@@ -45294,7 +45923,7 @@ function detectStrandedResidue(sources, cwd) {
|
|
|
45294
45923
|
const stranded = [];
|
|
45295
45924
|
for (const source of sources) {
|
|
45296
45925
|
if (!markedScopes.has(source.targetScope)) continue;
|
|
45297
|
-
if (
|
|
45926
|
+
if (existsSync22(source.path)) {
|
|
45298
45927
|
stranded.push({ name: source.name, path: source.path, scope: source.targetScope });
|
|
45299
45928
|
}
|
|
45300
45929
|
}
|
|
@@ -45335,13 +45964,13 @@ var init_archive2 = __esm({
|
|
|
45335
45964
|
});
|
|
45336
45965
|
|
|
45337
45966
|
// packages/core/src/store/exodus/count-parity.ts
|
|
45338
|
-
import { existsSync as
|
|
45967
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
45339
45968
|
function listTables2(db) {
|
|
45340
45969
|
return db.prepare(
|
|
45341
45970
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '__drizzle_%' ORDER BY name"
|
|
45342
45971
|
).all().map((r) => r.name);
|
|
45343
45972
|
}
|
|
45344
|
-
function
|
|
45973
|
+
function tableExists3(db, tableName) {
|
|
45345
45974
|
const escaped = tableName.replace(/'/g, "''");
|
|
45346
45975
|
return db.prepare(`SELECT 1 FROM sqlite_master WHERE type='table' AND name='${escaped}'`).get() !== void 0;
|
|
45347
45976
|
}
|
|
@@ -45356,14 +45985,14 @@ function rowCount(db, tableName) {
|
|
|
45356
45985
|
function computeCountParity(sources, projectDbPath, globalDbPath) {
|
|
45357
45986
|
const entries = [];
|
|
45358
45987
|
let skipped = 0;
|
|
45359
|
-
if (!
|
|
45988
|
+
if (!existsSync23(projectDbPath) || !existsSync23(globalDbPath)) {
|
|
45360
45989
|
return { ok: false, entries: [], deficits: [], checked: 0, skipped: 0 };
|
|
45361
45990
|
}
|
|
45362
45991
|
const projectSnap = openCleoDbSnapshot(projectDbPath, { readOnly: true });
|
|
45363
45992
|
const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
|
|
45364
45993
|
try {
|
|
45365
45994
|
for (const src of sources) {
|
|
45366
|
-
if (!
|
|
45995
|
+
if (!existsSync23(src.path)) continue;
|
|
45367
45996
|
const srcSnap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
45368
45997
|
try {
|
|
45369
45998
|
for (const legacyTable of listTables2(srcSnap.db)) {
|
|
@@ -45380,7 +46009,7 @@ function computeCountParity(sources, projectDbPath, globalDbPath) {
|
|
|
45380
46009
|
skipped++;
|
|
45381
46010
|
continue;
|
|
45382
46011
|
}
|
|
45383
|
-
const targetCount =
|
|
46012
|
+
const targetCount = tableExists3(targetSnap.db, targetTable) ? rowCount(targetSnap.db, targetTable) ?? 0 : 0;
|
|
45384
46013
|
const deficit = targetCount < sourceCount ? sourceCount - targetCount : 0;
|
|
45385
46014
|
entries.push({
|
|
45386
46015
|
sourceDb: src.name,
|
|
@@ -45421,7 +46050,7 @@ var init_count_parity = __esm({
|
|
|
45421
46050
|
});
|
|
45422
46051
|
|
|
45423
46052
|
// packages/core/src/store/exodus/plan.ts
|
|
45424
|
-
import { existsSync as
|
|
46053
|
+
import { existsSync as existsSync24, readdirSync as readdirSync6, statfsSync as statfsSync2, statSync as statSync6 } from "node:fs";
|
|
45425
46054
|
import { join as join29 } from "node:path";
|
|
45426
46055
|
function computeRequiredBytes(totalSourceBytes, largestSourceBytes) {
|
|
45427
46056
|
return Math.ceil(STAGING_HEADROOM_FACTOR * largestSourceBytes) + totalSourceBytes;
|
|
@@ -45523,7 +46152,7 @@ function buildExodusPlan(cwd) {
|
|
|
45523
46152
|
};
|
|
45524
46153
|
}
|
|
45525
46154
|
function sourcesPresent(sources) {
|
|
45526
|
-
return sources.some((s) =>
|
|
46155
|
+
return sources.some((s) => existsSync24(s.path));
|
|
45527
46156
|
}
|
|
45528
46157
|
var STAGING_HEADROOM_FACTOR, STAGING_COPY_SKIP_THRESHOLD_BYTES;
|
|
45529
46158
|
var init_plan2 = __esm({
|
|
@@ -45537,18 +46166,18 @@ var init_plan2 = __esm({
|
|
|
45537
46166
|
});
|
|
45538
46167
|
|
|
45539
46168
|
// packages/core/src/store/exodus/health.ts
|
|
45540
|
-
import { existsSync as
|
|
46169
|
+
import { existsSync as existsSync25, statSync as statSync7 } from "node:fs";
|
|
45541
46170
|
function buildExodusHealth(cwd) {
|
|
45542
46171
|
const plan = buildExodusPlan(cwd);
|
|
45543
|
-
const anyLegacyPresent = plan.sources.some((s) =>
|
|
46172
|
+
const anyLegacyPresent = plan.sources.some((s) => existsSync25(s.path));
|
|
45544
46173
|
const parity = anyLegacyPresent ? computeCountParity(plan.sources, plan.projectDbPath, plan.globalDbPath) : { ok: true, entries: [], deficits: [], checked: 0, skipped: 0 };
|
|
45545
46174
|
const consolidatedExistsByScope = {
|
|
45546
|
-
project:
|
|
45547
|
-
global:
|
|
46175
|
+
project: existsSync25(plan.projectDbPath),
|
|
46176
|
+
global: existsSync25(plan.globalDbPath)
|
|
45548
46177
|
};
|
|
45549
46178
|
const buildScope = (scope) => {
|
|
45550
46179
|
const sources = plan.sources.filter((s) => s.targetScope === scope).map((s) => {
|
|
45551
|
-
const present =
|
|
46180
|
+
const present = existsSync25(s.path);
|
|
45552
46181
|
let bytes = 0;
|
|
45553
46182
|
if (present) {
|
|
45554
46183
|
try {
|
|
@@ -45653,7 +46282,7 @@ var init_types = __esm({
|
|
|
45653
46282
|
// packages/core/src/store/exodus/migrate.ts
|
|
45654
46283
|
import {
|
|
45655
46284
|
copyFileSync as copyFileSync6,
|
|
45656
|
-
existsSync as
|
|
46285
|
+
existsSync as existsSync26,
|
|
45657
46286
|
mkdirSync as mkdirSync8,
|
|
45658
46287
|
readFileSync as readFileSync10,
|
|
45659
46288
|
renameSync as renameSync8,
|
|
@@ -45699,7 +46328,7 @@ function writeJournal(stagingDir, journal) {
|
|
|
45699
46328
|
}
|
|
45700
46329
|
function readJournal(stagingDir) {
|
|
45701
46330
|
const journalPath = join30(stagingDir, JOURNAL_FILENAME);
|
|
45702
|
-
if (!
|
|
46331
|
+
if (!existsSync26(journalPath)) return null;
|
|
45703
46332
|
try {
|
|
45704
46333
|
return JSON.parse(readFileSync10(journalPath, "utf8"));
|
|
45705
46334
|
} catch {
|
|
@@ -45709,7 +46338,7 @@ function readJournal(stagingDir) {
|
|
|
45709
46338
|
function clearExodusJournal(stagingDir) {
|
|
45710
46339
|
const journalPath = join30(stagingDir, JOURNAL_FILENAME);
|
|
45711
46340
|
try {
|
|
45712
|
-
if (!
|
|
46341
|
+
if (!existsSync26(journalPath)) return false;
|
|
45713
46342
|
unlinkSync5(journalPath);
|
|
45714
46343
|
log10.info(
|
|
45715
46344
|
{ stagingDir },
|
|
@@ -46005,7 +46634,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
46005
46634
|
mkdirSync8(stagingDir, { recursive: true });
|
|
46006
46635
|
let sqliteVersion = "unknown";
|
|
46007
46636
|
for (const src of sources) {
|
|
46008
|
-
if (
|
|
46637
|
+
if (existsSync26(src.path)) {
|
|
46009
46638
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
46010
46639
|
sqliteVersion = getSqliteVersion(snap.db);
|
|
46011
46640
|
snap.close();
|
|
@@ -46035,7 +46664,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
46035
46664
|
let reseedProject = null;
|
|
46036
46665
|
try {
|
|
46037
46666
|
for (const src of sources) {
|
|
46038
|
-
if (!
|
|
46667
|
+
if (!existsSync26(src.path)) continue;
|
|
46039
46668
|
const backupDest = join30(stagingDir, `${src.name.replace(/[^a-z0-9-]/g, "_")}-backup.db`);
|
|
46040
46669
|
const srcBytes = safeStatBytes(src.path);
|
|
46041
46670
|
const skipStagingCopy = srcBytes > plan.stagingCopyThresholdBytes;
|
|
@@ -46043,7 +46672,7 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
46043
46672
|
onProgress?.(
|
|
46044
46673
|
`Skipping full staging copy of ${src.name} (${srcBytes} bytes > ${plan.stagingCopyThresholdBytes} threshold) \u2014 source is archived, not deleted, on success.`
|
|
46045
46674
|
);
|
|
46046
|
-
} else if (!
|
|
46675
|
+
} else if (!existsSync26(backupDest)) {
|
|
46047
46676
|
onProgress?.(`Backing up ${src.name} \u2192 staging dir\u2026`);
|
|
46048
46677
|
copyFileSync6(src.path, backupDest);
|
|
46049
46678
|
backupPaths.push(backupDest);
|
|
@@ -46076,8 +46705,8 @@ async function runExodusMigrate(plan, forceCrossVersion = false, onProgress, opt
|
|
|
46076
46705
|
}
|
|
46077
46706
|
prepareExodusRecovery(projectNative, stagingDir);
|
|
46078
46707
|
if (globalNative !== null) prepareExodusRecovery(globalNative, stagingDir);
|
|
46079
|
-
const projectSources = sources.filter((s) => s.targetScope === "project" &&
|
|
46080
|
-
const globalSources = sources.filter((s) => s.targetScope === "global" &&
|
|
46708
|
+
const projectSources = sources.filter((s) => s.targetScope === "project" && existsSync26(s.path));
|
|
46709
|
+
const globalSources = sources.filter((s) => s.targetScope === "global" && existsSync26(s.path));
|
|
46081
46710
|
if (globalNative === null && globalSources.length > 0)
|
|
46082
46711
|
throw new Error("A projectOnly exodus run was given global-scope sources");
|
|
46083
46712
|
await migrateScope(
|
|
@@ -46326,7 +46955,8 @@ var init_migrate = __esm({
|
|
|
46326
46955
|
GRANDFATHERED_GUARD_TRIGGERS = [
|
|
46327
46956
|
"tasks_tasks_parent_type_matrix_insert",
|
|
46328
46957
|
"tasks_task_relations_non_containment_insert",
|
|
46329
|
-
"tasks_task_acceptance_child_target_insert"
|
|
46958
|
+
"tasks_task_acceptance_child_target_insert",
|
|
46959
|
+
"tasks_task_dependencies_cycle_guard_insert"
|
|
46330
46960
|
];
|
|
46331
46961
|
SOURCE_EPOCH_UNITS = /* @__PURE__ */ new Map([
|
|
46332
46962
|
["conduit", "seconds"],
|
|
@@ -46385,7 +47015,7 @@ __export(reconcile_exports, {
|
|
|
46385
47015
|
reconcileSupersededStores: () => reconcileSupersededStores,
|
|
46386
47016
|
unmigratedBareSources: () => unmigratedBareSources
|
|
46387
47017
|
});
|
|
46388
|
-
import { copyFileSync as copyFileSync7, existsSync as
|
|
47018
|
+
import { copyFileSync as copyFileSync7, existsSync as existsSync27, mkdirSync as mkdirSync9, mkdtempSync, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
46389
47019
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
46390
47020
|
import { basename as basename10, join as join31 } from "node:path";
|
|
46391
47021
|
function ident2(name15) {
|
|
@@ -46456,7 +47086,7 @@ function assessSupersededProjectStores(liveStorePath, sources, resolveTarget = r
|
|
|
46456
47086
|
}
|
|
46457
47087
|
function legacySourcesHoldRows(sources) {
|
|
46458
47088
|
for (const src of sources) {
|
|
46459
|
-
if (!
|
|
47089
|
+
if (!existsSync27(src.path)) continue;
|
|
46460
47090
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
46461
47091
|
try {
|
|
46462
47092
|
for (const table of orderTablesForCopy(snap.db)) {
|
|
@@ -46704,8 +47334,8 @@ async function reconcileSuppressed(projectRoot, options, liveStorePath) {
|
|
|
46704
47334
|
}
|
|
46705
47335
|
}
|
|
46706
47336
|
async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath, plan, resolveTarget, scratch) {
|
|
46707
|
-
const fileSources = plan.sources.filter((s) => s.targetScope === "project" &&
|
|
46708
|
-
const bare = !additive &&
|
|
47337
|
+
const fileSources = plan.sources.filter((s) => s.targetScope === "project" && existsSync27(s.path));
|
|
47338
|
+
const bare = !additive && existsSync27(liveStorePath) ? await bareTaskCoreSource(liveStorePath, resolveTarget, scratch) : null;
|
|
46709
47339
|
const copyResolver = additive ? (sourceName, legacyTable) => {
|
|
46710
47340
|
const r = resolveTarget(sourceName, legacyTable);
|
|
46711
47341
|
return r.kind !== "skip" && isLiveAuthoritative(sourceName, legacyTable, r.targetName) ? { kind: "skip", reason: "additive: live-authoritative task graph" } : r;
|
|
@@ -46724,7 +47354,7 @@ async function reconcileWithScratch(projectRoot, dryRun, additive, liveStorePath
|
|
|
46724
47354
|
stagingDir: null,
|
|
46725
47355
|
receiptPath: null
|
|
46726
47356
|
};
|
|
46727
|
-
if (sources.length === 0 || !
|
|
47357
|
+
if (sources.length === 0 || !existsSync27(liveStorePath)) {
|
|
46728
47358
|
return {
|
|
46729
47359
|
...base,
|
|
46730
47360
|
outcome: "nothing-to-reconcile",
|
|
@@ -46916,11 +47546,11 @@ var init_seal = __esm({
|
|
|
46916
47546
|
});
|
|
46917
47547
|
|
|
46918
47548
|
// packages/core/src/store/exodus/status.ts
|
|
46919
|
-
import { existsSync as
|
|
47549
|
+
import { existsSync as existsSync28, readdirSync as readdirSync7, readFileSync as readFileSync11, statSync as statSync9 } from "node:fs";
|
|
46920
47550
|
import { join as join32 } from "node:path";
|
|
46921
47551
|
function readJournal2(stagingDir) {
|
|
46922
47552
|
const p = join32(stagingDir, JOURNAL_FILENAME2);
|
|
46923
|
-
if (!
|
|
47553
|
+
if (!existsSync28(p)) return null;
|
|
46924
47554
|
try {
|
|
46925
47555
|
return JSON.parse(readFileSync11(p, "utf8"));
|
|
46926
47556
|
} catch {
|
|
@@ -46952,15 +47582,15 @@ function runExodusStatus(cwd) {
|
|
|
46952
47582
|
const sourcesInfo = plan.sources.map((s) => ({
|
|
46953
47583
|
name: s.name,
|
|
46954
47584
|
path: s.path,
|
|
46955
|
-
exists:
|
|
47585
|
+
exists: existsSync28(s.path),
|
|
46956
47586
|
bytes: safeBytes(s.path)
|
|
46957
47587
|
}));
|
|
46958
47588
|
return {
|
|
46959
47589
|
hasStaging: latestStaging !== null,
|
|
46960
47590
|
stagingDir: latestStaging,
|
|
46961
47591
|
journal,
|
|
46962
|
-
projectDbExists:
|
|
46963
|
-
globalDbExists:
|
|
47592
|
+
projectDbExists: existsSync28(projectDbPath),
|
|
47593
|
+
globalDbExists: existsSync28(globalDbPath),
|
|
46964
47594
|
sourcesPresent: sourcesInfo.some((s) => s.exists),
|
|
46965
47595
|
sources: sourcesInfo
|
|
46966
47596
|
};
|
|
@@ -46977,7 +47607,7 @@ var init_status = __esm({
|
|
|
46977
47607
|
});
|
|
46978
47608
|
|
|
46979
47609
|
// packages/core/src/store/exodus/verify-migration.ts
|
|
46980
|
-
import { existsSync as
|
|
47610
|
+
import { existsSync as existsSync29 } from "node:fs";
|
|
46981
47611
|
import { createRequire as createRequire10 } from "node:module";
|
|
46982
47612
|
function orderByClause(db, tableName) {
|
|
46983
47613
|
try {
|
|
@@ -47092,7 +47722,7 @@ function listTables3(db) {
|
|
|
47092
47722
|
).all();
|
|
47093
47723
|
return rows.map((r) => r.name);
|
|
47094
47724
|
}
|
|
47095
|
-
function
|
|
47725
|
+
function tableExists4(db, tableName) {
|
|
47096
47726
|
try {
|
|
47097
47727
|
const escaped = tableName.replace(/'/g, "''");
|
|
47098
47728
|
return db.prepare(`SELECT 1 FROM sqlite_master WHERE type='table' AND name='${escaped}'`).get() !== void 0;
|
|
@@ -47242,10 +47872,10 @@ function orphanAlreadyInSource(targetDb, fk, sources, resolveTarget = resolveCon
|
|
|
47242
47872
|
const anyFeeder = (targetTable, probe) => {
|
|
47243
47873
|
for (const feeder of feedersOf(targetTable)) {
|
|
47244
47874
|
const src = sources.find((s) => s.name === feeder.sourceName);
|
|
47245
|
-
if (src === void 0 || !
|
|
47875
|
+
if (src === void 0 || !existsSync29(src.path)) continue;
|
|
47246
47876
|
const snap = openCleoDbSnapshot(src.path, { readOnly: true });
|
|
47247
47877
|
try {
|
|
47248
|
-
if (!
|
|
47878
|
+
if (!tableExists4(snap.db, feeder.legacyTable)) continue;
|
|
47249
47879
|
const cols = new Set(
|
|
47250
47880
|
snap.db.prepare(`PRAGMA table_info("${feeder.legacyTable}")`).all().map((c) => c.name)
|
|
47251
47881
|
);
|
|
@@ -47297,7 +47927,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
47297
47927
|
const preExistingForeignKeyViolations = [];
|
|
47298
47928
|
const failureLines = [];
|
|
47299
47929
|
const sourceOrphanSigs = /* @__PURE__ */ new Set();
|
|
47300
|
-
if (!
|
|
47930
|
+
if (!existsSync29(projectDbPath)) {
|
|
47301
47931
|
return {
|
|
47302
47932
|
ok: false,
|
|
47303
47933
|
tables: [],
|
|
@@ -47308,7 +47938,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
47308
47938
|
error: `Consolidated project cleo.db not found at ${projectDbPath}. Run 'cleo exodus migrate' first.`
|
|
47309
47939
|
};
|
|
47310
47940
|
}
|
|
47311
|
-
if (!
|
|
47941
|
+
if (!existsSync29(globalDbPath)) {
|
|
47312
47942
|
return {
|
|
47313
47943
|
ok: false,
|
|
47314
47944
|
tables: [],
|
|
@@ -47323,7 +47953,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
47323
47953
|
const globalSnap = openCleoDbSnapshot(globalDbPath, { readOnly: true });
|
|
47324
47954
|
try {
|
|
47325
47955
|
for (const src of sources) {
|
|
47326
|
-
if (!
|
|
47956
|
+
if (!existsSync29(src.path)) {
|
|
47327
47957
|
onProgress?.(`Skipping ${src.name} (not present)`);
|
|
47328
47958
|
continue;
|
|
47329
47959
|
}
|
|
@@ -47448,7 +48078,7 @@ function verifyMigration(sources, projectDbPath, globalDbPath, onProgress, resol
|
|
|
47448
48078
|
targetOrphans.push(...foreignKeyCheck(globalSnap.db, "global"));
|
|
47449
48079
|
foreignKeyViolations.push(...targetOrphans);
|
|
47450
48080
|
for (const fk of targetOrphans) {
|
|
47451
|
-
const orphanDb =
|
|
48081
|
+
const orphanDb = tableExists4(projectSnap.db, fk.table) ? projectSnap.db : globalSnap.db;
|
|
47452
48082
|
const sig = orphanSignature(orphanDb, fk);
|
|
47453
48083
|
const preExisting = sourceOrphanSigs.has(sig) || orphanAlreadyInSource(orphanDb, fk, sources, resolveTarget);
|
|
47454
48084
|
if (preExisting) {
|
|
@@ -47614,7 +48244,7 @@ __export(on_open_exports, {
|
|
|
47614
48244
|
maybeRunExodusOnOpen: () => maybeRunExodusOnOpen,
|
|
47615
48245
|
withExodusOnOpenSuppressed: () => withExodusOnOpenSuppressed
|
|
47616
48246
|
});
|
|
47617
|
-
import { existsSync as
|
|
48247
|
+
import { existsSync as existsSync30, mkdtempSync as mkdtempSync2, rmSync as rmSync4 } from "node:fs";
|
|
47618
48248
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
47619
48249
|
import { join as join33, resolve as resolve13 } from "node:path";
|
|
47620
48250
|
async function withExodusOnOpenSuppressed(dbPath, fn) {
|
|
@@ -47656,7 +48286,7 @@ function remedyFor(scope) {
|
|
|
47656
48286
|
}
|
|
47657
48287
|
async function strandedLegacySources(scope, cwd) {
|
|
47658
48288
|
const { buildExodusPlan: buildExodusPlan2, legacySourcesHoldRows: legacySourcesHoldRows2 } = await Promise.resolve().then(() => (init_exodus(), exodus_exports));
|
|
47659
|
-
return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope &&
|
|
48289
|
+
return buildExodusPlan2(cwd).sources.filter((s) => s.targetScope === scope && existsSync30(s.path)).filter((s) => legacySourcesHoldRows2([s])).map((s) => s.name);
|
|
47660
48290
|
}
|
|
47661
48291
|
async function exodusStoreRewriteRefusal(dbPath, cwd) {
|
|
47662
48292
|
const { assertOwnerStoreRewriteConfirmed: assertOwnerStoreRewriteConfirmed2, invocationDirectory: invocationDirectory2 } = await Promise.resolve().then(() => (init_worktree_isolation_guard(), worktree_isolation_guard_exports));
|
|
@@ -47788,7 +48418,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
47788
48418
|
};
|
|
47789
48419
|
}
|
|
47790
48420
|
const scopeSources = plan.sources.filter((s) => s.targetScope === scope);
|
|
47791
|
-
if (!scopeSources.some((s) =>
|
|
48421
|
+
if (!scopeSources.some((s) => existsSync30(s.path))) {
|
|
47792
48422
|
return {
|
|
47793
48423
|
outcome: "skipped",
|
|
47794
48424
|
reason: `no legacy ${scope}-scope source DBs present (fresh install or cross-scope-only)`
|
|
@@ -47813,7 +48443,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
47813
48443
|
{
|
|
47814
48444
|
scope,
|
|
47815
48445
|
dbPath,
|
|
47816
|
-
sources: plan.sources.filter((s) =>
|
|
48446
|
+
sources: plan.sources.filter((s) => existsSync30(s.path)).map((s) => s.name)
|
|
47817
48447
|
},
|
|
47818
48448
|
"exodus-on-open: consolidated cleo.db is empty and legacy data present \u2014 auto-migrating"
|
|
47819
48449
|
);
|
|
@@ -47826,7 +48456,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
47826
48456
|
const bare = scope === "project" ? await unmigratedBareSources2(
|
|
47827
48457
|
dbPath,
|
|
47828
48458
|
resolveTarget,
|
|
47829
|
-
plan.sources.find((s) => s.name === "tasks" &&
|
|
48459
|
+
plan.sources.find((s) => s.name === "tasks" && existsSync30(s.path))?.path,
|
|
47830
48460
|
bareScratch
|
|
47831
48461
|
) : { first: [], last: [] };
|
|
47832
48462
|
const migratePlan = { ...plan, sources: [...bare.first, ...plan.sources, ...bare.last] };
|
|
@@ -47890,7 +48520,7 @@ async function runExodusOnOpen(scope, dbPath, nativeDb, cwd) {
|
|
|
47890
48520
|
"exodus-on-open: parity verified \u2014 legacy data migrated into consolidated cleo.db"
|
|
47891
48521
|
);
|
|
47892
48522
|
try {
|
|
47893
|
-
const consumed = plan.sources.filter((s) =>
|
|
48523
|
+
const consumed = plan.sources.filter((s) => existsSync30(s.path));
|
|
47894
48524
|
const identities = await sealTargets(plan, consumed);
|
|
47895
48525
|
const archiveResult = archiveMigratedSources(consumed, cwd, plan, identities);
|
|
47896
48526
|
log14.info(
|
|
@@ -47965,7 +48595,7 @@ __export(dual_scope_db_exports, {
|
|
|
47965
48595
|
upsertIdempotent: () => upsertIdempotent,
|
|
47966
48596
|
withStoreSchemaOwnership: () => withStoreSchemaOwnership
|
|
47967
48597
|
});
|
|
47968
|
-
import { existsSync as
|
|
48598
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync10 } from "node:fs";
|
|
47969
48599
|
import { createRequire as createRequire11 } from "node:module";
|
|
47970
48600
|
import { dirname as dirname21, join as join34, resolve as resolve14 } from "node:path";
|
|
47971
48601
|
function getDualScopeNativeDb(handle) {
|
|
@@ -48038,11 +48668,15 @@ async function openDualScopeDb(scope, cwd, options) {
|
|
|
48038
48668
|
open
|
|
48039
48669
|
) : open();
|
|
48040
48670
|
}
|
|
48671
|
+
function identityWorkOnOpen(nativeDb, scope) {
|
|
48672
|
+
if (ROW_IDENTITY[scope].length === 0) return false;
|
|
48673
|
+
return rowUidFillEnabled() || missingRowIdentitySchema(nativeDb).length > 0;
|
|
48674
|
+
}
|
|
48041
48675
|
async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
|
|
48042
48676
|
execution?.assertActive();
|
|
48043
48677
|
log15.debug({ scope, dbPath }, "opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)");
|
|
48044
48678
|
const dir = dirname21(dbPath);
|
|
48045
|
-
if (!
|
|
48679
|
+
if (!existsSync31(dir)) {
|
|
48046
48680
|
mkdirSync10(dir, { recursive: true });
|
|
48047
48681
|
}
|
|
48048
48682
|
execution?.assertActive();
|
|
@@ -48075,9 +48709,12 @@ async function openDedicatedDualScopeDb(scope, dbPath, log15, execution) {
|
|
|
48075
48709
|
`dual-scope-db[${scope}]`
|
|
48076
48710
|
);
|
|
48077
48711
|
execution?.assertActive();
|
|
48078
|
-
if (
|
|
48712
|
+
if (identityWorkOnOpen(nativeDb, scope)) {
|
|
48079
48713
|
await Promise.resolve().then(() => (init_sqlite_data_accessor(), sqlite_data_accessor_exports));
|
|
48080
|
-
|
|
48714
|
+
healRowIdentitySchema(nativeDb, scope);
|
|
48715
|
+
if (rowUidFillEnabled()) {
|
|
48716
|
+
prepareRowIdentity(nativeDb, scope, { triggers: false });
|
|
48717
|
+
}
|
|
48081
48718
|
}
|
|
48082
48719
|
execution?.assertActive();
|
|
48083
48720
|
log15.debug({ scope, dbPath }, "DEDICATED dual-scope cleo.db ready (T11782 FIX D)");
|
|
@@ -48190,7 +48827,7 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
48190
48827
|
execution?.assertActive();
|
|
48191
48828
|
log15.debug({ scope, dbPath: normalizedPath }, "opening dual-scope cleo.db");
|
|
48192
48829
|
const dir = dirname21(normalizedPath);
|
|
48193
|
-
if (!
|
|
48830
|
+
if (!existsSync31(dir)) {
|
|
48194
48831
|
mkdirSync10(dir, { recursive: true });
|
|
48195
48832
|
}
|
|
48196
48833
|
execution?.assertActive();
|
|
@@ -48223,9 +48860,12 @@ async function openDualScopeDbAtPath(scope, dbPath, exodusCwd, options) {
|
|
|
48223
48860
|
`dual-scope-db[${scope}]`
|
|
48224
48861
|
);
|
|
48225
48862
|
execution?.assertActive();
|
|
48226
|
-
if (
|
|
48863
|
+
if (identityWorkOnOpen(nativeDb, scope)) {
|
|
48227
48864
|
await Promise.resolve().then(() => (init_sqlite_data_accessor(), sqlite_data_accessor_exports));
|
|
48228
|
-
|
|
48865
|
+
healRowIdentitySchema(nativeDb, scope);
|
|
48866
|
+
if (rowUidFillEnabled()) {
|
|
48867
|
+
prepareRowIdentity(nativeDb, scope);
|
|
48868
|
+
}
|
|
48229
48869
|
}
|
|
48230
48870
|
execution?.assertActive();
|
|
48231
48871
|
log15.debug({ scope, dbPath: normalizedPath }, "dual-scope cleo.db ready");
|
|
@@ -49355,7 +49995,7 @@ __export(nexus_sqlite_exports, {
|
|
|
49355
49995
|
resetNexusDbState: () => resetNexusDbState,
|
|
49356
49996
|
resolveNexusMigrationsFolder: () => resolveNexusMigrationsFolder
|
|
49357
49997
|
});
|
|
49358
|
-
import { copyFileSync as copyFileSync8, existsSync as
|
|
49998
|
+
import { copyFileSync as copyFileSync8, existsSync as existsSync32 } from "node:fs";
|
|
49359
49999
|
import { join as join35 } from "node:path";
|
|
49360
50000
|
function getNexusDbPath(cwd) {
|
|
49361
50001
|
return resolveDualScopeDbPath("project", cwd);
|
|
@@ -49407,7 +50047,7 @@ function detectAndWarnOnNestedNexus() {
|
|
|
49407
50047
|
} catch {
|
|
49408
50048
|
return false;
|
|
49409
50049
|
}
|
|
49410
|
-
if (!
|
|
50050
|
+
if (!existsSync32(nestedPath)) return false;
|
|
49411
50051
|
if (_warnedNestedPaths.has(nestedPath)) return false;
|
|
49412
50052
|
_warnedNestedPaths.add(nestedPath);
|
|
49413
50053
|
const canonicalPath = getNexusDbPath();
|
|
@@ -49427,7 +50067,7 @@ function detectAndWarnOnNestedNexus() {
|
|
|
49427
50067
|
function _resetNestedNexusWarningGate() {
|
|
49428
50068
|
_warnedNestedPaths.clear();
|
|
49429
50069
|
}
|
|
49430
|
-
function
|
|
50070
|
+
function tableExists5(nativeDb, tableName) {
|
|
49431
50071
|
const result = nativeDb.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(tableName);
|
|
49432
50072
|
return !!result;
|
|
49433
50073
|
}
|
|
@@ -49436,7 +50076,7 @@ function objectExists(nativeDb, type, name15) {
|
|
|
49436
50076
|
return !!result;
|
|
49437
50077
|
}
|
|
49438
50078
|
function ensureNexusFts5(nativeDb) {
|
|
49439
|
-
if (!
|
|
50079
|
+
if (!tableExists5(nativeDb, "nexus_nodes")) return;
|
|
49440
50080
|
if (!objectExists(nativeDb, "table", "nexus_symbols_fts")) {
|
|
49441
50081
|
nativeDb.exec(`
|
|
49442
50082
|
CREATE VIRTUAL TABLE nexus_symbols_fts USING fts5(
|
|
@@ -49482,7 +50122,7 @@ function ensureNexusFts5(nativeDb) {
|
|
|
49482
50122
|
`);
|
|
49483
50123
|
}
|
|
49484
50124
|
function ensureNexusRelationWeights(nativeDb) {
|
|
49485
|
-
if (!
|
|
50125
|
+
if (!tableExists5(nativeDb, "nexus_relations")) return;
|
|
49486
50126
|
nativeDb.exec(`
|
|
49487
50127
|
CREATE TABLE IF NOT EXISTS nexus_relation_weights (
|
|
49488
50128
|
relation_id TEXT PRIMARY KEY NOT NULL,
|
|
@@ -49564,9 +50204,9 @@ function ensureNexusRelationWeights(nativeDb) {
|
|
|
49564
50204
|
}
|
|
49565
50205
|
function runNexusMigrations(nativeDb, db, dbPath) {
|
|
49566
50206
|
const migrationsFolder = resolveNexusMigrationsFolder();
|
|
49567
|
-
if (
|
|
50207
|
+
if (tableExists5(nativeDb, "nexus_nodes")) {
|
|
49568
50208
|
const backupPath = dbPath.replace(/\.db$/, "-pre-cleo.db.bak");
|
|
49569
|
-
if (!
|
|
50209
|
+
if (!existsSync32(backupPath)) {
|
|
49570
50210
|
try {
|
|
49571
50211
|
copyFileSync8(dbPath, backupPath);
|
|
49572
50212
|
} catch {
|
|
@@ -49696,13 +50336,13 @@ var init_legacy_alias = __esm({
|
|
|
49696
50336
|
|
|
49697
50337
|
// packages/core/src/llm/stable-device-id.ts
|
|
49698
50338
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
49699
|
-
import { existsSync as
|
|
50339
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync11, readFileSync as readFileSync12, renameSync as renameSync9, writeFileSync as writeFileSync9 } from "node:fs";
|
|
49700
50340
|
import { dirname as dirname22 } from "node:path";
|
|
49701
50341
|
import { resolveStableDeviceIdPath } from "@cleocode/paths";
|
|
49702
50342
|
function getStableDeviceId() {
|
|
49703
50343
|
if (_cachedDeviceId !== null) return _cachedDeviceId;
|
|
49704
50344
|
const path = resolveStableDeviceIdPath();
|
|
49705
|
-
if (
|
|
50345
|
+
if (existsSync33(path)) {
|
|
49706
50346
|
try {
|
|
49707
50347
|
const raw = readFileSync12(path, "utf-8").trim();
|
|
49708
50348
|
if (raw.length > 0) {
|
|
@@ -49715,7 +50355,7 @@ function getStableDeviceId() {
|
|
|
49715
50355
|
const fresh = randomUUID3();
|
|
49716
50356
|
try {
|
|
49717
50357
|
const dir = dirname22(path);
|
|
49718
|
-
if (!
|
|
50358
|
+
if (!existsSync33(dir)) {
|
|
49719
50359
|
mkdirSync11(dir, { recursive: true });
|
|
49720
50360
|
}
|
|
49721
50361
|
const tmpPath = `${path}.tmp.${process.pid}`;
|
|
@@ -49791,11 +50431,11 @@ __export(path_map_exports, {
|
|
|
49791
50431
|
supersededRegistryPath: () => supersededRegistryPath,
|
|
49792
50432
|
touchProjectLocation: () => touchProjectLocation
|
|
49793
50433
|
});
|
|
49794
|
-
import { existsSync as
|
|
50434
|
+
import { existsSync as existsSync34, lstatSync, readdirSync as readdirSync8 } from "node:fs";
|
|
49795
50435
|
import { lstat, readdir as readdir2 } from "node:fs/promises";
|
|
49796
50436
|
import { isAbsolute as isAbsolute5, join as join36, relative as relative3, sep as sep5 } from "node:path";
|
|
49797
50437
|
import { canonicalizePath as canonicalizePath3, readDeclaredProjectIdentity as readDeclaredProjectIdentity4 } from "@cleocode/paths";
|
|
49798
|
-
import { and as and9, desc as desc3, eq as eq12, inArray as
|
|
50438
|
+
import { and as and9, desc as desc3, eq as eq12, inArray as inArray7, ne as ne3 } from "drizzle-orm";
|
|
49799
50439
|
function holdingKey(projectId, path) {
|
|
49800
50440
|
return `${projectId}\0${path}`;
|
|
49801
50441
|
}
|
|
@@ -49943,7 +50583,7 @@ function decideEncounterBinding(db, record2) {
|
|
|
49943
50583
|
const here = db.select({ state: projectLocations.state, checkoutNonce: projectLocations.checkoutNonce }).from(projectLocations).where(
|
|
49944
50584
|
and9(
|
|
49945
50585
|
eq12(projectLocations.projectId, record2.projectId),
|
|
49946
|
-
|
|
50586
|
+
inArray7(projectLocations.deviceId, [deviceId, LOCAL_DEVICE_SENTINEL]),
|
|
49947
50587
|
eq12(projectLocations.path, record2.projectPath)
|
|
49948
50588
|
)
|
|
49949
50589
|
).all();
|
|
@@ -49954,7 +50594,7 @@ function decideEncounterBinding(db, record2) {
|
|
|
49954
50594
|
const previous = () => db.select({ checkoutNonce: projectLocations.checkoutNonce }).from(projectLocations).where(
|
|
49955
50595
|
and9(
|
|
49956
50596
|
eq12(projectLocations.projectId, record2.projectId),
|
|
49957
|
-
|
|
50597
|
+
inArray7(projectLocations.deviceId, [deviceId, LOCAL_DEVICE_SENTINEL]),
|
|
49958
50598
|
eq12(projectLocations.path, oldPath)
|
|
49959
50599
|
)
|
|
49960
50600
|
).all();
|
|
@@ -50002,7 +50642,7 @@ function hasOtherLiveLocation(db, record2, deviceId) {
|
|
|
50002
50642
|
ne3(projectLocations.path, record2.projectPath)
|
|
50003
50643
|
)
|
|
50004
50644
|
).all().some(
|
|
50005
|
-
(location) => isStrictlyInside(record2.projectPath, location.path) &&
|
|
50645
|
+
(location) => isStrictlyInside(record2.projectPath, location.path) && existsSync34(location.path) && readDeclaredProjectIdentity4(location.path)?.projectId === record2.projectId
|
|
50006
50646
|
);
|
|
50007
50647
|
}
|
|
50008
50648
|
function demoteProjectLocation(db, record2, state) {
|
|
@@ -50053,7 +50693,7 @@ function rehomeDisplacedRows(db, projectId, projectPath, deviceId, probed) {
|
|
|
50053
50693
|
).orderBy(desc3(projectLocations.lastSeen)).all();
|
|
50054
50694
|
const present = (path) => {
|
|
50055
50695
|
const holding = probed?.get(holdingKey(row.projectId, path));
|
|
50056
|
-
return holding === void 0 ?
|
|
50696
|
+
return holding === void 0 ? existsSync34(path) : holding === "yes";
|
|
50057
50697
|
};
|
|
50058
50698
|
const home = candidates.find(
|
|
50059
50699
|
(c) => present(c.path) && db.select({ projectId: projectRegistry.projectId }).from(projectRegistry).where(eq12(projectRegistry.projectPath, c.path)).all().length === 0
|
|
@@ -50082,7 +50722,7 @@ async function listProjectCheckouts(projectId, opts = {}) {
|
|
|
50082
50722
|
projectHash: generateProjectHash(row.path),
|
|
50083
50723
|
firstSeen: row.firstSeen,
|
|
50084
50724
|
lastSeen: row.lastSeen,
|
|
50085
|
-
exists: local &&
|
|
50725
|
+
exists: local && existsSync34(row.path),
|
|
50086
50726
|
deviceId: local ? deviceId : row.deviceId,
|
|
50087
50727
|
state: row.state
|
|
50088
50728
|
});
|
|
@@ -50115,7 +50755,7 @@ __export(project_activity_exports, {
|
|
|
50115
50755
|
projectLastActivitySql: () => projectLastActivitySql,
|
|
50116
50756
|
projectLastActivitySqlText: () => projectLastActivitySqlText
|
|
50117
50757
|
});
|
|
50118
|
-
import { eq as eq13, inArray as
|
|
50758
|
+
import { eq as eq13, inArray as inArray8, sql as sql32 } from "drizzle-orm";
|
|
50119
50759
|
function normalizeRegistryTimestamp(value) {
|
|
50120
50760
|
if (value === null || value === void 0 || value.length === 0) return null;
|
|
50121
50761
|
const iso = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?$/.test(value) ? `${value.replace(" ", "T")}Z` : value;
|
|
@@ -50144,7 +50784,7 @@ function markProjectsProbed(db, projectIds, now = /* @__PURE__ */ new Date()) {
|
|
|
50144
50784
|
for (let i = 0; i < ids.length; i += PROBED_CHUNK) {
|
|
50145
50785
|
const chunk = ids.slice(i, i + PROBED_CHUNK);
|
|
50146
50786
|
changed += Number(
|
|
50147
|
-
db.update(projectRegistry).set({ lastProbedAt: at }).where(
|
|
50787
|
+
db.update(projectRegistry).set({ lastProbedAt: at }).where(inArray8(projectRegistry.projectId, chunk)).run().changes
|
|
50148
50788
|
);
|
|
50149
50789
|
}
|
|
50150
50790
|
return changed;
|
|
@@ -50177,11 +50817,11 @@ __export(checkout_nonce_exports, {
|
|
|
50177
50817
|
readCheckoutNonce: () => readCheckoutNonce
|
|
50178
50818
|
});
|
|
50179
50819
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
50180
|
-
import { existsSync as
|
|
50820
|
+
import { existsSync as existsSync35, readFileSync as readFileSync13, renameSync as renameSync10, writeFileSync as writeFileSync10 } from "node:fs";
|
|
50181
50821
|
import { join as join37 } from "node:path";
|
|
50182
50822
|
function readInfo(projectRoot) {
|
|
50183
50823
|
const path = join37(projectRoot, ".cleo", "project-info.json");
|
|
50184
|
-
if (!
|
|
50824
|
+
if (!existsSync35(path)) return null;
|
|
50185
50825
|
try {
|
|
50186
50826
|
const parsed = JSON.parse(readFileSync13(path, "utf-8"));
|
|
50187
50827
|
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
@@ -50274,7 +50914,7 @@ __export(paths_exports, {
|
|
|
50274
50914
|
validateProjectRoot: () => validateProjectRoot,
|
|
50275
50915
|
worktreeScope: () => worktreeScope
|
|
50276
50916
|
});
|
|
50277
|
-
import { existsSync as
|
|
50917
|
+
import { existsSync as existsSync36, readFileSync as readFileSync14, statSync as statSync10 } from "node:fs";
|
|
50278
50918
|
import { createRequire as createRequire12 } from "node:module";
|
|
50279
50919
|
import { homedir as homedir2 } from "node:os";
|
|
50280
50920
|
import { dirname as dirname23, join as join38, resolve as resolve15 } from "node:path";
|
|
@@ -50300,7 +50940,7 @@ function runWithWorktreeScopeFromEnv(fn) {
|
|
|
50300
50940
|
function isProjectInitialized(projectRoot) {
|
|
50301
50941
|
const root = projectRoot ?? getProjectRoot();
|
|
50302
50942
|
const cleoDir = join38(root, ".cleo");
|
|
50303
|
-
return
|
|
50943
|
+
return existsSync36(cleoDir) && existsSync36(join38(cleoDir, "tasks.db"));
|
|
50304
50944
|
}
|
|
50305
50945
|
function getCleoHome() {
|
|
50306
50946
|
return getPlatformPaths().data;
|
|
@@ -50406,7 +51046,7 @@ function _resolveProjectByCwdFromNexus(cwd) {
|
|
|
50406
51046
|
try {
|
|
50407
51047
|
const cleoHome = getCleoHome();
|
|
50408
51048
|
const globalDbPath = join38(cleoHome, "cleo.db");
|
|
50409
|
-
if (!
|
|
51049
|
+
if (!existsSync36(globalDbPath)) return null;
|
|
50410
51050
|
const start = resolve15(cwd ?? process.cwd());
|
|
50411
51051
|
let current = start;
|
|
50412
51052
|
const DatabaseSync3 = _getDatabaseSyncCtor();
|
|
@@ -50569,7 +51209,7 @@ function _cwdHasGitAncestor(cwd) {
|
|
|
50569
51209
|
while (true) {
|
|
50570
51210
|
const gitMarker = join38(current, ".git");
|
|
50571
51211
|
try {
|
|
50572
|
-
if (
|
|
51212
|
+
if (existsSync36(gitMarker)) {
|
|
50573
51213
|
return true;
|
|
50574
51214
|
}
|
|
50575
51215
|
} catch {
|
|
@@ -50647,7 +51287,7 @@ function getCleoGlobalCantAgentsDir() {
|
|
|
50647
51287
|
function getAgentOutputsDir(cwd) {
|
|
50648
51288
|
const projectRoot = getProjectRoot(cwd);
|
|
50649
51289
|
const configPath = join38(projectRoot, ".cleo", "config.json");
|
|
50650
|
-
if (
|
|
51290
|
+
if (existsSync36(configPath)) {
|
|
50651
51291
|
try {
|
|
50652
51292
|
const config2 = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
50653
51293
|
if (typeof config2.agentOutputs === "object" && config2.agentOutputs?.directory) {
|
|
@@ -50680,7 +51320,7 @@ function getManifestPath(cwd) {
|
|
|
50680
51320
|
const configPath = join38(projectRoot, ".cleo", "config.json");
|
|
50681
51321
|
const legacyFileName = ["MANIFEST", "jsonl"].join(".");
|
|
50682
51322
|
let manifestFile = legacyFileName;
|
|
50683
|
-
if (
|
|
51323
|
+
if (existsSync36(configPath)) {
|
|
50684
51324
|
try {
|
|
50685
51325
|
const config2 = JSON.parse(readFileSync14(configPath, "utf-8"));
|
|
50686
51326
|
const customFile = config2.agentOutputs?.manifestFile ?? config2.research?.manifestFile;
|
|
@@ -50736,7 +51376,7 @@ function resolveWorktreeRouting(cwdOverride) {
|
|
|
50736
51376
|
while (current !== home && current !== "/" && current !== "") {
|
|
50737
51377
|
const gitPath = join38(current, ".git");
|
|
50738
51378
|
try {
|
|
50739
|
-
if (
|
|
51379
|
+
if (existsSync36(gitPath)) {
|
|
50740
51380
|
const stat3 = statSync10(gitPath);
|
|
50741
51381
|
if (stat3.isFile()) {
|
|
50742
51382
|
worktreePath = current;
|
|
@@ -50775,7 +51415,7 @@ function detectStrayCleoDb(routing) {
|
|
|
50775
51415
|
}
|
|
50776
51416
|
const tasksDbPath = join38(routing.worktreePath, ".cleo", "tasks.db");
|
|
50777
51417
|
try {
|
|
50778
|
-
if (
|
|
51418
|
+
if (existsSync36(tasksDbPath) && statSync10(tasksDbPath).isFile()) {
|
|
50779
51419
|
return tasksDbPath;
|
|
50780
51420
|
}
|
|
50781
51421
|
} catch {
|
|
@@ -50785,7 +51425,7 @@ function detectStrayCleoDb(routing) {
|
|
|
50785
51425
|
async function resolveProjectById(projectId) {
|
|
50786
51426
|
try {
|
|
50787
51427
|
const { getNexusDb: getNexusDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
50788
|
-
if (!
|
|
51428
|
+
if (!existsSync36(getNexusRegistryDbPath2())) return null;
|
|
50789
51429
|
const { eq: eq14 } = await import("drizzle-orm");
|
|
50790
51430
|
const { projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
|
|
50791
51431
|
const db = await getNexusDb2();
|
|
@@ -50821,7 +51461,7 @@ function _rowToRegistryEntry(row) {
|
|
|
50821
51461
|
}
|
|
50822
51462
|
function _assertProjectInfoReadable(projectRoot) {
|
|
50823
51463
|
const infoPath = join38(projectRoot, ".cleo", "project-info.json");
|
|
50824
|
-
if (
|
|
51464
|
+
if (existsSync36(infoPath)) JSON.parse(readFileSync14(infoPath, "utf-8"));
|
|
50825
51465
|
}
|
|
50826
51466
|
function startProjectEncounter(key, projectRoot, infoProjectId) {
|
|
50827
51467
|
const inFlight2 = _encountersInFlight.get(key);
|
|
@@ -50870,7 +51510,7 @@ async function recordProjectEncounter(cwd, options = {}) {
|
|
|
50870
51510
|
if (!shouldAutoRegisterProject(project.projectRoot, cleoHome)) return "ephemeral";
|
|
50871
51511
|
const checkout = captureProjectScope(project.projectRoot, worktreeScope.getStore()).worktreeRoot;
|
|
50872
51512
|
const { getNexusRegistryDb: getNexusRegistryDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
50873
|
-
if (
|
|
51513
|
+
if (existsSync36(getNexusRegistryDbPath2(cleoHome))) {
|
|
50874
51514
|
const { and: and10, eq: eq14 } = await import("drizzle-orm");
|
|
50875
51515
|
const { projectLocations: projectLocations2, projectRegistry: projectRegistry2 } = await Promise.resolve().then(() => (init_nexus_schema(), nexus_schema_exports));
|
|
50876
51516
|
const { currentDeviceId: currentDeviceId2 } = await Promise.resolve().then(() => (init_path_map(), path_map_exports));
|
|
@@ -50896,7 +51536,7 @@ async function recordProjectEncounter(cwd, options = {}) {
|
|
|
50896
51536
|
}
|
|
50897
51537
|
async function markEncounterOpened(cleoHome, projectId) {
|
|
50898
51538
|
const { getNexusRegistryDb: getNexusRegistryDb2, getNexusRegistryDbPath: getNexusRegistryDbPath2 } = await Promise.resolve().then(() => (init_nexus_sqlite(), nexus_sqlite_exports));
|
|
50899
|
-
if (!
|
|
51539
|
+
if (!existsSync36(getNexusRegistryDbPath2(cleoHome))) return;
|
|
50900
51540
|
const { markProjectOpened: markProjectOpened2 } = await Promise.resolve().then(() => (init_project_activity(), project_activity_exports));
|
|
50901
51541
|
markProjectOpened2(await getNexusRegistryDb2(cleoHome), projectId);
|
|
50902
51542
|
}
|
|
@@ -51139,7 +51779,7 @@ var init_api_mode = __esm({
|
|
|
51139
51779
|
// packages/core/src/store/file-utils.ts
|
|
51140
51780
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
51141
51781
|
import {
|
|
51142
|
-
existsSync as
|
|
51782
|
+
existsSync as existsSync37,
|
|
51143
51783
|
mkdirSync as mkdirSync12,
|
|
51144
51784
|
readdirSync as readdirSync9,
|
|
51145
51785
|
readFileSync as readFileSync15,
|
|
@@ -51154,7 +51794,7 @@ function rotateBackup(filePath, mode) {
|
|
|
51154
51794
|
const name15 = basename11(filePath);
|
|
51155
51795
|
const backupDir = join39(dir, ".backups");
|
|
51156
51796
|
const dirMode = typeof mode === "number" ? modeToDirMode(mode) : void 0;
|
|
51157
|
-
if (!
|
|
51797
|
+
if (!existsSync37(backupDir)) {
|
|
51158
51798
|
mkdirSync12(backupDir, { recursive: true, mode: dirMode });
|
|
51159
51799
|
}
|
|
51160
51800
|
for (let i = MAX_BACKUPS; i >= 1; i--) {
|
|
@@ -51167,7 +51807,7 @@ function rotateBackup(filePath, mode) {
|
|
|
51167
51807
|
} else {
|
|
51168
51808
|
const next = join39(backupDir, `${name15}.${i + 1}`);
|
|
51169
51809
|
try {
|
|
51170
|
-
if (
|
|
51810
|
+
if (existsSync37(current)) renameSync11(current, next);
|
|
51171
51811
|
} catch {
|
|
51172
51812
|
}
|
|
51173
51813
|
}
|
|
@@ -51203,7 +51843,7 @@ function writeJsonFileAtomic(filePath, data, optsOrIndent = 2) {
|
|
|
51203
51843
|
writeFileSync11(tempPath, content, "utf-8");
|
|
51204
51844
|
}
|
|
51205
51845
|
try {
|
|
51206
|
-
if (
|
|
51846
|
+
if (existsSync37(filePath)) {
|
|
51207
51847
|
rotateBackup(filePath, mode);
|
|
51208
51848
|
}
|
|
51209
51849
|
renameSync11(tempPath, filePath);
|
|
@@ -51229,10 +51869,10 @@ function readJsonFile(filePath) {
|
|
|
51229
51869
|
async function withLock2(filePath, transform2, opts = {}) {
|
|
51230
51870
|
const dir = dirname24(filePath);
|
|
51231
51871
|
const dirMode = typeof opts.mode === "number" ? modeToDirMode(opts.mode) : void 0;
|
|
51232
|
-
if (!
|
|
51872
|
+
if (!existsSync37(dir)) {
|
|
51233
51873
|
mkdirSync12(dir, { recursive: true, mode: dirMode });
|
|
51234
51874
|
}
|
|
51235
|
-
if (!
|
|
51875
|
+
if (!existsSync37(filePath)) {
|
|
51236
51876
|
if (typeof opts.mode === "number") {
|
|
51237
51877
|
writeFileSync11(filePath, "", { encoding: "utf-8", mode: opts.mode });
|
|
51238
51878
|
} else {
|
|
@@ -51254,10 +51894,10 @@ async function withLock2(filePath, transform2, opts = {}) {
|
|
|
51254
51894
|
}
|
|
51255
51895
|
async function withFileLock(filePath, operation) {
|
|
51256
51896
|
const dir = dirname24(filePath);
|
|
51257
|
-
if (!
|
|
51897
|
+
if (!existsSync37(dir)) {
|
|
51258
51898
|
mkdirSync12(dir, { recursive: true });
|
|
51259
51899
|
}
|
|
51260
|
-
if (!
|
|
51900
|
+
if (!existsSync37(filePath)) {
|
|
51261
51901
|
writeFileSync11(filePath, "", "utf-8");
|
|
51262
51902
|
}
|
|
51263
51903
|
let release;
|
|
@@ -51614,7 +52254,7 @@ var init_cleo_pkce_seeder = __esm({
|
|
|
51614
52254
|
});
|
|
51615
52255
|
|
|
51616
52256
|
// packages/core/src/llm/credential-seeders/codex-cli-seeder.ts
|
|
51617
|
-
import { existsSync as
|
|
52257
|
+
import { existsSync as existsSync38, readFileSync as readFileSync18 } from "node:fs";
|
|
51618
52258
|
import { homedir as homedir4 } from "node:os";
|
|
51619
52259
|
import { join as join43 } from "node:path";
|
|
51620
52260
|
function getCodexAuthPath() {
|
|
@@ -51639,7 +52279,7 @@ var init_codex_cli_seeder = __esm({
|
|
|
51639
52279
|
*/
|
|
51640
52280
|
async seed() {
|
|
51641
52281
|
const authPath = getCodexAuthPath();
|
|
51642
|
-
if (!
|
|
52282
|
+
if (!existsSync38(authPath)) {
|
|
51643
52283
|
return { entries: [] };
|
|
51644
52284
|
}
|
|
51645
52285
|
let raw;
|
|
@@ -51834,7 +52474,7 @@ var init_google_pkce = __esm({
|
|
|
51834
52474
|
});
|
|
51835
52475
|
|
|
51836
52476
|
// packages/core/src/llm/credential-seeders/gemini-cli-seeder.ts
|
|
51837
|
-
import { existsSync as
|
|
52477
|
+
import { existsSync as existsSync39, readFileSync as readFileSync19 } from "node:fs";
|
|
51838
52478
|
import { join as join44 } from "node:path";
|
|
51839
52479
|
import { getCleoHome as getCleoHome5 } from "@cleocode/paths";
|
|
51840
52480
|
function getGoogleOauthPath() {
|
|
@@ -51883,7 +52523,7 @@ var init_gemini_cli_seeder = __esm({
|
|
|
51883
52523
|
*/
|
|
51884
52524
|
async seed() {
|
|
51885
52525
|
const path = getGoogleOauthPath();
|
|
51886
|
-
if (!
|
|
52526
|
+
if (!existsSync39(path)) {
|
|
51887
52527
|
return { entries: [] };
|
|
51888
52528
|
}
|
|
51889
52529
|
let raw;
|
|
@@ -52108,7 +52748,7 @@ var init_credential_seeders = __esm({
|
|
|
52108
52748
|
|
|
52109
52749
|
// packages/core/src/llm/global-config-migration.ts
|
|
52110
52750
|
import {
|
|
52111
|
-
existsSync as
|
|
52751
|
+
existsSync as existsSync40,
|
|
52112
52752
|
mkdirSync as mkdirSync13,
|
|
52113
52753
|
readFileSync as readFileSync20,
|
|
52114
52754
|
renameSync as renameSync12,
|
|
@@ -52134,12 +52774,12 @@ function migrateGlobalConfigToConfigDir() {
|
|
|
52134
52774
|
const source = legacyGlobalConfigPath();
|
|
52135
52775
|
const target = configDirGlobalConfigPath();
|
|
52136
52776
|
const marker16 = migrationMarkerPath();
|
|
52137
|
-
if (
|
|
52138
|
-
if (!
|
|
52777
|
+
if (existsSync40(marker16)) return false;
|
|
52778
|
+
if (!existsSync40(source)) {
|
|
52139
52779
|
stampMarker(marker16);
|
|
52140
52780
|
return false;
|
|
52141
52781
|
}
|
|
52142
|
-
if (
|
|
52782
|
+
if (existsSync40(target)) {
|
|
52143
52783
|
backupSourceQuiet(source);
|
|
52144
52784
|
stampMarker(marker16);
|
|
52145
52785
|
return false;
|
|
@@ -52172,7 +52812,7 @@ function migrateGlobalConfigToConfigDir() {
|
|
|
52172
52812
|
} catch (err) {
|
|
52173
52813
|
try {
|
|
52174
52814
|
const temp = tempTargetPath();
|
|
52175
|
-
if (
|
|
52815
|
+
if (existsSync40(temp)) unlinkSync8(temp);
|
|
52176
52816
|
} catch {
|
|
52177
52817
|
}
|
|
52178
52818
|
console.error(
|
|
@@ -52192,7 +52832,7 @@ function stampMarker(markerPath) {
|
|
|
52192
52832
|
function backupSourceQuiet(source) {
|
|
52193
52833
|
try {
|
|
52194
52834
|
const backup = `${source}${BACKUP_SUFFIX}`;
|
|
52195
|
-
if (
|
|
52835
|
+
if (existsSync40(backup)) return;
|
|
52196
52836
|
renameSync12(source, backup);
|
|
52197
52837
|
} catch {
|
|
52198
52838
|
}
|
|
@@ -52215,7 +52855,7 @@ var init_global_config_migration = __esm({
|
|
|
52215
52855
|
});
|
|
52216
52856
|
|
|
52217
52857
|
// packages/core/src/llm/legacy-flat-key-import.ts
|
|
52218
|
-
import { existsSync as
|
|
52858
|
+
import { existsSync as existsSync41, readFileSync as readFileSync21, renameSync as renameSync13, writeFileSync as writeFileSync13 } from "node:fs";
|
|
52219
52859
|
import { join as join46 } from "node:path";
|
|
52220
52860
|
import { getCleoHome as getCleoHome7 } from "@cleocode/paths";
|
|
52221
52861
|
function migrationPaths() {
|
|
@@ -52244,7 +52884,7 @@ function writeMarker(markerPath) {
|
|
|
52244
52884
|
}
|
|
52245
52885
|
function readFlatKey(flatPath) {
|
|
52246
52886
|
try {
|
|
52247
|
-
if (!
|
|
52887
|
+
if (!existsSync41(flatPath)) return null;
|
|
52248
52888
|
const raw = readFileSync21(flatPath, "utf-8").trim();
|
|
52249
52889
|
return raw || null;
|
|
52250
52890
|
} catch (err) {
|
|
@@ -52257,7 +52897,7 @@ function readFlatKey(flatPath) {
|
|
|
52257
52897
|
}
|
|
52258
52898
|
async function importLegacyFlatAnthropicKey() {
|
|
52259
52899
|
const { flatPath, bakPath, markerPath } = migrationPaths();
|
|
52260
|
-
if (
|
|
52900
|
+
if (existsSync41(markerPath)) {
|
|
52261
52901
|
return { status: "marker-present", flatPath, bakPath: null, markerPath };
|
|
52262
52902
|
}
|
|
52263
52903
|
let existing = null;
|
|
@@ -52274,7 +52914,7 @@ async function importLegacyFlatAnthropicKey() {
|
|
|
52274
52914
|
writeMarker(markerPath);
|
|
52275
52915
|
return { status: "already-imported", flatPath, bakPath: null, markerPath };
|
|
52276
52916
|
}
|
|
52277
|
-
if (!
|
|
52917
|
+
if (!existsSync41(flatPath)) {
|
|
52278
52918
|
writeMarker(markerPath);
|
|
52279
52919
|
return { status: "no-flat-file", flatPath, bakPath: null, markerPath };
|
|
52280
52920
|
}
|
|
@@ -52336,7 +52976,7 @@ var init_legacy_flat_key_import = __esm({
|
|
|
52336
52976
|
});
|
|
52337
52977
|
|
|
52338
52978
|
// packages/core/src/llm/credentials.ts
|
|
52339
|
-
import { existsSync as
|
|
52979
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync14, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "node:fs";
|
|
52340
52980
|
import { join as join47 } from "node:path";
|
|
52341
52981
|
import { getCleoHome as getCleoHome8 } from "@cleocode/paths";
|
|
52342
52982
|
function globalConfigPath() {
|
|
@@ -52355,7 +52995,7 @@ function readGlobalProviderKey(provider) {
|
|
|
52355
52995
|
function readFlatAnthropicKey() {
|
|
52356
52996
|
try {
|
|
52357
52997
|
const keyFile = join47(getCleoHome8(), "anthropic-key");
|
|
52358
|
-
if (!
|
|
52998
|
+
if (!existsSync42(keyFile)) return null;
|
|
52359
52999
|
const stored = readFileSync22(keyFile, "utf-8").trim();
|
|
52360
53000
|
return stored || null;
|
|
52361
53001
|
} catch {
|
|
@@ -52364,7 +53004,7 @@ function readFlatAnthropicKey() {
|
|
|
52364
53004
|
}
|
|
52365
53005
|
function readProviderKeyFromConfig(configFile, provider) {
|
|
52366
53006
|
try {
|
|
52367
|
-
if (!
|
|
53007
|
+
if (!existsSync42(configFile)) return null;
|
|
52368
53008
|
const raw = readFileSync22(configFile, "utf-8");
|
|
52369
53009
|
const config2 = JSON.parse(raw);
|
|
52370
53010
|
const llm = config2["llm"];
|
|
@@ -52504,16 +53144,16 @@ __export(credentials_store_exports, {
|
|
|
52504
53144
|
pickCredentialForProviderSync: () => pickCredentialForProviderSync,
|
|
52505
53145
|
removeCredential: () => removeCredential
|
|
52506
53146
|
});
|
|
52507
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
53147
|
+
import { chmodSync as chmodSync2, existsSync as existsSync43, mkdirSync as mkdirSync15, readFileSync as readFileSync23, statSync as statSync11, writeFileSync as writeFileSync15 } from "node:fs";
|
|
52508
53148
|
import { dirname as dirname25, join as join48 } from "node:path";
|
|
52509
53149
|
import { getCleoHome as getCleoHome9 } from "@cleocode/paths";
|
|
52510
53150
|
function credentialsStorePath() {
|
|
52511
53151
|
return join48(getCleoHome9(), "llm-credentials.json");
|
|
52512
53152
|
}
|
|
52513
53153
|
function ensureFileInitialized(path) {
|
|
52514
|
-
if (
|
|
53154
|
+
if (existsSync43(path)) return;
|
|
52515
53155
|
const dir = dirname25(path);
|
|
52516
|
-
if (!
|
|
53156
|
+
if (!existsSync43(dir)) {
|
|
52517
53157
|
mkdirSync15(dir, { recursive: true, mode: 448 });
|
|
52518
53158
|
} else {
|
|
52519
53159
|
try {
|
|
@@ -53309,7 +53949,7 @@ var init_provider_registry = __esm({
|
|
|
53309
53949
|
});
|
|
53310
53950
|
|
|
53311
53951
|
// packages/core/src/llm/rate-limit-guard.ts
|
|
53312
|
-
import { existsSync as
|
|
53952
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync16, unlinkSync as unlinkSync9 } from "node:fs";
|
|
53313
53953
|
import { join as join50 } from "node:path";
|
|
53314
53954
|
import { getCleoHome as getCleoHome10 } from "@cleocode/paths";
|
|
53315
53955
|
function sanitize(value) {
|
|
@@ -53365,7 +54005,7 @@ async function recordRateLimit(provider, label, opts) {
|
|
|
53365
54005
|
}
|
|
53366
54006
|
const filePath = rateLimitStatePath(provider, label);
|
|
53367
54007
|
const dir = join50(getCleoHome10(), "rate-limit-state");
|
|
53368
|
-
if (!
|
|
54008
|
+
if (!existsSync44(dir)) {
|
|
53369
54009
|
mkdirSync16(dir, { recursive: true });
|
|
53370
54010
|
}
|
|
53371
54011
|
const state = { resetAt, recordedAt: now, source };
|
|
@@ -53950,7 +54590,7 @@ var init_local_inference_probe = __esm({
|
|
|
53950
54590
|
|
|
53951
54591
|
// packages/core/src/llm/catalog-cache.ts
|
|
53952
54592
|
import {
|
|
53953
|
-
existsSync as
|
|
54593
|
+
existsSync as existsSync45,
|
|
53954
54594
|
mkdirSync as mkdirSync17,
|
|
53955
54595
|
readdirSync as readdirSync11,
|
|
53956
54596
|
readFileSync as readFileSync24,
|
|
@@ -53968,7 +54608,7 @@ function getCatalogDir() {
|
|
|
53968
54608
|
return join51(getCleoHome11(), "llm-catalog");
|
|
53969
54609
|
}
|
|
53970
54610
|
function findLatestCacheFile(dir) {
|
|
53971
|
-
if (!
|
|
54611
|
+
if (!existsSync45(dir)) return null;
|
|
53972
54612
|
const files = readdirSync11(dir).filter((f) => f.endsWith("-models.json")).map((f) => ({ name: f, mtime: statSync13(join51(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
53973
54613
|
return files.length > 0 ? join51(dir, files[0].name) : null;
|
|
53974
54614
|
}
|