@cleocode/core 2026.4.45 → 2026.4.46

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/index.js CHANGED
@@ -11448,14 +11448,14 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
11448
11448
  const dbHashes = new Set(dbEntries.map((e) => e.hash));
11449
11449
  const allLocalHashesPresentInDb = localMigrations.every((m) => dbHashes.has(m.hash));
11450
11450
  if (allLocalHashesPresentInDb) {
11451
- const log10 = getLogger(logSubsystem);
11452
- log10.debug(
11451
+ const log11 = getLogger(logSubsystem);
11452
+ log11.debug(
11453
11453
  { extra: orphanedEntries.length },
11454
11454
  `Migration journal has ${orphanedEntries.length} entries for migrations not known to this install (DB is ahead). Skipping reconciliation.`
11455
11455
  );
11456
11456
  } else {
11457
- const log10 = getLogger(logSubsystem);
11458
- log10.warn(
11457
+ const log11 = getLogger(logSubsystem);
11458
+ log11.warn(
11459
11459
  { orphaned: orphanedEntries.length },
11460
11460
  `Detected stale migration journal entries from a previous CLEO version. Reconciling.`
11461
11461
  );
@@ -11486,8 +11486,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
11486
11486
  return cols.some((c) => c.name === column);
11487
11487
  });
11488
11488
  if (allColumnsExist) {
11489
- const log10 = getLogger(logSubsystem);
11490
- log10.warn(
11489
+ const log11 = getLogger(logSubsystem);
11490
+ log11.warn(
11491
11491
  { migration: migration.name, columns: alterMatches },
11492
11492
  `Detected partially-applied migration ${migration.name} \u2014 columns exist but journal entry missing. Auto-reconciling.`
11493
11493
  );
@@ -11505,8 +11505,8 @@ function reconcileJournal(nativeDb, migrationsFolder, existenceTable, logSubsyst
11505
11505
  for (const entry of unnamedEntries) {
11506
11506
  const migrationName = hashToName.get(entry.hash);
11507
11507
  if (!migrationName) continue;
11508
- const log10 = getLogger(logSubsystem);
11509
- log10.warn(
11508
+ const log11 = getLogger(logSubsystem);
11509
+ log11.warn(
11510
11510
  { id: entry.id, hash: entry.hash, name: migrationName },
11511
11511
  `Backfilling missing name on journal entry id=${entry.id} \u2014 Drizzle v1 beta requires name for applied-migration detection.`
11512
11512
  );
@@ -11550,8 +11550,8 @@ function ensureColumns(nativeDb, tableName, requiredColumns, logSubsystem) {
11550
11550
  const existingCols = new Set(columns.map((c) => c.name));
11551
11551
  for (const req of requiredColumns) {
11552
11552
  if (!existingCols.has(req.name)) {
11553
- const log10 = getLogger(logSubsystem);
11554
- log10.warn(
11553
+ const log11 = getLogger(logSubsystem);
11554
+ log11.warn(
11555
11555
  { column: req.name },
11556
11556
  `Adding missing column ${tableName}.${req.name} via ALTER TABLE`
11557
11557
  );
@@ -13511,7 +13511,7 @@ function getDbPath(cwd) {
13511
13511
  return join9(getCleoDirAbsolute(cwd), DB_FILENAME2);
13512
13512
  }
13513
13513
  async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
13514
- const log10 = getLogger("sqlite");
13514
+ const log11 = getLogger("sqlite");
13515
13515
  try {
13516
13516
  const countResult = nativeDb.prepare("SELECT COUNT(*) as cnt FROM tasks").get();
13517
13517
  const taskCount = countResult?.cnt ?? 0;
@@ -13532,7 +13532,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
13532
13532
  if (backupTaskCount < MIN_BACKUP_TASK_COUNT) {
13533
13533
  return;
13534
13534
  }
13535
- log10.warn(
13535
+ log11.warn(
13536
13536
  { dbPath, backupPath: newestBackup.path, backupTasks: backupTaskCount },
13537
13537
  `Empty database detected with ${backupTaskCount}-task backup available. Auto-recovering from backup. This likely happened because git-tracked WAL/SHM files were overwritten during a branch switch (T5188).`
13538
13538
  );
@@ -13550,7 +13550,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
13550
13550
  const tempPath = dbPath + ".recovery-tmp";
13551
13551
  copyFileSync4(newestBackup.path, tempPath);
13552
13552
  renameSync(tempPath, dbPath);
13553
- log10.info(
13553
+ log11.info(
13554
13554
  { dbPath, backupPath: newestBackup.path, restoredTasks: backupTaskCount },
13555
13555
  "Database auto-recovered from backup successfully."
13556
13556
  );
@@ -13560,7 +13560,7 @@ async function autoRecoverFromBackup(nativeDb, dbPath, cwd) {
13560
13560
  runMigrations(restoredNativeDb, restoredDb);
13561
13561
  _db = restoredDb;
13562
13562
  } catch (err) {
13563
- log10.error({ err, dbPath }, "Auto-recovery from backup failed. Continuing with empty database.");
13563
+ log11.error({ err, dbPath }, "Auto-recovery from backup failed. Continuing with empty database.");
13564
13564
  }
13565
13565
  }
13566
13566
  async function getDb(cwd) {
@@ -13594,7 +13594,7 @@ async function getDb(cwd) {
13594
13594
  const { execFileSync: execFileSync12 } = await import("node:child_process");
13595
13595
  const gitCwd = resolve3(dbPath, "..", "..");
13596
13596
  const filesToCheck = [dbPath, dbPath + "-wal", dbPath + "-shm"];
13597
- const log10 = getLogger("sqlite");
13597
+ const log11 = getLogger("sqlite");
13598
13598
  for (const fileToCheck of filesToCheck) {
13599
13599
  try {
13600
13600
  execFileSync12("git", ["ls-files", "--error-unmatch", fileToCheck], {
@@ -13603,7 +13603,7 @@ async function getDb(cwd) {
13603
13603
  });
13604
13604
  const basename18 = fileToCheck.split(/[\\/]/).pop();
13605
13605
  const relPath = fileToCheck.replace(gitCwd + sep, "");
13606
- log10.warn(
13606
+ log11.warn(
13607
13607
  { path: fileToCheck },
13608
13608
  `${basename18} is tracked by project git \u2014 this risks data loss on branch switch. Resolution (ADR-013 \xA79): \`git rm --cached ${relPath}\` and rely on \`.cleo/backups/sqlite/\` snapshots + \`cleo backup add\` for recovery.`
13609
13609
  );
@@ -14589,11 +14589,18 @@ var init_cross_db_cleanup = __esm({
14589
14589
 
14590
14590
  // packages/core/src/store/db-helpers.ts
14591
14591
  import { eq as eq4, inArray as inArray2 } from "drizzle-orm";
14592
- async function upsertTask(db, row, archiveFields) {
14592
+ async function upsertTask(db, row, archiveFields, allowOrphanParent = false) {
14593
14593
  if (row.parentId) {
14594
14594
  const parent = await db.select({ id: tasks.id }).from(tasks).where(eq4(tasks.id, row.parentId)).limit(1).all();
14595
14595
  if (parent.length === 0) {
14596
- row = { ...row, parentId: null };
14596
+ if (allowOrphanParent) {
14597
+ row = { ...row, parentId: null };
14598
+ } else {
14599
+ log2.warn(
14600
+ { taskId: row.id, parentId: row.parentId },
14601
+ "upsertTask: parentId references a non-existent task \u2014 parent relationship may be lost"
14602
+ );
14603
+ }
14597
14604
  }
14598
14605
  }
14599
14606
  const values = archiveFields ? { ...row, ...archiveFields, status: "archived" } : row;
@@ -14737,10 +14744,13 @@ async function loadRelationsForTasks(db, tasks2) {
14737
14744
  }
14738
14745
  }
14739
14746
  }
14747
+ var log2;
14740
14748
  var init_db_helpers = __esm({
14741
14749
  "packages/core/src/store/db-helpers.ts"() {
14742
14750
  "use strict";
14751
+ init_logger();
14743
14752
  init_tasks_schema();
14753
+ log2 = getLogger("db-helpers");
14744
14754
  }
14745
14755
  });
14746
14756
 
@@ -15074,7 +15084,7 @@ async function createSqliteDataAccessor(cwd) {
15074
15084
  archiveReason: taskAny.archiveReason ?? "completed",
15075
15085
  cycleTimeDays: taskAny.cycleTimeDays ?? null
15076
15086
  };
15077
- await upsertTask(db, row, archiveFields);
15087
+ await upsertTask(db, row, archiveFields, true);
15078
15088
  depBatch.push({ taskId: task.id, deps: task.depends ?? [] });
15079
15089
  }
15080
15090
  await batchUpdateDependencies(db, depBatch, validDepIds);
@@ -16061,7 +16071,7 @@ async function ensureSequenceValid(cwd, options) {
16061
16071
  if (!options?.validateSequence) return;
16062
16072
  const check2 = await checkSequence(cwd);
16063
16073
  if (!check2.valid) {
16064
- log2.warn({ counter: check2.counter, maxId: check2.maxIdInData }, "Sequence behind, repairing");
16074
+ log3.warn({ counter: check2.counter, maxId: check2.maxIdInData }, "Sequence behind, repairing");
16065
16075
  const repair = await repairSequence(cwd);
16066
16076
  if (!repair.repaired && options.strict) {
16067
16077
  throw new DataSafetyError(`Sequence repair failed: ${repair.message}`, "SEQUENCE_INVALID", {
@@ -16078,7 +16088,7 @@ async function checkpoint(context, cwd, options) {
16078
16088
  stats.checkpoints++;
16079
16089
  stats.lastCheckpoint = /* @__PURE__ */ new Date();
16080
16090
  } catch (err) {
16081
- log2.warn({ err }, "Checkpoint failed (non-fatal)");
16091
+ log3.warn({ err }, "Checkpoint failed (non-fatal)");
16082
16092
  }
16083
16093
  vacuumIntoBackup({ cwd }).catch(() => {
16084
16094
  });
@@ -16140,7 +16150,7 @@ async function safeAppendLog(accessor, entry, cwd, options) {
16140
16150
  stats.writes++;
16141
16151
  await checkpoint("log entry", cwd, opts);
16142
16152
  }
16143
- var log2, DataSafetyError, DEFAULT_SAFETY, stats;
16153
+ var log3, DataSafetyError, DEFAULT_SAFETY, stats;
16144
16154
  var init_data_safety_central = __esm({
16145
16155
  "packages/core/src/store/data-safety-central.ts"() {
16146
16156
  "use strict";
@@ -16148,7 +16158,7 @@ var init_data_safety_central = __esm({
16148
16158
  init_sequence();
16149
16159
  init_git_checkpoint();
16150
16160
  init_sqlite_backup();
16151
- log2 = getLogger("data-safety");
16161
+ log3 = getLogger("data-safety");
16152
16162
  DataSafetyError = class extends Error {
16153
16163
  constructor(message, code, context) {
16154
16164
  super(message);
@@ -16188,7 +16198,7 @@ function isSafetyDisabled() {
16188
16198
  }
16189
16199
  function wrapWithSafety(accessor, cwd) {
16190
16200
  if (isSafetyDisabled()) {
16191
- log3.warn(
16201
+ log4.warn(
16192
16202
  "Safety disabled - emergency mode (CLEO_DISABLE_SAFETY=true). Data integrity checks bypassed."
16193
16203
  );
16194
16204
  return accessor;
@@ -16209,13 +16219,13 @@ function getSafetyStatus() {
16209
16219
  enabled: true
16210
16220
  };
16211
16221
  }
16212
- var log3, SafetyDataAccessor;
16222
+ var log4, SafetyDataAccessor;
16213
16223
  var init_safety_data_accessor = __esm({
16214
16224
  "packages/core/src/store/safety-data-accessor.ts"() {
16215
16225
  "use strict";
16216
16226
  init_logger();
16217
16227
  init_data_safety_central();
16218
- log3 = getLogger("data-safety");
16228
+ log4 = getLogger("data-safety");
16219
16229
  SafetyDataAccessor = class {
16220
16230
  /** The underlying accessor being wrapped. */
16221
16231
  inner;
@@ -16239,7 +16249,7 @@ var init_safety_data_accessor = __esm({
16239
16249
  ...config2
16240
16250
  };
16241
16251
  if (this.config.verbose) {
16242
- log3.debug({ engine: inner.engine }, "SafetyDataAccessor initialized");
16252
+ log4.debug({ engine: inner.engine }, "SafetyDataAccessor initialized");
16243
16253
  }
16244
16254
  }
16245
16255
  /** The storage engine backing this accessor. */
@@ -16251,7 +16261,7 @@ var init_safety_data_accessor = __esm({
16251
16261
  */
16252
16262
  logVerbose(message) {
16253
16263
  if (this.config.verbose) {
16254
- log3.debug(message);
16264
+ log4.debug(message);
16255
16265
  }
16256
16266
  }
16257
16267
  /**
@@ -20611,16 +20621,16 @@ async function queryAudit(options) {
20611
20621
  error: row.errorMessage ?? void 0
20612
20622
  }));
20613
20623
  } catch (err) {
20614
- log4.warn({ err }, "Failed to query audit entries from SQLite");
20624
+ log5.warn({ err }, "Failed to query audit entries from SQLite");
20615
20625
  return [];
20616
20626
  }
20617
20627
  }
20618
- var log4;
20628
+ var log5;
20619
20629
  var init_audit = __esm({
20620
20630
  "packages/core/src/audit.ts"() {
20621
20631
  "use strict";
20622
20632
  init_logger();
20623
- log4 = getLogger("audit");
20633
+ log5 = getLogger("audit");
20624
20634
  }
20625
20635
  });
20626
20636
 
@@ -52550,9 +52560,7 @@ async function completeTask(options, cwd, accessor) {
52550
52560
  const parent = await acc.loadSingleTask(task.parentId);
52551
52561
  if (parent && parent.type === "epic" && !parent.noAutoComplete) {
52552
52562
  const siblings = await acc.getChildren(parent.id);
52553
- const allDone = siblings.every(
52554
- (c) => c.id === task.id || c.status === "done" || c.status === "cancelled"
52555
- );
52563
+ const allDone = siblings.length > 0 && siblings.every((c) => c.id === task.id || c.status === "done" || c.status === "cancelled");
52556
52564
  if (allDone) {
52557
52565
  parent.status = "done";
52558
52566
  parent.completedAt = now;
@@ -59571,7 +59579,7 @@ init_logger();
59571
59579
  init_paths();
59572
59580
  init_tasks_schema();
59573
59581
  import { basename as basename6, relative as relative2 } from "node:path";
59574
- var log5 = getLogger("lifecycle:evidence");
59582
+ var log6 = getLogger("lifecycle:evidence");
59575
59583
  async function recordEvidence(epicId, stage, uri, type, options) {
59576
59584
  const now = (/* @__PURE__ */ new Date()).toISOString();
59577
59585
  const stageId = `stage-${epicId}-${stage}`;
@@ -59598,7 +59606,7 @@ async function recordEvidence(epicId, stage, uri, type, options) {
59598
59606
  description: options?.description ?? null
59599
59607
  }).run();
59600
59608
  } catch (err) {
59601
- log5.warn({ err }, "Failed to write evidence to SQLite");
59609
+ log6.warn({ err }, "Failed to write evidence to SQLite");
59602
59610
  }
59603
59611
  return record2;
59604
59612
  }
@@ -65897,7 +65905,7 @@ init_sqlite2();
65897
65905
  init_tasks_schema();
65898
65906
  import { randomUUID as randomUUID5 } from "node:crypto";
65899
65907
  import { and as and8, eq as eq11, sql as sql11 } from "drizzle-orm";
65900
- var log6 = getLogger("link-store");
65908
+ var log7 = getLogger("link-store");
65901
65909
  async function getLinksByProvider(providerId, cwd) {
65902
65910
  const db = await getDb(cwd);
65903
65911
  const rows = await db.select().from(externalTaskLinks).where(eq11(externalTaskLinks.providerId, providerId));
@@ -65952,7 +65960,7 @@ async function ensureExternalTaskLinksTable(cwd) {
65952
65960
  )
65953
65961
  );
65954
65962
  } catch (err) {
65955
- log6.warn({ err }, "Failed to ensure external_task_links table exists");
65963
+ log7.warn({ err }, "Failed to ensure external_task_links table exists");
65956
65964
  throw err;
65957
65965
  }
65958
65966
  }
@@ -66026,7 +66034,7 @@ init_brain_accessor();
66026
66034
  init_brain_sqlite();
66027
66035
  init_data_accessor();
66028
66036
  init_registry3();
66029
- var log7 = getLogger("nexus:transfer");
66037
+ var log8 = getLogger("nexus:transfer");
66030
66038
  async function previewTransfer(params) {
66031
66039
  return executeTransferInternal({ ...params, dryRun: true });
66032
66040
  }
@@ -66167,7 +66175,7 @@ async function executeTransferInternal(params) {
66167
66175
  }
66168
66176
  }
66169
66177
  } catch (err) {
66170
- log7.warn(
66178
+ log8.warn(
66171
66179
  { err, linksCreated },
66172
66180
  "Failed to create external_task_links during transfer \u2014 tasks were transferred successfully but provenance links could not be written"
66173
66181
  );
@@ -66195,7 +66203,7 @@ async function executeTransferInternal(params) {
66195
66203
  })
66196
66204
  });
66197
66205
  } catch (err) {
66198
- log7.warn({ err }, "nexus transfer audit write failed");
66206
+ log8.warn({ err }, "nexus transfer audit write failed");
66199
66207
  }
66200
66208
  if (mode === "move") {
66201
66209
  let archived = 0;
@@ -66208,7 +66216,7 @@ async function executeTransferInternal(params) {
66208
66216
  });
66209
66217
  archived++;
66210
66218
  } catch (err) {
66211
- log7.warn({ err, taskId: entry.sourceId }, "failed to archive source task after transfer");
66219
+ log8.warn({ err, taskId: entry.sourceId }, "failed to archive source task after transfer");
66212
66220
  }
66213
66221
  }
66214
66222
  }
@@ -66246,7 +66254,7 @@ async function executeTransferInternal(params) {
66246
66254
  }
66247
66255
  }
66248
66256
  } catch (err) {
66249
- log7.warn({ err }, "brain observation transfer failed");
66257
+ log8.warn({ err }, "brain observation transfer failed");
66250
66258
  }
66251
66259
  result.brainObservationsTransferred = brainTransferred;
66252
66260
  result.manifest.brainObservationsTransferred = brainTransferred;
@@ -66294,8 +66302,8 @@ async function loadProjectACL(projectPath) {
66294
66302
  async function logAclFailure(projectPath) {
66295
66303
  try {
66296
66304
  const { getLogger: getLogger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
66297
- const log10 = getLogger2("nexus.acl");
66298
- log10.warn({ projectPath }, "Failed to load ACL configuration, defaulting to deny-all");
66305
+ const log11 = getLogger2("nexus.acl");
66306
+ log11.warn({ projectPath }, "Failed to load ACL configuration, defaulting to deny-all");
66299
66307
  } catch {
66300
66308
  }
66301
66309
  }
@@ -66450,9 +66458,9 @@ async function executeOperation(operation, taskId, projectPath, accessor, direct
66450
66458
  async function logRouteAudit(directive, projectName, taskId, operation, success2, error48) {
66451
66459
  try {
66452
66460
  const { getLogger: getLogger2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
66453
- const log10 = getLogger2("nexus.route");
66461
+ const log11 = getLogger2("nexus.route");
66454
66462
  const level = success2 ? "info" : "warn";
66455
- log10[level](
66463
+ log11[level](
66456
66464
  {
66457
66465
  directive: directive.verb,
66458
66466
  agentId: directive.agentId,
@@ -75028,7 +75036,7 @@ init_data_accessor();
75028
75036
 
75029
75037
  // packages/core/src/stats/workflow-telemetry.ts
75030
75038
  init_logger();
75031
- var log8 = getLogger("workflow-telemetry");
75039
+ var log9 = getLogger("workflow-telemetry");
75032
75040
  async function queryTasks(cwd, since) {
75033
75041
  try {
75034
75042
  const { getDb: getDb3 } = await Promise.resolve().then(() => (init_sqlite2(), sqlite_exports));
@@ -75050,7 +75058,7 @@ async function queryTasks(cwd, since) {
75050
75058
  }).from(tasks2).where(conditions.length > 0 ? and10(...conditions) : void 0).all();
75051
75059
  return rows;
75052
75060
  } catch (err) {
75053
- log8.warn({ err }, "Failed to query tasks for workflow telemetry");
75061
+ log9.warn({ err }, "Failed to query tasks for workflow telemetry");
75054
75062
  return [];
75055
75063
  }
75056
75064
  }
@@ -75084,7 +75092,7 @@ async function queryCompletionAuditRows(cwd, since) {
75084
75092
  return isComplete;
75085
75093
  });
75086
75094
  } catch (err) {
75087
- log8.warn({ err }, "Failed to query audit log for workflow telemetry");
75095
+ log9.warn({ err }, "Failed to query audit log for workflow telemetry");
75088
75096
  return [];
75089
75097
  }
75090
75098
  }
@@ -76540,11 +76548,11 @@ import { join as join87 } from "node:path";
76540
76548
  import { Readable } from "node:stream";
76541
76549
  import { pipeline } from "node:stream/promises";
76542
76550
  import { createGzip } from "node:zlib";
76543
- var log9 = getLogger("prune");
76551
+ var log10 = getLogger("prune");
76544
76552
  async function pruneAuditLog(cleoDir, config2) {
76545
76553
  try {
76546
76554
  if (!config2.auditRetentionDays || config2.auditRetentionDays <= 0) {
76547
- log9.debug("auditRetentionDays is 0 or unset; skipping audit prune");
76555
+ log10.debug("auditRetentionDays is 0 or unset; skipping audit prune");
76548
76556
  return { rowsArchived: 0, rowsDeleted: 0 };
76549
76557
  }
76550
76558
  const cutoff = new Date(Date.now() - config2.auditRetentionDays * 864e5).toISOString();
@@ -76555,7 +76563,7 @@ async function pruneAuditLog(cleoDir, config2) {
76555
76563
  const db = await getDb3(projectRoot);
76556
76564
  const oldRows = await db.select().from(auditLog2).where(lt3(auditLog2.timestamp, cutoff));
76557
76565
  if (oldRows.length === 0) {
76558
- log9.debug("No audit_log rows older than cutoff; nothing to prune");
76566
+ log10.debug("No audit_log rows older than cutoff; nothing to prune");
76559
76567
  return { rowsArchived: 0, rowsDeleted: 0 };
76560
76568
  }
76561
76569
  let archivePath;
@@ -76573,17 +76581,17 @@ async function pruneAuditLog(cleoDir, config2) {
76573
76581
  const inStream = Readable.from([jsonlContent]);
76574
76582
  await pipeline(inStream, gzip, outStream);
76575
76583
  rowsArchived = oldRows.length;
76576
- log9.info(
76584
+ log10.info(
76577
76585
  { archivePath, rowsArchived },
76578
76586
  `Archived ${rowsArchived} audit rows to ${archivePath}`
76579
76587
  );
76580
76588
  } catch (archiveErr) {
76581
- log9.warn({ err: archiveErr }, "Failed to archive audit rows; continuing with deletion");
76589
+ log10.warn({ err: archiveErr }, "Failed to archive audit rows; continuing with deletion");
76582
76590
  archivePath = void 0;
76583
76591
  }
76584
76592
  }
76585
76593
  await db.delete(auditLog2).where(lt3(auditLog2.timestamp, cutoff)).run();
76586
- log9.info(
76594
+ log10.info(
76587
76595
  { rowsDeleted: oldRows.length, cutoff },
76588
76596
  `Pruned ${oldRows.length} audit_log rows older than ${cutoff}`
76589
76597
  );
@@ -76593,7 +76601,7 @@ async function pruneAuditLog(cleoDir, config2) {
76593
76601
  archivePath
76594
76602
  };
76595
76603
  } catch (err) {
76596
- log9.warn({ err }, "audit log pruning failed");
76604
+ log10.warn({ err }, "audit log pruning failed");
76597
76605
  return { rowsArchived: 0, rowsDeleted: 0 };
76598
76606
  }
76599
76607
  }