@vortex-os/base 0.9.0 → 0.11.0

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
@@ -1,3 +1,22 @@
1
+ import {
2
+ SESSION_END_COMMAND,
3
+ SESSION_START_COMMAND,
4
+ collectStatuslineProbes,
5
+ effortMeter,
6
+ ensureStatusline,
7
+ ensureVortexHooks,
8
+ formatTokens,
9
+ formatWindow,
10
+ makeBar,
11
+ parseSettings,
12
+ parseStatuslineInput,
13
+ renderStatusline,
14
+ runStatuslineCli,
15
+ safeSegment,
16
+ serializeSettings,
17
+ sniffEffortFromTranscript,
18
+ statuslineCommand
19
+ } from "./chunk-DWANI3LV.js";
1
20
  import {
2
21
  catchUpSessions
3
22
  } from "./chunk-3L5DLEGP.js";
@@ -105,7 +124,7 @@ function moduleDir(ctx, moduleName) {
105
124
  import { existsSync, readFileSync } from "fs";
106
125
  import { join as join2 } from "path";
107
126
  var DEFAULT_CONFIG = {
108
- autoRecord: { sessionStart: true, worklog: true, decision: true, ambientRecall: true, archive: true, vectorize: true, vectorizeAutoDownload: true, commitFrameworkChanges: true, handoff: true, handoffRetentionDays: 7 },
127
+ autoRecord: { sessionStart: true, worklog: true, decision: true, ambientRecall: true, archive: true, vectorize: true, vectorizeAutoDownload: true, commitFrameworkChanges: true, handoff: true, handoffRetentionDays: 7, reindex: true, backfill: true },
109
128
  updates: { check: "session" },
110
129
  environments: []
111
130
  };
@@ -149,6 +168,8 @@ function loadVortexConfig(ctx) {
149
168
  const vectorizeAutoDownload = rawAuto.vectorizeAutoDownload === void 0 ? true : rawAuto.vectorizeAutoDownload === true;
150
169
  const commitFrameworkChanges = rawAuto.commitFrameworkChanges === void 0 ? true : rawAuto.commitFrameworkChanges === true;
151
170
  const handoff = rawAuto.handoff === void 0 ? true : rawAuto.handoff === true;
171
+ const reindex = rawAuto.reindex === void 0 ? true : rawAuto.reindex === true;
172
+ const backfill = rawAuto.backfill === void 0 ? true : rawAuto.backfill === true;
152
173
  const rawDays = rawAuto.handoffRetentionDays;
153
174
  const handoffRetentionDays = typeof rawDays === "number" && Number.isFinite(rawDays) && rawDays > 0 ? Math.floor(rawDays) : DEFAULT_CONFIG.autoRecord.handoffRetentionDays;
154
175
  return {
@@ -158,7 +179,9 @@ function loadVortexConfig(ctx) {
158
179
  vectorizeAutoDownload,
159
180
  commitFrameworkChanges,
160
181
  handoff,
161
- handoffRetentionDays
182
+ handoffRetentionDays,
183
+ reindex,
184
+ backfill
162
185
  },
163
186
  updates: { check },
164
187
  environments
@@ -4235,6 +4258,7 @@ var ClaudeDesktopLLMJudge = class extends InjectedLLMJudge {
4235
4258
  // ../plugins/session-rituals/dist/index.js
4236
4259
  var dist_exports14 = {};
4237
4260
  __export(dist_exports14, {
4261
+ DEFAULT_GAP_WINDOW_DAYS: () => DEFAULT_GAP_WINDOW_DAYS,
4238
4262
  HANDOFF_ARCHIVE_DIR: () => HANDOFF_ARCHIVE_DIR,
4239
4263
  HANDOFF_DIR: () => HANDOFF_DIR,
4240
4264
  OWNERSHIP_SCHEMA: () => OWNERSHIP_SCHEMA,
@@ -4244,6 +4268,7 @@ __export(dist_exports14, {
4244
4268
  aggregateHandoff: () => aggregateHandoff,
4245
4269
  applyGlobalSetup: () => applyGlobalSetup,
4246
4270
  argvToSlash: () => argvToSlash,
4271
+ autoReindexMemory: () => autoReindexMemory,
4247
4272
  buildInstallCommand: () => buildInstallCommand,
4248
4273
  buildOwnershipManifest: () => buildOwnershipManifest,
4249
4274
  buildRegistry: () => buildRegistry,
@@ -4252,6 +4277,7 @@ __export(dist_exports14, {
4252
4277
  collectAgenda: () => collectAgenda,
4253
4278
  collectCarryover: () => collectCarryover,
4254
4279
  collectSessionStartReport: () => collectSessionStartReport,
4280
+ collectStatuslineProbes: () => collectStatuslineProbes,
4255
4281
  compareSemver: () => compareSemver,
4256
4282
  computeCurateFingerprint: () => computeCurateFingerprint,
4257
4283
  countUncommitted: () => countUncommitted,
@@ -4262,10 +4288,15 @@ __export(dist_exports14, {
4262
4288
  decisionCommand: () => decisionCommand,
4263
4289
  detectInterruptedGitOp: () => detectInterruptedGitOp,
4264
4290
  detectWorklogGaps: () => detectWorklogGaps,
4291
+ effortMeter: () => effortMeter,
4292
+ ensureStatusline: () => ensureStatusline,
4265
4293
  ensureVortexHooks: () => ensureVortexHooks,
4266
4294
  ensureWorklogEntry: () => ensureWorklogEntry,
4267
4295
  extractNextUp: () => extractNextUp,
4268
4296
  extractOpenTasks: () => extractOpenTasks,
4297
+ formatTokens: () => formatTokens,
4298
+ formatWindow: () => formatWindow,
4299
+ gapWindowSinceArg: () => gapWindowSinceArg,
4269
4300
  globalMemoryPath: () => globalMemoryPath,
4270
4301
  globalSettingsHasHook: () => globalSettingsHasHook,
4271
4302
  globalSettingsPath: () => globalSettingsPath,
@@ -4277,9 +4308,11 @@ __export(dist_exports14, {
4277
4308
  isNewer: () => isNewer,
4278
4309
  isStableUpdate: () => isStableUpdate,
4279
4310
  logCommand: () => logCommand,
4311
+ makeBar: () => makeBar,
4280
4312
  ownershipManifestPath: () => ownershipManifestPath,
4281
4313
  parseAdoptArgs: () => parseAdoptArgs,
4282
4314
  parseSettings: () => parseSettings,
4315
+ parseStatuslineInput: () => parseStatuslineInput,
4283
4316
  pruneHandoffs: () => pruneHandoffs,
4284
4317
  queryNpmLatest: () => queryNpmLatest,
4285
4318
  readGlobalInstancePointer: () => readGlobalInstancePointer,
@@ -4290,17 +4323,22 @@ __export(dist_exports14, {
4290
4323
  renderAgenda: () => renderAgenda,
4291
4324
  renderGlobalBlock: () => renderGlobalBlock,
4292
4325
  renderSessionStartReport: () => renderSessionStartReport,
4326
+ renderStatusline: () => renderStatusline,
4293
4327
  repairOwnershipManifest: () => repairOwnershipManifest,
4294
4328
  resolveRepoRoot: () => resolveRepoRoot,
4295
4329
  runCurateAccept: () => runCurateAccept,
4296
4330
  runCurateCandidates: () => runCurateCandidates,
4297
4331
  runCurateDecline: () => runCurateDecline,
4298
4332
  runCuratePreview: () => runCuratePreview,
4333
+ runStatuslineCli: () => runStatuslineCli,
4299
4334
  runTemplatesUpdate: () => runTemplatesUpdate,
4300
4335
  runVortexCli: () => runVortexCli,
4336
+ safeSegment: () => safeSegment,
4301
4337
  scanHandoffs: () => scanHandoffs,
4302
4338
  serializeSettings: () => serializeSettings,
4303
4339
  sessionStartCommand: () => sessionStartCommand,
4340
+ sniffEffortFromTranscript: () => sniffEffortFromTranscript,
4341
+ statuslineCommand: () => statuslineCommand,
4304
4342
  templateDestRelPath: () => templateDestRelPath,
4305
4343
  upsertGlobalBlock: () => upsertGlobalBlock,
4306
4344
  validateCuratePayload: () => validateCuratePayload,
@@ -4552,7 +4590,7 @@ function todayIso() {
4552
4590
 
4553
4591
  // ../plugins/session-rituals/dist/commands/reindex.js
4554
4592
  import { existsSync as existsSync7 } from "fs";
4555
- import { readFile as readFile17, writeFile as writeFile9 } from "fs/promises";
4593
+ import { readFile as readFile17, writeFile as writeFile9, utimes } from "fs/promises";
4556
4594
  import { join as join21 } from "path";
4557
4595
  var TARGETS = [
4558
4596
  {
@@ -4706,6 +4744,52 @@ var reindexCommand = {
4706
4744
  return results;
4707
4745
  }
4708
4746
  };
4747
+ async function autoReindexMemory(ctx) {
4748
+ try {
4749
+ const target = TARGETS.find((t) => t.dir === "_memory");
4750
+ if (!target)
4751
+ return "missing";
4752
+ const dir = join21(ctx.dataDir, target.dir);
4753
+ if (!existsSync7(dir))
4754
+ return "missing";
4755
+ const entries = await scanDirectory(dir, {
4756
+ recursive: target.recursive,
4757
+ skipPrefixes: target.skipPrefixes,
4758
+ skipFilenames: target.skipFilenames
4759
+ });
4760
+ const body = renderIndex({
4761
+ title: target.title,
4762
+ description: target.description,
4763
+ entries,
4764
+ privacy: target.privacy
4765
+ });
4766
+ const indexPath = join21(dir, "_INDEX.md");
4767
+ let existing;
4768
+ try {
4769
+ existing = await readFile17(indexPath, "utf8");
4770
+ } catch {
4771
+ existing = void 0;
4772
+ }
4773
+ const sameListing = existing !== void 0 && stripIndexDate(existing) === stripIndexDate(body);
4774
+ let status;
4775
+ if (sameListing) {
4776
+ status = "unchanged";
4777
+ } else {
4778
+ await writeFile9(indexPath, body, "utf8");
4779
+ status = "written";
4780
+ }
4781
+ if (existsSync7(indexPath)) {
4782
+ const now = /* @__PURE__ */ new Date();
4783
+ await utimes(indexPath, now, now);
4784
+ }
4785
+ return status;
4786
+ } catch {
4787
+ return "error";
4788
+ }
4789
+ }
4790
+ function stripIndexDate(body) {
4791
+ return body.replace(/^updated: .*$/m, "updated:");
4792
+ }
4709
4793
 
4710
4794
  // ../plugins/session-rituals/dist/commands/session-start.js
4711
4795
  import { existsSync as existsSync8 } from "fs";
@@ -5156,84 +5240,6 @@ import { copyFile as copyFile2, mkdir as mkdir9, readdir as readdir16, readFile
5156
5240
  import { basename as basename7, dirname as dirname5, extname as extname11, join as join26, relative as relative5 } from "path";
5157
5241
  import { fileURLToPath } from "url";
5158
5242
 
5159
- // ../plugins/session-rituals/dist/ensure-hooks.js
5160
- var SESSION_START_COMMAND = "npx --no-install vortex session-start || exit 0";
5161
- var SESSION_END_COMMAND = "npx --no-install vortex session-end || exit 0";
5162
- var LEGACY_COMMANDS = {
5163
- SessionStart: [
5164
- "npx --no-install -p @vortex-os/base vortex session-start || exit 0",
5165
- "npx --no-install -p @vortex-os/base vortex session-start"
5166
- ],
5167
- SessionEnd: [
5168
- "npx --no-install -p @vortex-os/base vortex session-end || exit 0",
5169
- "npx --no-install -p @vortex-os/base vortex session-end"
5170
- ]
5171
- };
5172
- function parseSettings(text) {
5173
- const trimmed = (text ?? "").trim();
5174
- if (trimmed.length === 0)
5175
- return {};
5176
- let parsed;
5177
- try {
5178
- parsed = JSON.parse(trimmed);
5179
- } catch (e) {
5180
- throw new Error(`.claude/settings.json is not valid JSON \u2014 refusing to overwrite. Fix or remove it first. (${e.message})`);
5181
- }
5182
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
5183
- throw new Error(".claude/settings.json is not a JSON object \u2014 refusing to overwrite.");
5184
- }
5185
- return parsed;
5186
- }
5187
- function ensureVortexHooks(existing) {
5188
- const base = existing && typeof existing === "object" ? existing : {};
5189
- const hooks = { ...base.hooks ?? {} };
5190
- const added = [];
5191
- const wire = (event, command) => {
5192
- const legacy = LEGACY_COMMANDS[event];
5193
- const src = hooks[event] ?? [];
5194
- let changed = false;
5195
- let kept = false;
5196
- const groups = [];
5197
- for (const g of src) {
5198
- const hookList = [];
5199
- for (const h of g.hooks ?? []) {
5200
- const migrated = legacy.includes(h.command);
5201
- const cmd = migrated ? command : h.command;
5202
- if (cmd === command) {
5203
- if (kept) {
5204
- changed = true;
5205
- continue;
5206
- }
5207
- kept = true;
5208
- if (migrated)
5209
- changed = true;
5210
- hookList.push(migrated ? { ...h, command } : h);
5211
- } else {
5212
- hookList.push(h);
5213
- }
5214
- }
5215
- if (hookList.length > 0)
5216
- groups.push({ ...g, hooks: hookList });
5217
- else
5218
- changed = true;
5219
- }
5220
- if (!kept) {
5221
- groups.push({ hooks: [{ type: "command", command }] });
5222
- changed = true;
5223
- }
5224
- hooks[event] = groups;
5225
- if (changed)
5226
- added.push(event);
5227
- };
5228
- wire("SessionStart", SESSION_START_COMMAND);
5229
- wire("SessionEnd", SESSION_END_COMMAND);
5230
- const settings = { ...base, hooks };
5231
- return { settings, added, alreadyWired: added.length === 0 };
5232
- }
5233
- function serializeSettings(settings) {
5234
- return JSON.stringify(settings, null, 2) + "\n";
5235
- }
5236
-
5237
5243
  // ../plugins/session-rituals/dist/global-setup.js
5238
5244
  import { homedir } from "os";
5239
5245
  import { existsSync as existsSync10, readFileSync as readFileSync2 } from "fs";
@@ -7813,7 +7819,7 @@ import { execFileSync as execFileSync2, spawn as spawn2 } from "child_process";
7813
7819
  import { existsSync as existsSync16, readFileSync as readFileSync4, mkdirSync, openSync, writeSync, closeSync, linkSync, rmSync, statSync } from "fs";
7814
7820
  import { createRequire } from "module";
7815
7821
  import { hostname } from "os";
7816
- import { isAbsolute as isAbsolute5, join as join31 } from "path";
7822
+ import { isAbsolute as isAbsolute5, join as join30 } from "path";
7817
7823
 
7818
7824
  // ../plugins/session-rituals/dist/update-check.js
7819
7825
  import { execSync } from "child_process";
@@ -7931,6 +7937,9 @@ import { readdir as readdir17, readFile as readFile22, stat as stat9 } from "fs/
7931
7937
  import { join as join28 } from "path";
7932
7938
  var COUNTED_DIRS2 = ["_memory", "worklog", "decision-log"];
7933
7939
  var DEFAULT_GAP_WINDOW_DAYS = 30;
7940
+ function gapWindowSinceArg() {
7941
+ return `${DEFAULT_GAP_WINDOW_DAYS} days ago`;
7942
+ }
7934
7943
  var BOOT_BANNER = String.raw`
7935
7944
  __ __ _ _____ __
7936
7945
  \ \ / ___ _ _| |_| __\ \/ /
@@ -8131,7 +8140,7 @@ function renderSessionStartReport(report, extras) {
8131
8140
  lines.push(`- always-on rules (loaded below): ${slugs}${over}`);
8132
8141
  }
8133
8142
  if (report.memoryIndexStale) {
8134
- lines.push("- \u26A0\uFE0F memory index may be stale \u2014 run `npx vortex reindex _memory`");
8143
+ lines.push("- \u2139\uFE0F memory index is stale (auto-reindex off or failed) \u2014 recent memories may be missing from the index.");
8135
8144
  }
8136
8145
  const handoffs = report.handoffs ?? [];
8137
8146
  const nextUp = report.nextUp ?? [];
@@ -8171,14 +8180,14 @@ function renderSessionStartReport(report, extras) {
8171
8180
  }
8172
8181
  const gaps = extras?.missingWorklogDays ?? [];
8173
8182
  if (gaps.length) {
8174
- lines.push(`- \u26A0\uFE0F work without a worklog: ${gaps.join(", ")} \u2014 backfill from that day's commits`);
8183
+ lines.push(`- \u21A9\uFE0F no worklog yet for: ${gaps.join(", ")} \u2014 backfill from that day's session archive or commits.`);
8175
8184
  }
8176
8185
  const carry = extras?.carryover;
8177
8186
  if (carry?.interrupted) {
8178
8187
  lines.push(carry.interrupted === "index.lock" ? `- \u26A0\uFE0F a git lock (\`index.lock\`) is present \u2014 another git process may be running, or it is stale from a crash; remove it if nothing is using git. \`/resume\` shows what stopped.` : `- \u26A0\uFE0F interrupted git op (\`${carry.interrupted}\`) \u2014 likely a crashed prior session; finish or abort it before new work. Run \`/resume\` to see what stopped.`);
8179
8188
  }
8180
8189
  if (carry && carry.uncommitted > 0) {
8181
- lines.push(`- \u21A9\uFE0F ${carry.uncommitted} uncommitted change(s) carried over from a prior session \u2014 run \`/resume\` if you're unsure they were meant to stay.`);
8190
+ lines.push(`- \u21A9\uFE0F ${carry.uncommitted} uncommitted change(s) carried over from a prior session \u2014 likely normal work in progress.`);
8182
8191
  }
8183
8192
  const cu = extras?.catchUp;
8184
8193
  if (cu && (cu.ingestedLocal > 0 || cu.indexedPulled > 0 || cu.errors > 0)) {
@@ -8379,56 +8388,11 @@ function isoDate2(d2) {
8379
8388
  return `${y2}-${m2}-${day}`;
8380
8389
  }
8381
8390
 
8382
- // ../plugins/session-rituals/dist/worklog-write.js
8383
- import { mkdir as mkdir10, writeFile as writeFile12 } from "fs/promises";
8384
- import { dirname as dirname6, join as join29 } from "path";
8385
- async function ensureWorklogEntry(ctx, opts) {
8386
- const now = opts?.now ?? /* @__PURE__ */ new Date();
8387
- const date = isoDate3(now);
8388
- const time = isoTime2(now);
8389
- const keyword = (opts?.keyword ?? "worklog").trim() || "worklog";
8390
- const store = new WorklogStore(join29(ctx.dataDir, "worklog"));
8391
- const existing = await store.get(date);
8392
- if (existing) {
8393
- return { path: existing.path, date: existing.date, keyword: existing.keyword, created: false };
8394
- }
8395
- const path = store.pathFor(date, keyword, time);
8396
- const title = opts?.title ?? `${date} worklog`;
8397
- await mkdir10(dirname6(path), { recursive: true });
8398
- await writeFile12(path, renderWorklogFile(date, title, opts?.body ?? ""), "utf8");
8399
- return { path, date, keyword, created: true };
8400
- }
8401
- function renderWorklogFile(date, title, body) {
8402
- const trimmed = body.trimEnd();
8403
- return `---
8404
- type: worklog
8405
- created: ${date}
8406
- updated: ${date}
8407
- tags: [worklog]
8408
- ---
8409
-
8410
- # ${title}
8411
- ` + (trimmed ? `
8412
- ${trimmed}
8413
- ` : ``);
8414
- }
8415
- function isoDate3(d2) {
8416
- const y2 = d2.getFullYear();
8417
- const m2 = String(d2.getMonth() + 1).padStart(2, "0");
8418
- const day = String(d2.getDate()).padStart(2, "0");
8419
- return `${y2}-${m2}-${day}`;
8420
- }
8421
- function isoTime2(d2) {
8422
- const h = String(d2.getHours()).padStart(2, "0");
8423
- const m2 = String(d2.getMinutes()).padStart(2, "0");
8424
- return `${h}${m2}`;
8425
- }
8426
-
8427
8391
  // ../plugins/session-rituals/dist/curate-cli.js
8428
8392
  import { existsSync as existsSync15 } from "fs";
8429
8393
  import { createHash as createHash3 } from "crypto";
8430
8394
  import { readFile as readFile23, readdir as readdir18 } from "fs/promises";
8431
- import { join as join30 } from "path";
8395
+ import { join as join29 } from "path";
8432
8396
  var SYSTEM_META_DIRS3 = /* @__PURE__ */ new Set([
8433
8397
  "worklog",
8434
8398
  "decision-log",
@@ -8508,7 +8472,7 @@ function joinRel(...parts) {
8508
8472
  }
8509
8473
  async function runCurateCandidates(repoRoot, options) {
8510
8474
  const maxEntries = options?.maxEntries ?? 200;
8511
- const dataDir = join30(repoRoot, "data");
8475
+ const dataDir = join29(repoRoot, "data");
8512
8476
  const candidates = [];
8513
8477
  let truncated = false;
8514
8478
  if (existsSync15(dataDir)) {
@@ -8534,7 +8498,7 @@ async function runCurateCandidates(repoRoot, options) {
8534
8498
  continue;
8535
8499
  if (atRoot && (SYSTEM_META_DIRS3.has(e.name) || e.name.startsWith("_")))
8536
8500
  continue;
8537
- await visit(join30(absDir, e.name), joinRel(relDir, e.name));
8501
+ await visit(join29(absDir, e.name), joinRel(relDir, e.name));
8538
8502
  } else if (e.isFile() && e.name.endsWith(".md")) {
8539
8503
  if (NON_DOC_FILES.has(e.name))
8540
8504
  continue;
@@ -8543,7 +8507,7 @@ async function runCurateCandidates(repoRoot, options) {
8543
8507
  let topic = null;
8544
8508
  let tags = [];
8545
8509
  try {
8546
- const raw = await readFile23(join30(absDir, e.name), "utf8");
8510
+ const raw = await readFile23(join29(absDir, e.name), "utf8");
8547
8511
  const parsed = parseFrontmatter(raw);
8548
8512
  if (typeof parsed.frontmatter.topic === "string") {
8549
8513
  topic = parsed.frontmatter.topic.trim().toLowerCase();
@@ -8581,7 +8545,7 @@ async function runCuratePreview(repoRoot, payload, now = /* @__PURE__ */ new Dat
8581
8545
  };
8582
8546
  }
8583
8547
  try {
8584
- validateDataRelativePath(join30(repoRoot, "data"), v2.effectiveRelPath);
8548
+ validateDataRelativePath(join29(repoRoot, "data"), v2.effectiveRelPath);
8585
8549
  } catch (e) {
8586
8550
  return {
8587
8551
  subcommand: "curate-preview",
@@ -8598,10 +8562,10 @@ async function runCuratePreview(repoRoot, payload, now = /* @__PURE__ */ new Dat
8598
8562
  let targetExists;
8599
8563
  let wouldDo;
8600
8564
  if (payload.action === "create-file") {
8601
- targetExists = existsSync15(join30(repoRoot, "data", v2.effectiveRelPath));
8565
+ targetExists = existsSync15(join29(repoRoot, "data", v2.effectiveRelPath));
8602
8566
  wouldDo = targetExists ? `create-file at ${v2.effectiveRelPath} \u2014 but the file already EXISTS, so accept would REFUSE (no overwrite).` : `create a new document at data/${v2.effectiveRelPath}.`;
8603
8567
  } else {
8604
- targetExists = existsSync15(join30(repoRoot, "data", v2.effectiveRelPath));
8568
+ targetExists = existsSync15(join29(repoRoot, "data", v2.effectiveRelPath));
8605
8569
  wouldDo = targetExists ? `append a "## ${payload.sectionHeader}" section to data/${v2.effectiveRelPath}.` : `append-section to data/${v2.effectiveRelPath} \u2014 but the file does NOT exist, so accept would FAIL (append-section never creates).`;
8606
8570
  }
8607
8571
  const nextActions = [];
@@ -8774,8 +8738,13 @@ function readCuratePayload(args) {
8774
8738
  async function runVortexCli(argv, io) {
8775
8739
  const out = io?.stdout ?? ((s) => process.stdout.write(s));
8776
8740
  const err = io?.stderr ?? ((s) => process.stderr.write(s));
8777
- const repoRoot = resolveRepoRoot();
8778
8741
  try {
8742
+ if (argv[0] === "statusline") {
8743
+ const { runStatuslineCli: runStatuslineCli2 } = await import("./statusline-NQKJ3NWD.js");
8744
+ const statuslineRoot = process.env.VORTEX_REPO_ROOT?.trim() || process.cwd();
8745
+ return runStatuslineCli2(argv.slice(1), statuslineRoot, out, err);
8746
+ }
8747
+ const repoRoot = resolveRepoRoot();
8779
8748
  if (argv[0] === "session-start") {
8780
8749
  await runSessionStart(repoRoot, out);
8781
8750
  return 0;
@@ -8812,8 +8781,9 @@ async function runVortexCli(argv, io) {
8812
8781
  Commands:
8813
8782
  ${names}
8814
8783
  session-start \u2014 emit the start-of-session boot report (git pull + data counts + catch-up)
8815
- session-end \u2014 worklog safety net (create today's worklog if work happened and none exists)
8784
+ session-end \u2014 no-op (kept for hook compatibility; worklog gap handling is at session-start)
8816
8785
  check-updates \u2014 check the npm registry for a newer @vortex-os/base (read-only; prints the exact update command)
8786
+ statusline \u2014 render the Claude Code status bar from stdin JSON (\`lite\` for 1-line; \`install [--lite]\` wires .claude/settings.json)
8817
8787
 
8818
8788
  Instance shortcuts (also available as \`/vortex <sub>\`):
8819
8789
  init \u2014 first-time setup: routers + data/ + hooks + slash-commands
@@ -8880,7 +8850,7 @@ function memoryExtendedPresent() {
8880
8850
  }
8881
8851
  var VECTORIZE_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
8882
8852
  function vectorizeLockPath(ctx) {
8883
- return join31(ctx.dataDir, "_indexes", ".vectorize.lock");
8853
+ return join30(ctx.dataDir, "_indexes", ".vectorize.lock");
8884
8854
  }
8885
8855
  function vectorizeSetupInProgress(ctx) {
8886
8856
  const lock = vectorizeLockPath(ctx);
@@ -8906,8 +8876,8 @@ function spawnVectorizeSetup(repoRoot) {
8906
8876
  }
8907
8877
  async function runVectorizeSetup(repoRoot, out, err) {
8908
8878
  const ctx = makeContext(repoRoot);
8909
- const indexDir = join31(ctx.dataDir, "_indexes");
8910
- const finalDb = join31(indexDir, "memory.sqlite");
8879
+ const indexDir = join30(ctx.dataDir, "_indexes");
8880
+ const finalDb = join30(indexDir, "memory.sqlite");
8911
8881
  if (existsSync16(finalDb)) {
8912
8882
  out("recall index already present \u2014 nothing to do\n");
8913
8883
  return;
@@ -8939,7 +8909,7 @@ async function runVectorizeSetup(repoRoot, out, err) {
8939
8909
  return;
8940
8910
  }
8941
8911
  }
8942
- const tmpDb = join31(indexDir, `memory.sqlite.building-${process.pid}`);
8912
+ const tmpDb = join30(indexDir, `memory.sqlite.building-${process.pid}`);
8943
8913
  const tmpSidecars = [tmpDb + "-wal", tmpDb + "-shm", tmpDb + "-journal"];
8944
8914
  const cleanTmp = () => {
8945
8915
  rmSync(tmpDb, { force: true });
@@ -9028,13 +8998,18 @@ async function runSessionStart(repoRoot, out) {
9028
8998
  }
9029
8999
  const bookkeepingPrefix = frameworkBookkeepingPrefix(ctx);
9030
9000
  const carryover = collectCarryover(repoRoot, (p) => p.startsWith(bookkeepingPrefix));
9001
+ if (config.autoRecord.reindex && !git2?.conflict) {
9002
+ await autoReindexMemory(ctx);
9003
+ }
9031
9004
  const report = await collectSessionStartReport(ctx, { environment });
9032
9005
  let missingWorklogDays = [];
9033
- try {
9034
- const log = gitOut(repoRoot, ["log", "--since=7 days ago", "--pretty=%cd", "--date=short"]);
9035
- const commitDays = log.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
9036
- missingWorklogDays = detectWorklogGaps(commitDays, report.recentWorklogDates);
9037
- } catch {
9006
+ if (config.autoRecord.worklog && config.autoRecord.backfill && !git2?.conflict) {
9007
+ try {
9008
+ const log = gitOut(repoRoot, ["log", `--since=${gapWindowSinceArg()}`, "--pretty=%cd", "--date=short"]);
9009
+ const commitDays = log.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
9010
+ missingWorklogDays = detectWorklogGaps(commitDays, report.recentWorklogDates);
9011
+ } catch {
9012
+ }
9038
9013
  }
9039
9014
  let catchUp = null;
9040
9015
  if (config.autoRecord.archive) {
@@ -9057,7 +9032,7 @@ async function runSessionStart(repoRoot, out) {
9057
9032
  let vectorized = null;
9058
9033
  let vectorizeSetupStarted = false;
9059
9034
  if (config.autoRecord.vectorize) {
9060
- const dbExists = existsSync16(join31(ctx.dataDir, "_indexes", "memory.sqlite"));
9035
+ const dbExists = existsSync16(join30(ctx.dataDir, "_indexes", "memory.sqlite"));
9061
9036
  const action = decideVectorizeAction({
9062
9037
  vectorizeOn: true,
9063
9038
  dbExists,
@@ -9122,17 +9097,7 @@ async function runSessionStart(repoRoot, out) {
9122
9097
  handoffPrune: handoffPrune ?? void 0
9123
9098
  }));
9124
9099
  }
9125
- async function runSessionEnd(repoRoot, out) {
9126
- const ctx = makeContext(repoRoot);
9127
- const config = loadVortexConfig(ctx);
9128
- if (config.autoRecord.worklog && hadActivityToday(repoRoot)) {
9129
- const res = await ensureWorklogEntry(ctx, {
9130
- body: "_Auto-created at session end (work detected but no worklog written). Enrich with the session's work, or remove if there is nothing to log._"
9131
- });
9132
- if (res.created)
9133
- out(`VortEX: created worklog ${res.path}
9134
- `);
9135
- }
9100
+ async function runSessionEnd(_repoRoot, _out) {
9136
9101
  }
9137
9102
  function gitOut(cwd, gitArgs) {
9138
9103
  return execFileSync2("git", [...gitArgs], {
@@ -9156,7 +9121,7 @@ function detectInterruptedGitOp(repoRoot) {
9156
9121
  const resolved = gitOut(repoRoot, args).split(/\r?\n/).map((s) => s.trim());
9157
9122
  for (let i = 0; i < markers.length; i++) {
9158
9123
  const p = resolved[i];
9159
- if (p && existsSync16(isAbsolute5(p) ? p : join31(repoRoot, p)))
9124
+ if (p && existsSync16(isAbsolute5(p) ? p : join30(repoRoot, p)))
9160
9125
  return markers[i];
9161
9126
  }
9162
9127
  } catch {
@@ -9172,19 +9137,6 @@ function collectCarryover(repoRoot, ignore) {
9172
9137
  }
9173
9138
  return uncommitted > 0 || interrupted ? { uncommitted, interrupted } : null;
9174
9139
  }
9175
- function hadActivityToday(repoRoot) {
9176
- try {
9177
- const dirty = gitOut(repoRoot, ["status", "--porcelain"]).trim();
9178
- if (dirty)
9179
- return true;
9180
- const since = /* @__PURE__ */ new Date();
9181
- since.setHours(0, 0, 0, 0);
9182
- const commits = gitOut(repoRoot, ["log", "--oneline", `--since=${since.toISOString()}`]).trim();
9183
- return commits.length > 0;
9184
- } catch {
9185
- return false;
9186
- }
9187
- }
9188
9140
  function resolveSessionEnvironment(ctx, config) {
9189
9141
  let environment = resolveEnvironment(config, {
9190
9142
  hostname: hostname(),
@@ -9194,7 +9146,7 @@ function resolveSessionEnvironment(ctx, config) {
9194
9146
  if (!environment)
9195
9147
  environment = process.env.VORTEX_ENV?.trim() || null;
9196
9148
  if (!environment) {
9197
- const envFile = join31(ctx.repoRoot, ".agent", "environment");
9149
+ const envFile = join30(ctx.repoRoot, ".agent", "environment");
9198
9150
  if (existsSync16(envFile)) {
9199
9151
  environment = readFileSync4(envFile, "utf8").split(/\r?\n/)[0]?.trim() || null;
9200
9152
  }
@@ -9203,9 +9155,9 @@ function resolveSessionEnvironment(ctx, config) {
9203
9155
  }
9204
9156
 
9205
9157
  // ../plugins/session-rituals/dist/ambient-recall.js
9206
- import { join as join32 } from "path";
9158
+ import { join as join31 } from "path";
9207
9159
  function defaultDbPath2(ctx) {
9208
- return join32(ctx.dataDir, "_indexes", "memory.sqlite");
9160
+ return join31(ctx.dataDir, "_indexes", "memory.sqlite");
9209
9161
  }
9210
9162
  function createAmbientRecaller(ctx, options) {
9211
9163
  const resolveDb = options.dbPath ?? defaultDbPath2;
@@ -9240,6 +9192,51 @@ function createAmbientRecaller(ctx, options) {
9240
9192
  }
9241
9193
  });
9242
9194
  }
9195
+
9196
+ // ../plugins/session-rituals/dist/worklog-write.js
9197
+ import { mkdir as mkdir10, writeFile as writeFile12 } from "fs/promises";
9198
+ import { dirname as dirname6, join as join32 } from "path";
9199
+ async function ensureWorklogEntry(ctx, opts) {
9200
+ const now = opts?.now ?? /* @__PURE__ */ new Date();
9201
+ const date = isoDate3(now);
9202
+ const time = isoTime2(now);
9203
+ const keyword = (opts?.keyword ?? "worklog").trim() || "worklog";
9204
+ const store = new WorklogStore(join32(ctx.dataDir, "worklog"));
9205
+ const existing = await store.get(date);
9206
+ if (existing) {
9207
+ return { path: existing.path, date: existing.date, keyword: existing.keyword, created: false };
9208
+ }
9209
+ const path = store.pathFor(date, keyword, time);
9210
+ const title = opts?.title ?? `${date} worklog`;
9211
+ await mkdir10(dirname6(path), { recursive: true });
9212
+ await writeFile12(path, renderWorklogFile(date, title, opts?.body ?? ""), "utf8");
9213
+ return { path, date, keyword, created: true };
9214
+ }
9215
+ function renderWorklogFile(date, title, body) {
9216
+ const trimmed = body.trimEnd();
9217
+ return `---
9218
+ type: worklog
9219
+ created: ${date}
9220
+ updated: ${date}
9221
+ tags: [worklog]
9222
+ ---
9223
+
9224
+ # ${title}
9225
+ ` + (trimmed ? `
9226
+ ${trimmed}
9227
+ ` : ``);
9228
+ }
9229
+ function isoDate3(d2) {
9230
+ const y2 = d2.getFullYear();
9231
+ const m2 = String(d2.getMonth() + 1).padStart(2, "0");
9232
+ const day = String(d2.getDate()).padStart(2, "0");
9233
+ return `${y2}-${m2}-${day}`;
9234
+ }
9235
+ function isoTime2(d2) {
9236
+ const h = String(d2.getHours()).padStart(2, "0");
9237
+ const m2 = String(d2.getMinutes()).padStart(2, "0");
9238
+ return `${h}${m2}`;
9239
+ }
9243
9240
  export {
9244
9241
  dist_exports5 as aiCodingPitfalls,
9245
9242
  dist_exports as core,