@vortex-os/base 0.10.0 → 0.12.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.
Files changed (38) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +48 -1
  3. package/bin/vortex.mjs +17 -17
  4. package/dist/{catch-up-KIHTAUPX.js → catch-up-GDDKPZHJ.js} +2 -2
  5. package/dist/chunk-2FVNWW77.js +166 -0
  6. package/dist/chunk-2FVNWW77.js.map +1 -0
  7. package/dist/{chunk-7SNLVGBO.js → chunk-3L5DLEGP.js} +1 -1
  8. package/dist/chunk-3L5DLEGP.js.map +1 -0
  9. package/dist/chunk-EAKDR5B2.js +501 -0
  10. package/dist/chunk-EAKDR5B2.js.map +1 -0
  11. package/dist/chunk-T53UWSTR.js +301 -0
  12. package/dist/chunk-T53UWSTR.js.map +1 -0
  13. package/dist/chunk-UV76ZEDC.js +292 -0
  14. package/dist/chunk-UV76ZEDC.js.map +1 -0
  15. package/dist/failures-PMURLMVB.js +25 -0
  16. package/dist/failures-PMURLMVB.js.map +1 -0
  17. package/dist/guard-IMJR6ET7.js +23 -0
  18. package/dist/guard-IMJR6ET7.js.map +1 -0
  19. package/dist/index.d.ts +425 -3
  20. package/dist/index.js +472 -709
  21. package/dist/index.js.map +1 -1
  22. package/dist/statusline-6KSHISXO.js +36 -0
  23. package/dist/statusline-6KSHISXO.js.map +1 -0
  24. package/dist/{vectorize-RBDBTSTW.js → vectorize-PN4Y7XMO.js} +1 -1
  25. package/dist/vectorize-PN4Y7XMO.js.map +1 -0
  26. package/package.json +1 -1
  27. package/templates/commands/agenda.md +15 -15
  28. package/templates/commands/handoff.md +26 -26
  29. package/templates/commands/resume.md +52 -52
  30. package/templates/config/vortex.json +13 -13
  31. package/templates/manifest.json +2 -2
  32. package/templates/routers/.cursorrules +14 -14
  33. package/templates/routers/AGENTS.md +27 -27
  34. package/templates/routers/AI-RULES.md +3 -1
  35. package/templates/routers/GEMINI.md +16 -16
  36. package/dist/chunk-7SNLVGBO.js.map +0 -1
  37. package/dist/vectorize-RBDBTSTW.js.map +0 -1
  38. /package/dist/{catch-up-KIHTAUPX.js.map → catch-up-GDDKPZHJ.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,291 +1,63 @@
1
+ import {
2
+ FAILURES_DIR,
3
+ GUARD_DENIAL_KEY,
4
+ failureReportSlice,
5
+ isValidFailureKey,
6
+ ladderStage,
7
+ recordFailure,
8
+ recordGuardDenial,
9
+ runFailureCli,
10
+ scanFailures
11
+ } from "./chunk-UV76ZEDC.js";
12
+ import {
13
+ SESSION_END_COMMAND,
14
+ SESSION_START_COMMAND,
15
+ collectStatuslineProbes,
16
+ effortMeter,
17
+ ensureStatusline,
18
+ ensureVortexHooks,
19
+ formatTokens,
20
+ formatWindow,
21
+ makeBar,
22
+ parseSettings,
23
+ parseStatuslineInput,
24
+ renderStatusline,
25
+ runStatuslineCli,
26
+ safeSegment,
27
+ serializeSettings,
28
+ sniffEffortFromTranscript,
29
+ statuslineCommand
30
+ } from "./chunk-EAKDR5B2.js";
31
+ import {
32
+ GUARD_WRITE_COMMAND,
33
+ GUARD_WRITE_MATCHER,
34
+ buildDenyDecision,
35
+ findControlChar,
36
+ guardWriteDecision,
37
+ resolveInstanceRoot,
38
+ runGuardCli,
39
+ scanToolInput
40
+ } from "./chunk-2FVNWW77.js";
41
+ import {
42
+ atomicWriteFile,
43
+ dist_exports,
44
+ exclusiveCreateFile,
45
+ isVisibleAt,
46
+ loadVortexConfig,
47
+ makeContext,
48
+ normalizePrivacy,
49
+ parseFrontmatter,
50
+ resolveEnvironment,
51
+ serializeFrontmatter,
52
+ validateDataRelativePath
53
+ } from "./chunk-T53UWSTR.js";
1
54
  import {
2
55
  catchUpSessions
3
- } from "./chunk-7SNLVGBO.js";
56
+ } from "./chunk-3L5DLEGP.js";
4
57
  import {
5
58
  __export
6
59
  } from "./chunk-PZ5AY32C.js";
7
60
 
8
- // ../core/dist/index.js
9
- var dist_exports = {};
10
- __export(dist_exports, {
11
- Privacy: () => Privacy,
12
- atomicWriteFile: () => atomicWriteFile,
13
- exclusiveCreateFile: () => exclusiveCreateFile,
14
- isVisibleAt: () => isVisibleAt,
15
- loadVortexConfig: () => loadVortexConfig,
16
- makeContext: () => makeContext,
17
- maxPrivacy: () => maxPrivacy,
18
- moduleDir: () => moduleDir,
19
- normalizePrivacy: () => normalizePrivacy,
20
- parseFrontmatter: () => parseFrontmatter,
21
- resolveEnvironment: () => resolveEnvironment,
22
- serializeFrontmatter: () => serializeFrontmatter,
23
- validateDataRelativePath: () => validateDataRelativePath,
24
- vortexConfigPath: () => vortexConfigPath
25
- });
26
-
27
- // ../core/dist/types.js
28
- var Privacy = {
29
- Public: "public",
30
- Internal: "internal",
31
- Personal: "personal"
32
- };
33
-
34
- // ../core/dist/frontmatter.js
35
- import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
36
- var FENCE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
37
- var BOM = "\uFEFF";
38
- function parseFrontmatter(source) {
39
- const cleaned = source.startsWith(BOM) ? source.slice(1) : source;
40
- const match = cleaned.match(FENCE);
41
- if (!match) {
42
- return {
43
- frontmatter: {},
44
- body: cleaned
45
- };
46
- }
47
- const yaml = match[1] ?? "";
48
- const body = cleaned.slice(match[0].length);
49
- let parsed;
50
- try {
51
- const value = parseYaml(yaml);
52
- parsed = typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
53
- } catch {
54
- parsed = {};
55
- }
56
- return { frontmatter: parsed, body };
57
- }
58
- function serializeFrontmatter(doc) {
59
- const keys = Object.keys(doc.frontmatter ?? {});
60
- if (keys.length === 0)
61
- return doc.body;
62
- const yaml = stringifyYaml(doc.frontmatter).trimEnd();
63
- return `---
64
- ${yaml}
65
- ---
66
- ${doc.body}`;
67
- }
68
-
69
- // ../core/dist/privacy.js
70
- var ORDER = {
71
- public: 0,
72
- internal: 1,
73
- personal: 2
74
- };
75
- function isVisibleAt(docPrivacy, viewerPrivacy) {
76
- return ORDER[docPrivacy] <= ORDER[viewerPrivacy];
77
- }
78
- function maxPrivacy(a, b2) {
79
- return ORDER[a] >= ORDER[b2] ? a : b2;
80
- }
81
- function normalizePrivacy(value, fallback = "internal") {
82
- if (value === "public" || value === "internal" || value === "personal") {
83
- return value;
84
- }
85
- return fallback;
86
- }
87
-
88
- // ../core/dist/paths.js
89
- import { resolve, join } from "path";
90
- function makeContext(repoRoot) {
91
- const root = resolve(repoRoot);
92
- return {
93
- repoRoot: root,
94
- agentDir: join(root, ".agent"),
95
- dataDir: join(root, "data"),
96
- modulesDir: join(root, "modules"),
97
- pluginsDir: join(root, "plugins")
98
- };
99
- }
100
- function moduleDir(ctx, moduleName) {
101
- return join(ctx.modulesDir, moduleName);
102
- }
103
-
104
- // ../core/dist/config.js
105
- import { existsSync, readFileSync } from "fs";
106
- import { join as join2 } from "path";
107
- 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, reindex: true, backfill: true },
109
- updates: { check: "session" },
110
- environments: []
111
- };
112
- function vortexConfigPath(ctx) {
113
- return join2(ctx.agentDir, "vortex.json");
114
- }
115
- function parseEnvironmentRule(raw) {
116
- if (typeof raw !== "object" || raw === null || Array.isArray(raw))
117
- return null;
118
- const candidate = raw;
119
- if (typeof candidate.label !== "string")
120
- return null;
121
- const rule = {
122
- label: candidate.label
123
- };
124
- if (typeof candidate.pathExists === "string")
125
- rule.pathExists = candidate.pathExists;
126
- if (typeof candidate.hostname === "string")
127
- rule.hostname = candidate.hostname;
128
- if (typeof candidate.envVar === "string") {
129
- rule.envVar = candidate.envVar;
130
- } else if (typeof candidate.envVar === "object" && candidate.envVar !== null) {
131
- const ev = candidate.envVar;
132
- if (typeof ev.name === "string") {
133
- rule.envVar = typeof ev.equals === "string" ? { name: ev.name, equals: ev.equals } : { name: ev.name };
134
- }
135
- }
136
- return rule;
137
- }
138
- function loadVortexConfig(ctx) {
139
- const path = vortexConfigPath(ctx);
140
- if (!existsSync(path))
141
- return DEFAULT_CONFIG;
142
- try {
143
- const raw = JSON.parse(readFileSync(path, "utf8"));
144
- const environments = Array.isArray(raw.environments) ? raw.environments.map(parseEnvironmentRule).filter((rule) => rule !== null) : [];
145
- const rawUpdates = raw.updates && typeof raw.updates === "object" && !Array.isArray(raw.updates) ? raw.updates : {};
146
- const rawCheck = rawUpdates.check;
147
- const check = rawCheck === void 0 ? "session" : typeof rawCheck === "string" && rawCheck.trim().toLowerCase() === "session" ? "session" : "off";
148
- const rawAuto = raw.autoRecord && typeof raw.autoRecord === "object" && !Array.isArray(raw.autoRecord) ? raw.autoRecord : {};
149
- const vectorizeAutoDownload = rawAuto.vectorizeAutoDownload === void 0 ? true : rawAuto.vectorizeAutoDownload === true;
150
- const commitFrameworkChanges = rawAuto.commitFrameworkChanges === void 0 ? true : rawAuto.commitFrameworkChanges === true;
151
- const handoff = rawAuto.handoff === void 0 ? true : rawAuto.handoff === true;
152
- const reindex = rawAuto.reindex === void 0 ? true : rawAuto.reindex === true;
153
- const backfill = rawAuto.backfill === void 0 ? true : rawAuto.backfill === true;
154
- const rawDays = rawAuto.handoffRetentionDays;
155
- const handoffRetentionDays = typeof rawDays === "number" && Number.isFinite(rawDays) && rawDays > 0 ? Math.floor(rawDays) : DEFAULT_CONFIG.autoRecord.handoffRetentionDays;
156
- return {
157
- autoRecord: {
158
- ...DEFAULT_CONFIG.autoRecord,
159
- ...raw.autoRecord ?? {},
160
- vectorizeAutoDownload,
161
- commitFrameworkChanges,
162
- handoff,
163
- handoffRetentionDays,
164
- reindex,
165
- backfill
166
- },
167
- updates: { check },
168
- environments
169
- };
170
- } catch {
171
- return DEFAULT_CONFIG;
172
- }
173
- }
174
- function resolveEnvironment(config, signals) {
175
- const host = signals.hostname?.toLowerCase();
176
- const env = signals.env ?? {};
177
- const pathExists = signals.pathExists ?? (() => false);
178
- for (const rule of config.environments) {
179
- if (rule.pathExists && pathExists(rule.pathExists))
180
- return rule.label;
181
- if (rule.hostname && host && rule.hostname.toLowerCase() === host)
182
- return rule.label;
183
- if (rule.envVar) {
184
- if (typeof rule.envVar === "string") {
185
- if (env[rule.envVar] !== void 0)
186
- return rule.label;
187
- } else {
188
- const v2 = env[rule.envVar.name];
189
- if (v2 !== void 0 && (rule.envVar.equals === void 0 || v2 === rule.envVar.equals)) {
190
- return rule.label;
191
- }
192
- }
193
- }
194
- }
195
- return null;
196
- }
197
-
198
- // ../core/dist/safe-fs.js
199
- import { rename, writeFile } from "fs/promises";
200
- import { isAbsolute, relative, resolve as resolve2, sep } from "path";
201
- var SYSTEM_META_DIRS = /* @__PURE__ */ new Set([
202
- "worklog",
203
- "decision-log",
204
- "runbooks",
205
- "hubs",
206
- "_memory",
207
- "_templates",
208
- "_proactive-curator",
209
- // Framework metadata carve-out: `data/.vortex/` holds the update-lifecycle
210
- // ownership manifest and template backups. It is NOT user space — the curate
211
- // value loop (and any LLM-chosen write path) must never target it, even
212
- // though it does not start with `_`. (The leading-`_` rule below does not
213
- // cover a leading-dot dir, so it is listed explicitly.)
214
- ".vortex"
215
- ]);
216
- var DRIVE_QUALIFIED = /^[a-zA-Z]:/;
217
- var CONTROL_CHARS = /[\u0000-\u001F]/;
218
- function validateDataRelativePath(dataDir, rel, _options = {}) {
219
- if (typeof rel !== "string" || rel.length === 0) {
220
- throw new Error("Invalid data-relative path: must be a non-empty string.");
221
- }
222
- if (CONTROL_CHARS.test(rel)) {
223
- throw new Error("Invalid data-relative path: contains control characters.");
224
- }
225
- const normalized = rel.replace(/\\/g, "/");
226
- if (normalized === "" || normalized === ".") {
227
- throw new Error(`Invalid data-relative path: "${rel}" is empty or '.'.`);
228
- }
229
- if (DRIVE_QUALIFIED.test(normalized)) {
230
- throw new Error(`Invalid data-relative path: "${rel}" is drive-qualified (must be data-relative).`);
231
- }
232
- if (isAbsolute(normalized) || normalized.startsWith("/")) {
233
- throw new Error(`Invalid data-relative path: "${rel}" is absolute (must be data-relative).`);
234
- }
235
- const segments = normalized.split("/");
236
- for (const segment of segments) {
237
- if (segment === "" || segment === "." || segment === "..") {
238
- throw new Error(`Invalid data-relative path: "${rel}" contains an empty, '.', or '..' segment (path traversal).`);
239
- }
240
- }
241
- const filename = segments[segments.length - 1];
242
- if (filename.length === 0 || filename.includes("/") || filename.includes("\\")) {
243
- throw new Error(`Invalid data-relative path: "${rel}" has an invalid filename.`);
244
- }
245
- const first = segments[0];
246
- if (SYSTEM_META_DIRS.has(first) || first.startsWith("_")) {
247
- throw new Error(`Invalid data-relative path: "${rel}" targets a reserved system/meta directory ("${first}"). The curate value loop writes user documents only \u2014 not worklog/decision-log/runbooks/hubs or any _* directory.`);
248
- }
249
- const absPath = resolve2(dataDir, normalized);
250
- const rootResolved = resolve2(dataDir);
251
- let relToData = relative(rootResolved, absPath);
252
- let relCompare = relToData;
253
- let upPrefix = ".." + sep;
254
- if (sep === "\\") {
255
- relCompare = relToData.toLowerCase();
256
- upPrefix = upPrefix.toLowerCase();
257
- }
258
- if (relCompare === ".." || relCompare.startsWith(upPrefix) || isAbsolute(relToData)) {
259
- throw new Error(`Invalid data-relative path: "${rel}" resolves outside the data directory.`);
260
- }
261
- return absPath;
262
- }
263
- async function exclusiveCreateFile(absPath, body) {
264
- try {
265
- await writeFile(absPath, body, { encoding: "utf8", flag: "wx" });
266
- } catch (e) {
267
- if (e.code === "EEXIST") {
268
- throw new Error(`Refusing to overwrite existing file: ${absPath}. create-file is an exclusive create; to add to an existing document use append-section instead.`);
269
- }
270
- throw e;
271
- }
272
- }
273
- var atomicWriteCounter = 0;
274
- async function atomicWriteFile(absPath, body) {
275
- const tmp = `${absPath}.tmp-${process.pid}-${atomicWriteCounter++}`;
276
- try {
277
- await writeFile(tmp, body, { encoding: "utf8" });
278
- await rename(tmp, absPath);
279
- } catch (e) {
280
- try {
281
- const { rm } = await import("fs/promises");
282
- await rm(tmp, { force: true });
283
- } catch {
284
- }
285
- throw e;
286
- }
287
- }
288
-
289
61
  // ../modules/slash-commands/dist/index.js
290
62
  var dist_exports2 = {};
291
63
  __export(dist_exports2, {
@@ -399,8 +171,8 @@ var MemoryType = {
399
171
  };
400
172
 
401
173
  // ../modules/memory-system/dist/store.js
402
- import { readdir, readFile, writeFile as writeFile2, mkdir, unlink, stat } from "fs/promises";
403
- import { join as join3, basename, extname } from "path";
174
+ import { readdir, readFile, writeFile, mkdir, unlink, stat } from "fs/promises";
175
+ import { join, basename, extname } from "path";
404
176
  var MemoryStore = class {
405
177
  dir;
406
178
  constructor(dir) {
@@ -434,7 +206,7 @@ var MemoryStore = class {
434
206
  frontmatter: memory.frontmatter,
435
207
  body: memory.body
436
208
  });
437
- await writeFile2(this.pathFor(memory.id), source, "utf8");
209
+ await writeFile(this.pathFor(memory.id), source, "utf8");
438
210
  }
439
211
  /** Delete a memory. Returns false if it did not exist. */
440
212
  async delete(id) {
@@ -458,13 +230,13 @@ var MemoryStore = class {
458
230
  }
459
231
  /** Absolute path of a memory file (file may not exist). */
460
232
  pathFor(id) {
461
- return join3(this.dir, `${id}.md`);
233
+ return join(this.dir, `${id}.md`);
462
234
  }
463
235
  };
464
236
 
465
237
  // ../modules/memory-system/dist/memory-index.js
466
- import { writeFile as writeFile3 } from "fs/promises";
467
- import { join as join4 } from "path";
238
+ import { writeFile as writeFile2 } from "fs/promises";
239
+ import { join as join2 } from "path";
468
240
  async function writeMemoryIndex(store, options = {}) {
469
241
  const ids = await store.list();
470
242
  const lines = [];
@@ -476,7 +248,7 @@ async function writeMemoryIndex(store, options = {}) {
476
248
  const memory = await store.read(id);
477
249
  lines.push(`- [${memory.frontmatter.name}](${id}.md) \u2014 ${memory.frontmatter.description}`);
478
250
  }
479
- await writeFile3(join4(store.dir, "MEMORY.md"), `${lines.join("\n")}
251
+ await writeFile2(join2(store.dir, "MEMORY.md"), `${lines.join("\n")}
480
252
  `, "utf8");
481
253
  }
482
254
 
@@ -514,7 +286,7 @@ __export(dist_exports4, {
514
286
 
515
287
  // ../modules/data-lint/dist/runner.js
516
288
  import { readdir as readdir2, readFile as readFile3 } from "fs/promises";
517
- import { join as join5 } from "path";
289
+ import { join as join3 } from "path";
518
290
  async function lintDirectory(options) {
519
291
  const start = Date.now();
520
292
  const extensions = options.extensions ?? [".md"];
@@ -551,7 +323,7 @@ async function collectFiles(dir, extensions) {
551
323
  throw e;
552
324
  }
553
325
  for (const entry of entries) {
554
- const full = join5(current, entry.name);
326
+ const full = join3(current, entry.name);
555
327
  if (entry.isDirectory()) {
556
328
  stack.push(full);
557
329
  } else if (entry.isFile() && extensions.some((ext) => entry.name.endsWith(ext))) {
@@ -612,7 +384,7 @@ function privacyValid() {
612
384
 
613
385
  // ../modules/data-lint/dist/rules/wiki-link-resolves.js
614
386
  import { readdir as readdir3 } from "fs/promises";
615
- import { basename as basename2, extname as extname2, join as join6 } from "path";
387
+ import { basename as basename2, extname as extname2, join as join4 } from "path";
616
388
  var WIKI_LINK = /\[\[([^\]|#]+)(?:[|#][^\]]*)?\]\]/g;
617
389
  function wikiLinkResolves(options) {
618
390
  let cache;
@@ -633,7 +405,7 @@ function wikiLinkResolves(options) {
633
405
  continue;
634
406
  }
635
407
  for (const entry of entries) {
636
- const full = join6(current, entry.name);
408
+ const full = join4(current, entry.name);
637
409
  if (entry.isDirectory()) {
638
410
  stack.push(full);
639
411
  } else if (entry.isFile()) {
@@ -718,7 +490,7 @@ __export(dist_exports5, {
718
490
 
719
491
  // ../modules/ai-coding-pitfalls/dist/catalog.js
720
492
  import { readdir as readdir4, readFile as readFile4 } from "fs/promises";
721
- import { basename as basename3, extname as extname3, join as join7 } from "path";
493
+ import { basename as basename3, extname as extname3, join as join5 } from "path";
722
494
  var PitfallCatalog = class {
723
495
  dir;
724
496
  constructor(dir) {
@@ -746,7 +518,7 @@ var PitfallCatalog = class {
746
518
  async entries() {
747
519
  try {
748
520
  const names = await readdir4(this.dir);
749
- return names.filter((n) => n.endsWith(".md")).map((n) => join7(this.dir, n));
521
+ return names.filter((n) => n.endsWith(".md")).map((n) => join5(this.dir, n));
750
522
  } catch (e) {
751
523
  if (e.code === "ENOENT")
752
524
  return [];
@@ -778,7 +550,7 @@ __export(dist_exports6, {
778
550
 
779
551
  // ../modules/tool-rules/dist/catalog.js
780
552
  import { readdir as readdir5, readFile as readFile5 } from "fs/promises";
781
- import { basename as basename4, extname as extname4, join as join8 } from "path";
553
+ import { basename as basename4, extname as extname4, join as join6 } from "path";
782
554
  var ToolRuleCatalog = class {
783
555
  dir;
784
556
  constructor(dir) {
@@ -811,7 +583,7 @@ var ToolRuleCatalog = class {
811
583
  async entries() {
812
584
  try {
813
585
  const names = await readdir5(this.dir);
814
- return names.filter((n) => n.endsWith(".md")).map((n) => join8(this.dir, n));
586
+ return names.filter((n) => n.endsWith(".md")).map((n) => join6(this.dir, n));
815
587
  } catch (e) {
816
588
  if (e.code === "ENOENT")
817
589
  return [];
@@ -2075,7 +1847,7 @@ __export(dist_exports8, {
2075
1847
 
2076
1848
  // ../modules/worklog/dist/store.js
2077
1849
  import { readdir as readdir6, readFile as readFile6, stat as stat2 } from "fs/promises";
2078
- import { join as join9, resolve as resolve3, sep as sep2 } from "path";
1850
+ import { join as join7, resolve, sep } from "path";
2079
1851
  var FILENAME_PATTERN = /^(\d{4}-\d{2}-\d{2})(?:_(\d{4}))?-(.+)\.md$/;
2080
1852
  var MONTH_PATTERN = /^\d{2}$/;
2081
1853
  var YEAR_PATTERN = /^\d{4}$/;
@@ -2089,17 +1861,17 @@ var WorklogStore = class {
2089
1861
  const years = await this.listSubdirs(this.rootDir, YEAR_PATTERN);
2090
1862
  const entries = [];
2091
1863
  for (const year of years) {
2092
- const yearDir = join9(this.rootDir, year);
1864
+ const yearDir = join7(this.rootDir, year);
2093
1865
  const months = await this.listSubdirs(yearDir, MONTH_PATTERN);
2094
1866
  for (const month of months) {
2095
- entries.push(...await this.entriesIn(join9(yearDir, month)));
1867
+ entries.push(...await this.entriesIn(join7(yearDir, month)));
2096
1868
  }
2097
1869
  }
2098
1870
  return entries.sort(compareWorklog);
2099
1871
  }
2100
1872
  /** Entries within one calendar month. */
2101
1873
  async listByMonth(year, month) {
2102
- const monthDir = join9(this.rootDir, String(year).padStart(4, "0"), String(month).padStart(2, "0"));
1874
+ const monthDir = join7(this.rootDir, String(year).padStart(4, "0"), String(month).padStart(2, "0"));
2103
1875
  const entries = await this.entriesIn(monthDir);
2104
1876
  return entries.sort(compareWorklog);
2105
1877
  }
@@ -2112,7 +1884,7 @@ var WorklogStore = class {
2112
1884
  const [year, month] = date.split("-");
2113
1885
  if (!year || !month)
2114
1886
  return void 0;
2115
- const monthDir = join9(this.rootDir, year, month);
1887
+ const monthDir = join7(this.rootDir, year, month);
2116
1888
  const entries = (await this.entriesIn(monthDir)).filter((e) => e.date === date).sort(compareWorklog);
2117
1889
  return entries[0];
2118
1890
  }
@@ -2134,7 +1906,7 @@ var WorklogStore = class {
2134
1906
  const [year, month] = date.split("-");
2135
1907
  validateSegment("keyword", keyword);
2136
1908
  const stem = time ? `${date}_${time}-${keyword}` : `${date}-${keyword}`;
2137
- const abs = join9(this.rootDir, year, month, `${stem}.md`);
1909
+ const abs = join7(this.rootDir, year, month, `${stem}.md`);
2138
1910
  assertContained(abs, this.rootDir);
2139
1911
  return abs;
2140
1912
  }
@@ -2162,7 +1934,7 @@ var WorklogStore = class {
2162
1934
  const match = name.match(FILENAME_PATTERN);
2163
1935
  if (!match)
2164
1936
  continue;
2165
- const path = join9(monthDir, name);
1937
+ const path = join7(monthDir, name);
2166
1938
  try {
2167
1939
  const info = await stat2(path);
2168
1940
  if (!info.isFile())
@@ -2203,15 +1975,15 @@ function validateSegment(label, value) {
2203
1975
  throw new Error(`${label} must not contain NUL or control characters: ${value}`);
2204
1976
  }
2205
1977
  function assertContained(abs, rootDir) {
2206
- const root = resolve3(rootDir);
2207
- const target = resolve3(abs);
2208
- if (target !== root && !(target + sep2).startsWith(root + sep2)) {
1978
+ const root = resolve(rootDir);
1979
+ const target = resolve(abs);
1980
+ if (target !== root && !(target + sep).startsWith(root + sep)) {
2209
1981
  throw new Error(`Refusing to write outside the store directory: ${abs}`);
2210
1982
  }
2211
1983
  }
2212
1984
 
2213
1985
  // ../modules/worklog/dist/append.js
2214
- import { readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
1986
+ import { readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
2215
1987
  async function appendSection(entry, title, body) {
2216
1988
  const original = await readFile7(entry.path, "utf8");
2217
1989
  const trimmed = original.replace(/\s+$/u, "");
@@ -2222,7 +1994,7 @@ ${body.trimEnd()}
2222
1994
  const next = `${trimmed}
2223
1995
 
2224
1996
  ${section}`;
2225
- await writeFile4(entry.path, next, "utf8");
1997
+ await writeFile3(entry.path, next, "utf8");
2226
1998
  return next;
2227
1999
  }
2228
2000
 
@@ -2235,7 +2007,7 @@ __export(dist_exports9, {
2235
2007
 
2236
2008
  // ../modules/decision-log/dist/store.js
2237
2009
  import { readdir as readdir7, readFile as readFile8, stat as stat3 } from "fs/promises";
2238
- import { join as join10, resolve as resolve4, sep as sep3 } from "path";
2010
+ import { join as join8, resolve as resolve2, sep as sep2 } from "path";
2239
2011
  var FILENAME_PATTERN2 = /^(\d{4}-\d{2}-\d{2})-(.+)\.md$/;
2240
2012
  var DecisionStore = class {
2241
2013
  rootDir;
@@ -2257,7 +2029,7 @@ var DecisionStore = class {
2257
2029
  const match = name.match(FILENAME_PATTERN2);
2258
2030
  if (!match)
2259
2031
  continue;
2260
- const path = join10(this.rootDir, name);
2032
+ const path = join8(this.rootDir, name);
2261
2033
  try {
2262
2034
  const info = await stat3(path);
2263
2035
  if (!info.isFile())
@@ -2329,7 +2101,7 @@ var DecisionStore = class {
2329
2101
  throw new Error(`Invalid date: ${date} (expected YYYY-MM-DD)`);
2330
2102
  }
2331
2103
  validateSegment2("slug", slug);
2332
- const abs = join10(this.rootDir, `${date}-${slug}.md`);
2104
+ const abs = join8(this.rootDir, `${date}-${slug}.md`);
2333
2105
  assertContained2(abs, this.rootDir);
2334
2106
  return abs;
2335
2107
  }
@@ -2348,9 +2120,9 @@ function validateSegment2(label, value) {
2348
2120
  throw new Error(`${label} must not contain NUL or control characters: ${value}`);
2349
2121
  }
2350
2122
  function assertContained2(abs, rootDir) {
2351
- const root = resolve4(rootDir);
2352
- const target = resolve4(abs);
2353
- if (target !== root && !(target + sep3).startsWith(root + sep3)) {
2123
+ const root = resolve2(rootDir);
2124
+ const target = resolve2(abs);
2125
+ if (target !== root && !(target + sep2).startsWith(root + sep2)) {
2354
2126
  throw new Error(`Refusing to write outside the store directory: ${abs}`);
2355
2127
  }
2356
2128
  }
@@ -2415,7 +2187,7 @@ __export(dist_exports10, {
2415
2187
 
2416
2188
  // ../modules/index-generator/dist/scan.js
2417
2189
  import { readdir as readdir8, readFile as readFile9, stat as stat4 } from "fs/promises";
2418
- import { basename as basename5, extname as extname5, join as join11, relative as relative2 } from "path";
2190
+ import { basename as basename5, extname as extname5, join as join9, relative } from "path";
2419
2191
  var RESERVED_FILES = /* @__PURE__ */ new Set(["README.md", "_INDEX.md"]);
2420
2192
  var H1_PATTERN = /^#\s+(.+?)\s*$/m;
2421
2193
  async function scanDirectory(rootDir, opts = {}) {
@@ -2445,7 +2217,7 @@ async function walk(rootDir, currentDir, recursive, skipFilenames, skipPrefixes,
2445
2217
  continue;
2446
2218
  if (name.startsWith(".") || name.startsWith("_"))
2447
2219
  continue;
2448
- await walk(rootDir, join11(currentDir, name), recursive, skipFilenames, skipPrefixes, out);
2220
+ await walk(rootDir, join9(currentDir, name), recursive, skipFilenames, skipPrefixes, out);
2449
2221
  continue;
2450
2222
  }
2451
2223
  if (!dirent.isFile())
@@ -2457,7 +2229,7 @@ async function walk(rootDir, currentDir, recursive, skipFilenames, skipPrefixes,
2457
2229
  const nameNoExt = basename5(name, ".md");
2458
2230
  if (skipPrefixes.some((p) => nameNoExt.startsWith(p)))
2459
2231
  continue;
2460
- const fullPath = join11(currentDir, name);
2232
+ const fullPath = join9(currentDir, name);
2461
2233
  let info;
2462
2234
  try {
2463
2235
  info = await stat4(fullPath);
@@ -2474,7 +2246,7 @@ async function walk(rootDir, currentDir, recursive, skipFilenames, skipPrefixes,
2474
2246
  const updated = stringField(frontmatter, "updated") ?? stringField(frontmatter, "created");
2475
2247
  const scope = stringField(frontmatter, "scope");
2476
2248
  out.push({
2477
- relPath: relative2(rootDir, fullPath).split(/[\\/]/).join("/"),
2249
+ relPath: relative(rootDir, fullPath).split(/[\\/]/).join("/"),
2478
2250
  name: nameNoExt,
2479
2251
  title,
2480
2252
  description,
@@ -2613,7 +2385,7 @@ function today() {
2613
2385
 
2614
2386
  // ../modules/index-generator/dist/nested.js
2615
2387
  import { readdir as readdir9, stat as stat5 } from "fs/promises";
2616
- import { extname as extname6, join as join12 } from "path";
2388
+ import { extname as extname6, join as join10 } from "path";
2617
2389
  async function findIndexableDirs(rootDir, options = {}) {
2618
2390
  const minEntries = options.minEntries ?? 1;
2619
2391
  const skipPrefixes = options.skipPrefixes ?? [];
@@ -2649,7 +2421,7 @@ async function walk2(dir, minEntries, skipPrefixes, out) {
2649
2421
  if (skipPrefixes.some((p) => nameNoExt.startsWith(p)))
2650
2422
  continue;
2651
2423
  try {
2652
- const info = await stat5(join12(dir, dirent.name));
2424
+ const info = await stat5(join10(dir, dirent.name));
2653
2425
  if (!info.isFile())
2654
2426
  continue;
2655
2427
  } catch {
@@ -2661,7 +2433,7 @@ async function walk2(dir, minEntries, skipPrefixes, out) {
2661
2433
  out.push(dir);
2662
2434
  }
2663
2435
  for (const name of subdirs) {
2664
- await walk2(join12(dir, name), minEntries, skipPrefixes, out);
2436
+ await walk2(join10(dir, name), minEntries, skipPrefixes, out);
2665
2437
  }
2666
2438
  }
2667
2439
 
@@ -2673,7 +2445,7 @@ __export(dist_exports11, {
2673
2445
 
2674
2446
  // ../modules/runbooks/dist/store.js
2675
2447
  import { readdir as readdir10, readFile as readFile10, stat as stat6 } from "fs/promises";
2676
- import { extname as extname7, join as join13 } from "path";
2448
+ import { extname as extname7, join as join11 } from "path";
2677
2449
  var RESERVED_FILES2 = /* @__PURE__ */ new Set(["README.md", "_INDEX.md"]);
2678
2450
  var RunbookStore = class {
2679
2451
  rootDir;
@@ -2696,7 +2468,7 @@ var RunbookStore = class {
2696
2468
  continue;
2697
2469
  if (RESERVED_FILES2.has(name))
2698
2470
  continue;
2699
- const path = join13(this.rootDir, name);
2471
+ const path = join11(this.rootDir, name);
2700
2472
  try {
2701
2473
  const info = await stat6(path);
2702
2474
  if (!info.isFile())
@@ -2805,7 +2577,7 @@ function extractWikiLinks(body) {
2805
2577
 
2806
2578
  // ../modules/link-rewriter/dist/resolve.js
2807
2579
  import { readdir as readdir11 } from "fs/promises";
2808
- import { basename as basename6, dirname, extname as extname8, isAbsolute as isAbsolute2, join as join14, relative as relative3, resolve as pathResolve } from "path";
2580
+ import { basename as basename6, dirname, extname as extname8, isAbsolute, join as join12, relative as relative2, resolve as pathResolve } from "path";
2809
2581
  async function buildFileIndex(rootDir, options = {}) {
2810
2582
  const byBasename = /* @__PURE__ */ new Map();
2811
2583
  const byRelPath = /* @__PURE__ */ new Map();
@@ -2838,7 +2610,7 @@ async function walk3(rootDir, dir, byBasename, byRelPath, additionalExts) {
2838
2610
  if (dirent.isDirectory()) {
2839
2611
  if (name.startsWith("."))
2840
2612
  continue;
2841
- await walk3(rootDir, join14(dir, name), byBasename, byRelPath, additionalExts);
2613
+ await walk3(rootDir, join12(dir, name), byBasename, byRelPath, additionalExts);
2842
2614
  continue;
2843
2615
  }
2844
2616
  if (!dirent.isFile())
@@ -2847,7 +2619,7 @@ async function walk3(rootDir, dir, byBasename, byRelPath, additionalExts) {
2847
2619
  const isMd = ext === ".md";
2848
2620
  if (!isMd && !additionalExts.has(ext))
2849
2621
  continue;
2850
- const path = join14(dir, name);
2622
+ const path = join12(dir, name);
2851
2623
  const key = isMd ? basename6(name, ".md") : name;
2852
2624
  const list = byBasename.get(key);
2853
2625
  if (list) {
@@ -2855,7 +2627,7 @@ async function walk3(rootDir, dir, byBasename, byRelPath, additionalExts) {
2855
2627
  } else {
2856
2628
  byBasename.set(key, [path]);
2857
2629
  }
2858
- const relRaw = relative3(rootDir, path).split(/[\\/]/).join("/");
2630
+ const relRaw = relative2(rootDir, path).split(/[\\/]/).join("/");
2859
2631
  const rel = isMd ? relRaw.replace(/\.md$/, "") : relRaw;
2860
2632
  byRelPath.set(rel, path);
2861
2633
  }
@@ -2876,8 +2648,8 @@ function resolveLink(name, index, opts = {}) {
2876
2648
  return { kind: "not-found" };
2877
2649
  const baseDir = dirname(opts.sourcePath);
2878
2650
  const absolute = pathResolve(baseDir, normalized);
2879
- const rel = relative3(index.rootDir, absolute).split(/[\\/]/).join("/");
2880
- if (rel === ".." || rel.startsWith("../") || isAbsolute2(rel)) {
2651
+ const rel = relative2(index.rootDir, absolute).split(/[\\/]/).join("/");
2652
+ if (rel === ".." || rel.startsWith("../") || isAbsolute(rel)) {
2881
2653
  return { kind: "not-found" };
2882
2654
  }
2883
2655
  return lookupRelPath(rel, index);
@@ -2896,7 +2668,7 @@ function lookupRelPath(rel, index) {
2896
2668
  return { kind: "not-found" };
2897
2669
  }
2898
2670
  function toRel(path, rootDir) {
2899
- return relative3(rootDir, path).split(/[\\/]/).join("/");
2671
+ return relative2(rootDir, path).split(/[\\/]/).join("/");
2900
2672
  }
2901
2673
 
2902
2674
  // ../modules/link-rewriter/dist/checker.js
@@ -2946,7 +2718,7 @@ function topBrokenTargets(broken, limit = 20) {
2946
2718
  }
2947
2719
 
2948
2720
  // ../modules/link-rewriter/dist/rewrite.js
2949
- import { readFile as readFile12, writeFile as writeFile5 } from "fs/promises";
2721
+ import { readFile as readFile12, writeFile as writeFile4 } from "fs/promises";
2950
2722
  import { extname as extname10 } from "path";
2951
2723
  async function rewriteDirectory(rootDir, opts) {
2952
2724
  const { redirections, dryRun = false } = opts;
@@ -2968,7 +2740,7 @@ async function rewriteDirectory(rootDir, opts) {
2968
2740
  rewritesApplied += fileRewrites.length;
2969
2741
  details.push({ sourcePath: path, rewrites: fileRewrites });
2970
2742
  if (!dryRun) {
2971
- await writeFile5(path, newBody, "utf8");
2743
+ await writeFile4(path, newBody, "utf8");
2972
2744
  }
2973
2745
  }
2974
2746
  }
@@ -3072,18 +2844,18 @@ function normalizePath(p) {
3072
2844
  }
3073
2845
 
3074
2846
  // ../modules/proactive-curator/dist/doc-writer.js
3075
- import { existsSync as existsSync2 } from "fs";
2847
+ import { existsSync } from "fs";
3076
2848
  import { appendFile, mkdir as mkdir2, readFile as readFile13 } from "fs/promises";
3077
- import { dirname as dirname2, join as join15 } from "path";
2849
+ import { dirname as dirname2, join as join13 } from "path";
3078
2850
  async function writeDocAction(cwd, action) {
3079
- const dataDir = join15(cwd, "data");
2851
+ const dataDir = join13(cwd, "data");
3080
2852
  const abs = validateDataRelativePath(dataDir, action.targetRelPath);
3081
2853
  if (action.kind === "create-file") {
3082
2854
  await mkdir2(dirname2(abs), { recursive: true });
3083
2855
  await exclusiveCreateFile(abs, action.body);
3084
2856
  return { writtenPath: abs, kind: "create-file" };
3085
2857
  }
3086
- if (!existsSync2(abs)) {
2858
+ if (!existsSync(abs)) {
3087
2859
  throw new Error(`Cannot append-section: target file does not exist: ${action.targetRelPath}. append-section adds to an existing document; use create-file for a new one.`);
3088
2860
  }
3089
2861
  const existing = await readFile13(abs, "utf8");
@@ -3096,9 +2868,9 @@ ${action.body}`;
3096
2868
  }
3097
2869
 
3098
2870
  // ../modules/proactive-curator/dist/decline-store.js
3099
- import { existsSync as existsSync3 } from "fs";
3100
- import { appendFile as appendFile2, mkdir as mkdir3, readFile as readFile14, writeFile as writeFile6 } from "fs/promises";
3101
- import { join as join16 } from "path";
2871
+ import { existsSync as existsSync2 } from "fs";
2872
+ import { appendFile as appendFile2, mkdir as mkdir3, readFile as readFile14, writeFile as writeFile5 } from "fs/promises";
2873
+ import { join as join14 } from "path";
3102
2874
  var STORE_DIR = "data/_proactive-curator";
3103
2875
  var DECLINED_FILE = "declined.json";
3104
2876
  var ACCEPTED_LOG = "accepted.log";
@@ -3136,7 +2908,7 @@ async function recordDecline(cwd, args) {
3136
2908
  ...args.sourceDocs ? { sourceDocs: args.sourceDocs } : {}
3137
2909
  };
3138
2910
  updated[args.kind] = { ...updated[args.kind], [args.fingerprint]: entry };
3139
- await writeFile6(join16(cwd, STORE_DIR, DECLINED_FILE), JSON.stringify(updated, null, 2) + "\n", "utf8");
2911
+ await writeFile5(join14(cwd, STORE_DIR, DECLINED_FILE), JSON.stringify(updated, null, 2) + "\n", "utf8");
3140
2912
  }
3141
2913
  async function recordAcceptance(cwd, args) {
3142
2914
  await ensureStoreDir(cwd);
@@ -3148,19 +2920,19 @@ async function recordAcceptance(cwd, args) {
3148
2920
  actionKind: args.actionKind,
3149
2921
  writtenPath: args.writtenPath
3150
2922
  });
3151
- await appendFile2(join16(cwd, STORE_DIR, ACCEPTED_LOG), line + "\n", "utf8");
2923
+ await appendFile2(join14(cwd, STORE_DIR, ACCEPTED_LOG), line + "\n", "utf8");
3152
2924
  }
3153
2925
  async function resetDeclined(cwd, kind) {
3154
- const file = join16(cwd, STORE_DIR, DECLINED_FILE);
3155
- if (!existsSync3(file))
2926
+ const file = join14(cwd, STORE_DIR, DECLINED_FILE);
2927
+ if (!existsSync2(file))
3156
2928
  return;
3157
2929
  if (kind === void 0) {
3158
- await writeFile6(file, JSON.stringify(emptyDeclinedFile(), null, 2) + "\n", "utf8");
2930
+ await writeFile5(file, JSON.stringify(emptyDeclinedFile(), null, 2) + "\n", "utf8");
3159
2931
  return;
3160
2932
  }
3161
2933
  const parsed = await readDeclinedFile(cwd) ?? emptyDeclinedFile();
3162
2934
  parsed[kind] = {};
3163
- await writeFile6(file, JSON.stringify(parsed, null, 2) + "\n", "utf8");
2935
+ await writeFile5(file, JSON.stringify(parsed, null, 2) + "\n", "utf8");
3164
2936
  }
3165
2937
  function isActive(entry, nowMs) {
3166
2938
  const expiresMs = new Date(entry.expiresAt).getTime();
@@ -3181,8 +2953,8 @@ function purgeExpired(entries, now) {
3181
2953
  return out;
3182
2954
  }
3183
2955
  async function readDeclinedFile(cwd) {
3184
- const file = join16(cwd, STORE_DIR, DECLINED_FILE);
3185
- if (!existsSync3(file))
2956
+ const file = join14(cwd, STORE_DIR, DECLINED_FILE);
2957
+ if (!existsSync2(file))
3186
2958
  return null;
3187
2959
  try {
3188
2960
  const raw = await readFile14(file, "utf8");
@@ -3199,14 +2971,14 @@ function emptyDeclinedFile() {
3199
2971
  return { "capture-insight": {}, "create-hub": {} };
3200
2972
  }
3201
2973
  async function ensureStoreDir(cwd) {
3202
- await mkdir3(join16(cwd, STORE_DIR), { recursive: true });
2974
+ await mkdir3(join14(cwd, STORE_DIR), { recursive: true });
3203
2975
  }
3204
2976
 
3205
2977
  // ../modules/proactive-curator/dist/insight-proposer.js
3206
- import { existsSync as existsSync4 } from "fs";
3207
- import { mkdir as mkdir4, readFile as readFile15, readdir as readdir12, writeFile as writeFile7 } from "fs/promises";
3208
- import { dirname as dirname3, join as join17 } from "path";
3209
- var SYSTEM_META_DIRS2 = /* @__PURE__ */ new Set([
2978
+ import { existsSync as existsSync3 } from "fs";
2979
+ import { mkdir as mkdir4, readFile as readFile15, readdir as readdir12, writeFile as writeFile6 } from "fs/promises";
2980
+ import { dirname as dirname3, join as join15 } from "path";
2981
+ var SYSTEM_META_DIRS = /* @__PURE__ */ new Set([
3210
2982
  "worklog",
3211
2983
  "decision-log",
3212
2984
  "runbooks",
@@ -3416,7 +3188,7 @@ function normalizePlacementDecision(raw) {
3416
3188
  function isSystemMetaPath(p) {
3417
3189
  const normalized = p.replace(/\\/g, "/").replace(/^\/+/, "");
3418
3190
  const first = normalized.split("/")[0] ?? "";
3419
- if (SYSTEM_META_DIRS2.has(first))
3191
+ if (SYSTEM_META_DIRS.has(first))
3420
3192
  return true;
3421
3193
  if (first.startsWith("_"))
3422
3194
  return true;
@@ -3511,7 +3283,7 @@ function joinDataPath(...parts) {
3511
3283
  return parts.filter((p) => p.length > 0).map((p) => p.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "")).join("/");
3512
3284
  }
3513
3285
  async function applyAction(cwd, action) {
3514
- const dataDir = join17(cwd, "data");
3286
+ const dataDir = join15(cwd, "data");
3515
3287
  switch (action.kind) {
3516
3288
  case "create-file": {
3517
3289
  const res = await writeDocAction(cwd, {
@@ -3541,7 +3313,7 @@ async function applyAction(cwd, action) {
3541
3313
  const rel = joinDataPath(action.filePath);
3542
3314
  const file = validateDataRelativePath(dataDir, rel);
3543
3315
  await mkdir4(dirname3(file), { recursive: true });
3544
- await writeFile7(file, action.body, "utf8");
3316
+ await writeFile6(file, action.body, "utf8");
3545
3317
  return file;
3546
3318
  }
3547
3319
  }
@@ -3556,8 +3328,8 @@ function nextActionHintFor(action) {
3556
3328
  return `New file at ${action.folderPath}/${action.filename}. Add cross-links from related docs as the topic grows.`;
3557
3329
  }
3558
3330
  async function scanTopicTree(cwd, maxEntries) {
3559
- const dataDir = join17(cwd, "data");
3560
- if (!existsSync4(dataDir)) {
3331
+ const dataDir = join15(cwd, "data");
3332
+ if (!existsSync3(dataDir)) {
3561
3333
  return { folders: [], truncated: false };
3562
3334
  }
3563
3335
  const folders = [];
@@ -3584,7 +3356,7 @@ async function scanTopicTree(cwd, maxEntries) {
3584
3356
  } else if (e.isFile() && e.name.endsWith(".md")) {
3585
3357
  if (e.name === "README.md" || e.name === "_INDEX.md" || e.name === "MEMORY.md")
3586
3358
  continue;
3587
- const filePath = join17(absDir, e.name);
3359
+ const filePath = join15(absDir, e.name);
3588
3360
  let frontmatterTopic;
3589
3361
  let tags;
3590
3362
  try {
@@ -3621,14 +3393,14 @@ async function scanTopicTree(cwd, maxEntries) {
3621
3393
  return;
3622
3394
  }
3623
3395
  const childRel = joinDataPath(relDir, d2);
3624
- await visit(join17(absDir, d2), childRel);
3396
+ await visit(join15(absDir, d2), childRel);
3625
3397
  }
3626
3398
  }
3627
3399
  await visit(dataDir, "");
3628
3400
  return { folders, truncated };
3629
3401
  }
3630
3402
  function isReservedDir(name, atRoot) {
3631
- if (atRoot && SYSTEM_META_DIRS2.has(name))
3403
+ if (atRoot && SYSTEM_META_DIRS.has(name))
3632
3404
  return true;
3633
3405
  if (name.startsWith("."))
3634
3406
  return true;
@@ -3638,9 +3410,9 @@ function isReservedDir(name, atRoot) {
3638
3410
  }
3639
3411
 
3640
3412
  // ../modules/proactive-curator/dist/hub-proposer.js
3641
- import { existsSync as existsSync5 } from "fs";
3413
+ import { existsSync as existsSync4 } from "fs";
3642
3414
  import { mkdir as mkdir5, readFile as readFile16, readdir as readdir13 } from "fs/promises";
3643
- import { join as join18 } from "path";
3415
+ import { join as join16 } from "path";
3644
3416
  var DEFAULT_CATEGORIES = [
3645
3417
  "worklog",
3646
3418
  "decision-log",
@@ -3727,13 +3499,13 @@ var HubProposer = class {
3727
3499
  }
3728
3500
  };
3729
3501
  async function scanDocs(cwd, categories) {
3730
- const dataDir = join18(cwd, "data");
3731
- if (!existsSync5(dataDir))
3502
+ const dataDir = join16(cwd, "data");
3503
+ if (!existsSync4(dataDir))
3732
3504
  return [];
3733
3505
  const out = [];
3734
3506
  for (const category of categories) {
3735
- const abs = join18(dataDir, category);
3736
- if (!existsSync5(abs))
3507
+ const abs = join16(dataDir, category);
3508
+ if (!existsSync4(abs))
3737
3509
  continue;
3738
3510
  await walk4(abs, category, out);
3739
3511
  }
@@ -3750,13 +3522,13 @@ async function walk4(absDir, relPath, acc) {
3750
3522
  if (e.isDirectory()) {
3751
3523
  if (e.name.startsWith(".") || e.name.startsWith("_"))
3752
3524
  continue;
3753
- await walk4(join18(absDir, e.name), `${relPath}/${e.name}`, acc);
3525
+ await walk4(join16(absDir, e.name), `${relPath}/${e.name}`, acc);
3754
3526
  } else if (e.isFile() && e.name.endsWith(".md")) {
3755
3527
  if (e.name === "README.md" || e.name === "_INDEX.md" || e.name === "MEMORY.md")
3756
3528
  continue;
3757
3529
  if (e.name.startsWith("_TEMPLATE"))
3758
3530
  continue;
3759
- const filePath = join18(absDir, e.name);
3531
+ const filePath = join16(absDir, e.name);
3760
3532
  let frontmatterTopic;
3761
3533
  let tags = [];
3762
3534
  try {
@@ -3827,8 +3599,8 @@ function pickCluster(clusters, weakThreshold, cwd) {
3827
3599
  for (const c of clusters) {
3828
3600
  if (c.docs.length < weakThreshold)
3829
3601
  return null;
3830
- const hubPath = join18(cwd, "data", HUB_DIR, `_HUB-${c.topic}.md`);
3831
- if (existsSync5(hubPath))
3602
+ const hubPath = join16(cwd, "data", HUB_DIR, `_HUB-${c.topic}.md`);
3603
+ if (existsSync4(hubPath))
3832
3604
  continue;
3833
3605
  return c;
3834
3606
  }
@@ -3951,9 +3723,9 @@ async function applyHubCreate(cwd, action) {
3951
3723
  if (fn.trim().length === 0 || fn === "." || fn === ".." || unsafe.test(fn)) {
3952
3724
  throw new Error(`Refusing to create hub: unsafe filename "${action.filename}" \u2014 must be a plain basename with no path separators, traversal, or reserved characters (including ":").`);
3953
3725
  }
3954
- const folder = join18(cwd, "data", HUB_DIR);
3726
+ const folder = join16(cwd, "data", HUB_DIR);
3955
3727
  await mkdir5(folder, { recursive: true });
3956
- const file = join18(folder, fn);
3728
+ const file = join16(folder, fn);
3957
3729
  await exclusiveCreateFile(file, action.body);
3958
3730
  return file;
3959
3731
  }
@@ -4240,6 +4012,10 @@ var ClaudeDesktopLLMJudge = class extends InjectedLLMJudge {
4240
4012
  var dist_exports14 = {};
4241
4013
  __export(dist_exports14, {
4242
4014
  DEFAULT_GAP_WINDOW_DAYS: () => DEFAULT_GAP_WINDOW_DAYS,
4015
+ FAILURES_DIR: () => FAILURES_DIR,
4016
+ GUARD_DENIAL_KEY: () => GUARD_DENIAL_KEY,
4017
+ GUARD_WRITE_COMMAND: () => GUARD_WRITE_COMMAND,
4018
+ GUARD_WRITE_MATCHER: () => GUARD_WRITE_MATCHER,
4243
4019
  HANDOFF_ARCHIVE_DIR: () => HANDOFF_ARCHIVE_DIR,
4244
4020
  HANDOFF_DIR: () => HANDOFF_DIR,
4245
4021
  OWNERSHIP_SCHEMA: () => OWNERSHIP_SCHEMA,
@@ -4250,6 +4026,7 @@ __export(dist_exports14, {
4250
4026
  applyGlobalSetup: () => applyGlobalSetup,
4251
4027
  argvToSlash: () => argvToSlash,
4252
4028
  autoReindexMemory: () => autoReindexMemory,
4029
+ buildDenyDecision: () => buildDenyDecision,
4253
4030
  buildInstallCommand: () => buildInstallCommand,
4254
4031
  buildOwnershipManifest: () => buildOwnershipManifest,
4255
4032
  buildRegistry: () => buildRegistry,
@@ -4258,6 +4035,7 @@ __export(dist_exports14, {
4258
4035
  collectAgenda: () => collectAgenda,
4259
4036
  collectCarryover: () => collectCarryover,
4260
4037
  collectSessionStartReport: () => collectSessionStartReport,
4038
+ collectStatuslineProbes: () => collectStatuslineProbes,
4261
4039
  compareSemver: () => compareSemver,
4262
4040
  computeCurateFingerprint: () => computeCurateFingerprint,
4263
4041
  countUncommitted: () => countUncommitted,
@@ -4268,46 +4046,69 @@ __export(dist_exports14, {
4268
4046
  decisionCommand: () => decisionCommand,
4269
4047
  detectInterruptedGitOp: () => detectInterruptedGitOp,
4270
4048
  detectWorklogGaps: () => detectWorklogGaps,
4049
+ effortMeter: () => effortMeter,
4050
+ ensureStatusline: () => ensureStatusline,
4271
4051
  ensureVortexHooks: () => ensureVortexHooks,
4272
4052
  ensureWorklogEntry: () => ensureWorklogEntry,
4273
4053
  extractNextUp: () => extractNextUp,
4274
4054
  extractOpenTasks: () => extractOpenTasks,
4055
+ failureReportSlice: () => failureReportSlice,
4056
+ findControlChar: () => findControlChar,
4057
+ formatTokens: () => formatTokens,
4058
+ formatWindow: () => formatWindow,
4275
4059
  gapWindowSinceArg: () => gapWindowSinceArg,
4276
4060
  globalMemoryPath: () => globalMemoryPath,
4277
4061
  globalSettingsHasHook: () => globalSettingsHasHook,
4278
4062
  globalSettingsPath: () => globalSettingsPath,
4279
4063
  globalStatePath: () => globalStatePath,
4064
+ guardWriteDecision: () => guardWriteDecision,
4280
4065
  handoffCommand: () => handoffCommand,
4281
4066
  inspectGlobalSetup: () => inspectGlobalSetup,
4282
4067
  inspectOwnership: () => inspectOwnership,
4283
4068
  isInstanceRoot: () => isInstanceRoot,
4284
4069
  isNewer: () => isNewer,
4285
4070
  isStableUpdate: () => isStableUpdate,
4071
+ isValidFailureKey: () => isValidFailureKey,
4072
+ ladderStage: () => ladderStage,
4286
4073
  logCommand: () => logCommand,
4074
+ makeBar: () => makeBar,
4287
4075
  ownershipManifestPath: () => ownershipManifestPath,
4288
4076
  parseAdoptArgs: () => parseAdoptArgs,
4289
4077
  parseSettings: () => parseSettings,
4078
+ parseStatuslineInput: () => parseStatuslineInput,
4290
4079
  pruneHandoffs: () => pruneHandoffs,
4291
4080
  queryNpmLatest: () => queryNpmLatest,
4292
4081
  readGlobalInstancePointer: () => readGlobalInstancePointer,
4293
4082
  readInstalledBaseVersion: () => readInstalledBaseVersion,
4294
4083
  recallCommand: () => recallCommand,
4084
+ recordFailure: () => recordFailure,
4295
4085
  recordGlobalSetupDecline: () => recordGlobalSetupDecline,
4086
+ recordGuardDenial: () => recordGuardDenial,
4296
4087
  reindexCommand: () => reindexCommand,
4297
4088
  renderAgenda: () => renderAgenda,
4298
4089
  renderGlobalBlock: () => renderGlobalBlock,
4299
4090
  renderSessionStartReport: () => renderSessionStartReport,
4091
+ renderStatusline: () => renderStatusline,
4300
4092
  repairOwnershipManifest: () => repairOwnershipManifest,
4093
+ resolveInstanceRoot: () => resolveInstanceRoot,
4301
4094
  resolveRepoRoot: () => resolveRepoRoot,
4302
4095
  runCurateAccept: () => runCurateAccept,
4303
4096
  runCurateCandidates: () => runCurateCandidates,
4304
4097
  runCurateDecline: () => runCurateDecline,
4305
4098
  runCuratePreview: () => runCuratePreview,
4099
+ runFailureCli: () => runFailureCli,
4100
+ runGuardCli: () => runGuardCli,
4101
+ runStatuslineCli: () => runStatuslineCli,
4306
4102
  runTemplatesUpdate: () => runTemplatesUpdate,
4307
4103
  runVortexCli: () => runVortexCli,
4104
+ safeSegment: () => safeSegment,
4105
+ scanFailures: () => scanFailures,
4308
4106
  scanHandoffs: () => scanHandoffs,
4107
+ scanToolInput: () => scanToolInput,
4309
4108
  serializeSettings: () => serializeSettings,
4310
4109
  sessionStartCommand: () => sessionStartCommand,
4110
+ sniffEffortFromTranscript: () => sniffEffortFromTranscript,
4111
+ statuslineCommand: () => statuslineCommand,
4311
4112
  templateDestRelPath: () => templateDestRelPath,
4312
4113
  upsertGlobalBlock: () => upsertGlobalBlock,
4313
4114
  validateCuratePayload: () => validateCuratePayload,
@@ -4417,7 +4218,7 @@ function curateCommand(options) {
4417
4218
  }
4418
4219
 
4419
4220
  // ../plugins/session-rituals/dist/commands/recall.js
4420
- import { join as join19 } from "path";
4221
+ import { join as join17 } from "path";
4421
4222
  function asMode(s) {
4422
4223
  return s === "keyword" || s === "semantic" || s === "hybrid" ? s : void 0;
4423
4224
  }
@@ -4453,7 +4254,7 @@ function parseRecallArgs(rest, defaultK) {
4453
4254
  return out;
4454
4255
  }
4455
4256
  function defaultDbPath(ctx) {
4456
- return join19(ctx.dataDir, "_indexes", "memory.sqlite");
4257
+ return join17(ctx.dataDir, "_indexes", "memory.sqlite");
4457
4258
  }
4458
4259
  function recallCommand(options) {
4459
4260
  const defaultK = options.defaultK ?? 5;
@@ -4511,9 +4312,9 @@ function recallCommand(options) {
4511
4312
  }
4512
4313
 
4513
4314
  // ../plugins/session-rituals/dist/commands/decision.js
4514
- import { writeFile as writeFile8 } from "fs/promises";
4515
- import { join as join20 } from "path";
4516
- import { existsSync as existsSync6 } from "fs";
4315
+ import { writeFile as writeFile7 } from "fs/promises";
4316
+ import { join as join18 } from "path";
4317
+ import { existsSync as existsSync5 } from "fs";
4517
4318
  var decisionCommand = {
4518
4319
  name: "decision",
4519
4320
  description: "Create a new Decision Log entry from the canonical template at `data/decision-log/<today>-<slug>.md`. Refuses to overwrite an existing file.",
@@ -4531,14 +4332,14 @@ var decisionCommand = {
4531
4332
  throw new Error("`/decision` requires a title after the slug.");
4532
4333
  }
4533
4334
  const date = todayIso();
4534
- const dir = join20(input.context.dataDir, "decision-log");
4335
+ const dir = join18(input.context.dataDir, "decision-log");
4535
4336
  const store = new DecisionStore(dir);
4536
4337
  const path = store.pathFor(date, slug);
4537
- if (existsSync6(path)) {
4338
+ if (existsSync5(path)) {
4538
4339
  throw new Error(`Refusing to overwrite existing entry: ${path}`);
4539
4340
  }
4540
4341
  const body = renderTemplate({ date, slug, title });
4541
- await writeFile8(path, body, "utf8");
4342
+ await writeFile7(path, body, "utf8");
4542
4343
  return { path, date, slug };
4543
4344
  }
4544
4345
  };
@@ -4558,9 +4359,9 @@ function todayIso() {
4558
4359
  }
4559
4360
 
4560
4361
  // ../plugins/session-rituals/dist/commands/reindex.js
4561
- import { existsSync as existsSync7 } from "fs";
4562
- import { readFile as readFile17, writeFile as writeFile9, utimes } from "fs/promises";
4563
- import { join as join21 } from "path";
4362
+ import { existsSync as existsSync6 } from "fs";
4363
+ import { readFile as readFile17, writeFile as writeFile8, utimes } from "fs/promises";
4364
+ import { join as join19 } from "path";
4564
4365
  var TARGETS = [
4565
4366
  {
4566
4367
  dir: "_memory",
@@ -4670,8 +4471,8 @@ var reindexCommand = {
4670
4471
  }
4671
4472
  const results = [];
4672
4473
  for (const t of targets) {
4673
- const dir = join21(input.context.dataDir, t.dir);
4674
- if (!existsSync7(dir)) {
4474
+ const dir = join19(input.context.dataDir, t.dir);
4475
+ if (!existsSync6(dir)) {
4675
4476
  results.push({ dir: t.dir, status: "missing", entries: 0, bytes: 0 });
4676
4477
  continue;
4677
4478
  }
@@ -4686,7 +4487,7 @@ var reindexCommand = {
4686
4487
  entries,
4687
4488
  privacy: t.privacy
4688
4489
  });
4689
- const target = join21(dir, "_INDEX.md");
4490
+ const target = join19(dir, "_INDEX.md");
4690
4491
  let existing;
4691
4492
  try {
4692
4493
  existing = await readFile17(target, "utf8");
@@ -4702,7 +4503,7 @@ var reindexCommand = {
4702
4503
  });
4703
4504
  continue;
4704
4505
  }
4705
- await writeFile9(target, body, "utf8");
4506
+ await writeFile8(target, body, "utf8");
4706
4507
  results.push({
4707
4508
  dir: t.dir,
4708
4509
  status: "written",
@@ -4718,8 +4519,8 @@ async function autoReindexMemory(ctx) {
4718
4519
  const target = TARGETS.find((t) => t.dir === "_memory");
4719
4520
  if (!target)
4720
4521
  return "missing";
4721
- const dir = join21(ctx.dataDir, target.dir);
4722
- if (!existsSync7(dir))
4522
+ const dir = join19(ctx.dataDir, target.dir);
4523
+ if (!existsSync6(dir))
4723
4524
  return "missing";
4724
4525
  const entries = await scanDirectory(dir, {
4725
4526
  recursive: target.recursive,
@@ -4732,7 +4533,7 @@ async function autoReindexMemory(ctx) {
4732
4533
  entries,
4733
4534
  privacy: target.privacy
4734
4535
  });
4735
- const indexPath = join21(dir, "_INDEX.md");
4536
+ const indexPath = join19(dir, "_INDEX.md");
4736
4537
  let existing;
4737
4538
  try {
4738
4539
  existing = await readFile17(indexPath, "utf8");
@@ -4744,10 +4545,10 @@ async function autoReindexMemory(ctx) {
4744
4545
  if (sameListing) {
4745
4546
  status = "unchanged";
4746
4547
  } else {
4747
- await writeFile9(indexPath, body, "utf8");
4548
+ await writeFile8(indexPath, body, "utf8");
4748
4549
  status = "written";
4749
4550
  }
4750
- if (existsSync7(indexPath)) {
4551
+ if (existsSync6(indexPath)) {
4751
4552
  const now = /* @__PURE__ */ new Date();
4752
4553
  await utimes(indexPath, now, now);
4753
4554
  }
@@ -4761,9 +4562,9 @@ function stripIndexDate(body) {
4761
4562
  }
4762
4563
 
4763
4564
  // ../plugins/session-rituals/dist/commands/session-start.js
4764
- import { existsSync as existsSync8 } from "fs";
4565
+ import { existsSync as existsSync7 } from "fs";
4765
4566
  import { readdir as readdir14 } from "fs/promises";
4766
- import { join as join22 } from "path";
4567
+ import { join as join20 } from "path";
4767
4568
  var COUNTED_DIRS = ["_memory", "worklog", "decision-log"];
4768
4569
  var sessionStartCommand = {
4769
4570
  name: "session-start",
@@ -4773,8 +4574,8 @@ var sessionStartCommand = {
4773
4574
  const counts = {};
4774
4575
  const missing = [];
4775
4576
  for (const name of COUNTED_DIRS) {
4776
- const dir = join22(dataDir, name);
4777
- if (!existsSync8(dir)) {
4577
+ const dir = join20(dataDir, name);
4578
+ if (!existsSync7(dir)) {
4778
4579
  missing.push(name);
4779
4580
  counts[name] = 0;
4780
4581
  continue;
@@ -4806,7 +4607,7 @@ async function countMarkdown(dir, recursive) {
4806
4607
  } else if (e.isDirectory() && recursive) {
4807
4608
  if (e.name.startsWith(".") || e.name.startsWith("_"))
4808
4609
  continue;
4809
- total += await countMarkdown(join22(dir, e.name), recursive);
4610
+ total += await countMarkdown(join20(dir, e.name), recursive);
4810
4611
  }
4811
4612
  }
4812
4613
  return total;
@@ -4852,9 +4653,9 @@ function todayIso2() {
4852
4653
  }
4853
4654
 
4854
4655
  // ../plugins/session-rituals/dist/handoff.js
4855
- import { existsSync as existsSync9 } from "fs";
4856
- import { mkdir as mkdir6, open, readdir as readdir15, readFile as readFile18, rename as rename2, stat as stat7 } from "fs/promises";
4857
- import { join as join23 } from "path";
4656
+ import { existsSync as existsSync8 } from "fs";
4657
+ import { mkdir as mkdir6, open, readdir as readdir15, readFile as readFile18, rename, stat as stat7 } from "fs/promises";
4658
+ import { join as join21 } from "path";
4858
4659
 
4859
4660
  // ../plugins/session-rituals/dist/agenda.js
4860
4661
  var DEFAULT_RECENT = 7;
@@ -5052,7 +4853,7 @@ async function createHandoffSkeleton(dataDir, opts) {
5052
4853
  const now = opts?.now ?? /* @__PURE__ */ new Date();
5053
4854
  const date = isoDate(now);
5054
4855
  const time = isoTime(now);
5055
- const dir = join23(dataDir, HANDOFF_DIR);
4856
+ const dir = join21(dataDir, HANDOFF_DIR);
5056
4857
  await mkdir6(dir, { recursive: true });
5057
4858
  const stamp = `${date} ${time.slice(0, 2)}:${time.slice(2)}`;
5058
4859
  const title = (opts?.title ?? "").trim();
@@ -5060,7 +4861,7 @@ async function createHandoffSkeleton(dataDir, opts) {
5060
4861
  const base = `${date}_${time}`;
5061
4862
  for (let i = 0; i < MAX_COLLISION_TRIES; i++) {
5062
4863
  const name = i === 0 ? `${base}.md` : `${base}-${i + 1}.md`;
5063
- const abs = join23(dir, name);
4864
+ const abs = join21(dir, name);
5064
4865
  try {
5065
4866
  const fh = await open(abs, "wx");
5066
4867
  try {
@@ -5094,8 +4895,8 @@ ${heading}
5094
4895
  `;
5095
4896
  }
5096
4897
  async function scanHandoffs(dataDir, opts) {
5097
- const dir = join23(dataDir, HANDOFF_DIR);
5098
- if (!existsSync9(dir))
4898
+ const dir = join21(dataDir, HANDOFF_DIR);
4899
+ if (!existsSync8(dir))
5099
4900
  return { active: [], omitted: 0 };
5100
4901
  let names;
5101
4902
  try {
@@ -5109,7 +4910,7 @@ async function scanHandoffs(dataDir, opts) {
5109
4910
  const omitted = Math.max(0, matched.length - take.length);
5110
4911
  const active = [];
5111
4912
  for (const { name, m: m2 } of take) {
5112
- const abs = join23(dir, name);
4913
+ const abs = join21(dir, name);
5113
4914
  let title = name.replace(/\.md$/, "");
5114
4915
  let nextUp = [];
5115
4916
  try {
@@ -5129,8 +4930,8 @@ async function scanHandoffs(dataDir, opts) {
5129
4930
  async function pruneHandoffs(dataDir, opts) {
5130
4931
  const now = opts.now ?? /* @__PURE__ */ new Date();
5131
4932
  const retentionDays = opts.retentionDays;
5132
- const dir = join23(dataDir, HANDOFF_DIR);
5133
- if (!existsSync9(dir) || !(retentionDays > 0))
4933
+ const dir = join21(dataDir, HANDOFF_DIR);
4934
+ if (!existsSync8(dir) || !(retentionDays > 0))
5134
4935
  return { archived: 0 };
5135
4936
  let names;
5136
4937
  try {
@@ -5142,21 +4943,21 @@ async function pruneHandoffs(dataDir, opts) {
5142
4943
  const stale = names.map((name) => ({ name, m: name.match(HANDOFF_PATTERN) })).filter((x2) => x2.m !== null && x2.m[1] < cutoff);
5143
4944
  if (stale.length === 0)
5144
4945
  return { archived: 0 };
5145
- const archiveDir = join23(dir, HANDOFF_ARCHIVE_DIR);
4946
+ const archiveDir = join21(dir, HANDOFF_ARCHIVE_DIR);
5146
4947
  await mkdir6(archiveDir, { recursive: true });
5147
4948
  let archived = 0;
5148
4949
  for (const { name } of stale) {
5149
- const from = join23(dir, name);
5150
- let to = join23(archiveDir, name);
5151
- if (existsSync9(to)) {
4950
+ const from = join21(dir, name);
4951
+ let to = join21(archiveDir, name);
4952
+ if (existsSync8(to)) {
5152
4953
  const stem = name.replace(/\.md$/, "");
5153
4954
  let i = 2;
5154
- while (existsSync9(join23(archiveDir, `${stem}-${i}.md`)))
4955
+ while (existsSync8(join21(archiveDir, `${stem}-${i}.md`)))
5155
4956
  i++;
5156
- to = join23(archiveDir, `${stem}-${i}.md`);
4957
+ to = join21(archiveDir, `${stem}-${i}.md`);
5157
4958
  }
5158
4959
  try {
5159
- await rename2(from, to);
4960
+ await rename(from, to);
5160
4961
  archived++;
5161
4962
  } catch {
5162
4963
  }
@@ -5204,94 +5005,16 @@ var handoffCommand = {
5204
5005
 
5205
5006
  // ../plugins/session-rituals/dist/commands/vortex.js
5206
5007
  import { spawn } from "child_process";
5207
- import { constants, existsSync as existsSync12 } from "fs";
5208
- import { copyFile as copyFile2, mkdir as mkdir9, readdir as readdir16, readFile as readFile21, stat as stat8, writeFile as writeFile11 } from "fs/promises";
5209
- import { basename as basename7, dirname as dirname5, extname as extname11, join as join26, relative as relative5 } from "path";
5008
+ import { constants, existsSync as existsSync11 } from "fs";
5009
+ import { copyFile as copyFile2, mkdir as mkdir9, readdir as readdir16, readFile as readFile21, stat as stat8, writeFile as writeFile10 } from "fs/promises";
5010
+ import { basename as basename7, dirname as dirname5, extname as extname11, join as join24, relative as relative4 } from "path";
5210
5011
  import { fileURLToPath } from "url";
5211
5012
 
5212
- // ../plugins/session-rituals/dist/ensure-hooks.js
5213
- var SESSION_START_COMMAND = "npx --no-install vortex session-start || exit 0";
5214
- var SESSION_END_COMMAND = "npx --no-install vortex session-end || exit 0";
5215
- var LEGACY_COMMANDS = {
5216
- SessionStart: [
5217
- "npx --no-install -p @vortex-os/base vortex session-start || exit 0",
5218
- "npx --no-install -p @vortex-os/base vortex session-start"
5219
- ],
5220
- SessionEnd: [
5221
- "npx --no-install -p @vortex-os/base vortex session-end || exit 0",
5222
- "npx --no-install -p @vortex-os/base vortex session-end"
5223
- ]
5224
- };
5225
- function parseSettings(text) {
5226
- const trimmed = (text ?? "").trim();
5227
- if (trimmed.length === 0)
5228
- return {};
5229
- let parsed;
5230
- try {
5231
- parsed = JSON.parse(trimmed);
5232
- } catch (e) {
5233
- throw new Error(`.claude/settings.json is not valid JSON \u2014 refusing to overwrite. Fix or remove it first. (${e.message})`);
5234
- }
5235
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
5236
- throw new Error(".claude/settings.json is not a JSON object \u2014 refusing to overwrite.");
5237
- }
5238
- return parsed;
5239
- }
5240
- function ensureVortexHooks(existing) {
5241
- const base = existing && typeof existing === "object" ? existing : {};
5242
- const hooks = { ...base.hooks ?? {} };
5243
- const added = [];
5244
- const wire = (event, command) => {
5245
- const legacy = LEGACY_COMMANDS[event];
5246
- const src = hooks[event] ?? [];
5247
- let changed = false;
5248
- let kept = false;
5249
- const groups = [];
5250
- for (const g of src) {
5251
- const hookList = [];
5252
- for (const h of g.hooks ?? []) {
5253
- const migrated = legacy.includes(h.command);
5254
- const cmd = migrated ? command : h.command;
5255
- if (cmd === command) {
5256
- if (kept) {
5257
- changed = true;
5258
- continue;
5259
- }
5260
- kept = true;
5261
- if (migrated)
5262
- changed = true;
5263
- hookList.push(migrated ? { ...h, command } : h);
5264
- } else {
5265
- hookList.push(h);
5266
- }
5267
- }
5268
- if (hookList.length > 0)
5269
- groups.push({ ...g, hooks: hookList });
5270
- else
5271
- changed = true;
5272
- }
5273
- if (!kept) {
5274
- groups.push({ hooks: [{ type: "command", command }] });
5275
- changed = true;
5276
- }
5277
- hooks[event] = groups;
5278
- if (changed)
5279
- added.push(event);
5280
- };
5281
- wire("SessionStart", SESSION_START_COMMAND);
5282
- wire("SessionEnd", SESSION_END_COMMAND);
5283
- const settings = { ...base, hooks };
5284
- return { settings, added, alreadyWired: added.length === 0 };
5285
- }
5286
- function serializeSettings(settings) {
5287
- return JSON.stringify(settings, null, 2) + "\n";
5288
- }
5289
-
5290
5013
  // ../plugins/session-rituals/dist/global-setup.js
5291
5014
  import { homedir } from "os";
5292
- import { existsSync as existsSync10, readFileSync as readFileSync2 } from "fs";
5293
- import { mkdir as mkdir7, readFile as readFile19, writeFile as writeFile10 } from "fs/promises";
5294
- import { isAbsolute as isAbsolute3, join as join24 } from "path";
5015
+ import { existsSync as existsSync9, readFileSync } from "fs";
5016
+ import { mkdir as mkdir7, readFile as readFile19, writeFile as writeFile9 } from "fs/promises";
5017
+ import { isAbsolute as isAbsolute2, join as join22 } from "path";
5295
5018
  async function readFileIfExists(path) {
5296
5019
  try {
5297
5020
  return await readFile19(path, "utf8");
@@ -5302,23 +5025,23 @@ async function readFileIfExists(path) {
5302
5025
  }
5303
5026
  }
5304
5027
  function isSafeInstanceRoot(dir) {
5305
- return typeof dir === "string" && dir.trim().length > 0 && isAbsolute3(dir) && !/[\r\n`]/.test(dir) && isInstanceRoot(dir);
5028
+ return typeof dir === "string" && dir.trim().length > 0 && isAbsolute2(dir) && !/[\r\n`]/.test(dir) && isInstanceRoot(dir);
5306
5029
  }
5307
5030
  function globalClaudeDir(home = homedir()) {
5308
- return join24(home, ".claude");
5031
+ return join22(home, ".claude");
5309
5032
  }
5310
5033
  function globalSettingsPath(home = homedir()) {
5311
- return join24(globalClaudeDir(home), "settings.json");
5034
+ return join22(globalClaudeDir(home), "settings.json");
5312
5035
  }
5313
5036
  function globalStatePath(home = homedir()) {
5314
- return join24(globalClaudeDir(home), "vortex-global.json");
5037
+ return join22(globalClaudeDir(home), "vortex-global.json");
5315
5038
  }
5316
5039
  function globalMemoryPath(home = homedir()) {
5317
- return join24(globalClaudeDir(home), "CLAUDE.md");
5040
+ return join22(globalClaudeDir(home), "CLAUDE.md");
5318
5041
  }
5319
5042
  function readGlobalStateRaw(home = homedir()) {
5320
5043
  try {
5321
- const parsed = JSON.parse(readFileSync2(globalStatePath(home), "utf8"));
5044
+ const parsed = JSON.parse(readFileSync(globalStatePath(home), "utf8"));
5322
5045
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
5323
5046
  return parsed;
5324
5047
  }
@@ -5331,11 +5054,11 @@ function readGlobalInstancePointer(home = homedir()) {
5331
5054
  return typeof root === "string" && root.trim().length > 0 ? root.trim() : null;
5332
5055
  }
5333
5056
  function isInstanceRoot(dir) {
5334
- return existsSync10(join24(dir, ".agent", "vortex.json")) || existsSync10(join24(dir, "data", "_memory", "user_profile.md"));
5057
+ return existsSync9(join22(dir, ".agent", "vortex.json")) || existsSync9(join22(dir, "data", "_memory", "user_profile.md"));
5335
5058
  }
5336
5059
  function globalSettingsHasHook(home = homedir()) {
5337
5060
  try {
5338
- const settings = parseSettings(readFileSync2(globalSettingsPath(home), "utf8"));
5061
+ const settings = parseSettings(readFileSync(globalSettingsPath(home), "utf8"));
5339
5062
  const wired = (event, command) => Boolean(settings.hooks?.[event]?.some((g) => g.hooks?.some((h) => h.command === command)));
5340
5063
  return wired("SessionStart", SESSION_START_COMMAND) && wired("SessionEnd", SESSION_END_COMMAND);
5341
5064
  } catch {
@@ -5379,9 +5102,9 @@ async function applyGlobalSetup(opts) {
5379
5102
  const skipped = [];
5380
5103
  const statePath = globalStatePath(home);
5381
5104
  const settingsPath = globalSettingsPath(home);
5382
- const instSettingsPath = join24(instanceRoot, ".claude", "settings.json");
5105
+ const instSettingsPath = join22(instanceRoot, ".claude", "settings.json");
5383
5106
  const mdPath = globalMemoryPath(home);
5384
- const hadState = existsSync10(statePath);
5107
+ const hadState = existsSync9(statePath);
5385
5108
  const prevState = readGlobalStateRaw(home) ?? {};
5386
5109
  const settingsText = await readFileIfExists(settingsPath);
5387
5110
  const mergedGlobal = ensureVortexHooks(parseSettings(settingsText));
@@ -5394,27 +5117,27 @@ async function applyGlobalSetup(opts) {
5394
5117
  const { declinedAt: _wasDeclined, ...restState } = prevState;
5395
5118
  const nextState = { ...restState, instanceRoot };
5396
5119
  if (!hadState || prevState.instanceRoot !== instanceRoot || typeof prevState.declinedAt === "string") {
5397
- await writeFile10(statePath, JSON.stringify(nextState, null, 2) + "\n", "utf8");
5120
+ await writeFile9(statePath, JSON.stringify(nextState, null, 2) + "\n", "utf8");
5398
5121
  (hadState ? modified : created).push(statePath);
5399
5122
  } else {
5400
5123
  skipped.push(statePath);
5401
5124
  }
5402
5125
  if (!mergedGlobal.alreadyWired) {
5403
- await writeFile10(settingsPath, serializeSettings(mergedGlobal.settings), "utf8");
5126
+ await writeFile9(settingsPath, serializeSettings(mergedGlobal.settings), "utf8");
5404
5127
  (settingsText === null ? created : modified).push(settingsPath);
5405
5128
  } else {
5406
5129
  skipped.push(settingsPath);
5407
5130
  }
5408
5131
  if (mergedInst !== null) {
5409
5132
  if (!mergedInst.alreadyWired) {
5410
- await writeFile10(instSettingsPath, serializeSettings(mergedInst.settings), "utf8");
5133
+ await writeFile9(instSettingsPath, serializeSettings(mergedInst.settings), "utf8");
5411
5134
  modified.push(instSettingsPath);
5412
5135
  } else {
5413
5136
  skipped.push(instSettingsPath);
5414
5137
  }
5415
5138
  }
5416
5139
  if (nextMd !== mdText) {
5417
- await writeFile10(mdPath, nextMd, "utf8");
5140
+ await writeFile9(mdPath, nextMd, "utf8");
5418
5141
  (mdRead === null ? created : modified).push(mdPath);
5419
5142
  } else {
5420
5143
  skipped.push(mdPath);
@@ -5428,23 +5151,23 @@ async function recordGlobalSetupDecline(opts) {
5428
5151
  const statePath = globalStatePath(home);
5429
5152
  const prevState = readGlobalStateRaw(home) ?? {};
5430
5153
  const nextState = { ...prevState, declinedAt: now.toISOString() };
5431
- await writeFile10(statePath, JSON.stringify(nextState, null, 2) + "\n", "utf8");
5154
+ await writeFile9(statePath, JSON.stringify(nextState, null, 2) + "\n", "utf8");
5432
5155
  return statePath;
5433
5156
  }
5434
5157
 
5435
5158
  // ../plugins/session-rituals/dist/update.js
5436
5159
  import { createHash as createHash2 } from "crypto";
5437
- import { existsSync as existsSync11 } from "fs";
5160
+ import { existsSync as existsSync10 } from "fs";
5438
5161
  import { copyFile, mkdir as mkdir8, readFile as readFile20 } from "fs/promises";
5439
- import { dirname as dirname4, isAbsolute as isAbsolute4, join as join25, relative as relative4, sep as sep4 } from "path";
5162
+ import { dirname as dirname4, isAbsolute as isAbsolute3, join as join23, relative as relative3, sep as sep3 } from "path";
5440
5163
  var OWNERSHIP_SCHEMA = "vortex-ownership/2";
5441
5164
  var OWNERSHIP_SCHEMA_V1 = "vortex-ownership/1";
5442
5165
  var MANIFEST_NAME = "manifest.json";
5443
5166
  function ownershipManifestPath(ctx) {
5444
- return join25(ctx.dataDir, ".vortex", "ownership.json");
5167
+ return join23(ctx.dataDir, ".vortex", "ownership.json");
5445
5168
  }
5446
5169
  function frameworkBookkeepingPrefix(ctx) {
5447
- return toPosix(relative4(ctx.repoRoot, join25(ctx.dataDir, ".vortex"))) + "/";
5170
+ return toPosix(relative3(ctx.repoRoot, join23(ctx.dataDir, ".vortex"))) + "/";
5448
5171
  }
5449
5172
  function committableUpdatePaths(ctx, result) {
5450
5173
  const out = /* @__PURE__ */ new Set();
@@ -5455,11 +5178,11 @@ function committableUpdatePaths(ctx, result) {
5455
5178
  out.add(a.path);
5456
5179
  }
5457
5180
  }
5458
- out.add(toPosix(relative4(ctx.repoRoot, ownershipManifestPath(ctx))));
5181
+ out.add(toPosix(relative3(ctx.repoRoot, ownershipManifestPath(ctx))));
5459
5182
  return [...out];
5460
5183
  }
5461
5184
  function toPosix(p) {
5462
- return p.split(sep4).join("/");
5185
+ return p.split(sep3).join("/");
5463
5186
  }
5464
5187
  function normalizeEol(input) {
5465
5188
  const s = typeof input === "string" ? input : input.toString("utf8");
@@ -5490,24 +5213,24 @@ function templateDestRelPath(templateRelPath) {
5490
5213
  if (top === "routers")
5491
5214
  return tail;
5492
5215
  if (top === "commands")
5493
- return join25(".claude", "commands", tail);
5216
+ return join23(".claude", "commands", tail);
5494
5217
  if (top === "config")
5495
- return join25(".agent", tail);
5218
+ return join23(".agent", tail);
5496
5219
  return null;
5497
5220
  }
5498
5221
  function assertUnderRoot(rootAbs, candidateAbs) {
5499
- const rel = relative4(rootAbs, candidateAbs);
5500
- const up = ".." + sep4;
5501
- const winsensitive = sep4 === "\\";
5222
+ const rel = relative3(rootAbs, candidateAbs);
5223
+ const up = ".." + sep3;
5224
+ const winsensitive = sep3 === "\\";
5502
5225
  const cmp = winsensitive ? rel.toLowerCase() : rel;
5503
5226
  const upCmp = winsensitive ? up.toLowerCase() : up;
5504
- if (rel === ".." || cmp.startsWith(upCmp) || isAbsolute4(rel)) {
5227
+ if (rel === ".." || cmp.startsWith(upCmp) || isAbsolute3(rel)) {
5505
5228
  throw new Error(`Refusing to write outside the instance root: ${candidateAbs}`);
5506
5229
  }
5507
5230
  }
5508
5231
  async function readTemplateIndex(templatesDir) {
5509
- const indexPath = join25(templatesDir, MANIFEST_NAME);
5510
- if (!existsSync11(indexPath))
5232
+ const indexPath = join23(templatesDir, MANIFEST_NAME);
5233
+ if (!existsSync10(indexPath))
5511
5234
  return null;
5512
5235
  try {
5513
5236
  const parsed = JSON.parse(await readFile20(indexPath, "utf8"));
@@ -5531,14 +5254,14 @@ async function buildOwnershipManifest(ctx, templatesDir) {
5531
5254
  if (seenDest.has(destRel))
5532
5255
  continue;
5533
5256
  seenDest.add(destRel);
5534
- const shippedAbs = join25(templatesDir, entry.path);
5535
- if (!existsSync11(shippedAbs))
5257
+ const shippedAbs = join23(templatesDir, entry.path);
5258
+ if (!existsSync10(shippedAbs))
5536
5259
  continue;
5537
5260
  const sourceSha256 = await sha256File(shippedAbs);
5538
- const destAbs = join25(ctx.repoRoot, destRel);
5261
+ const destAbs = join23(ctx.repoRoot, destRel);
5539
5262
  assertUnderRoot(ctx.repoRoot, destAbs);
5540
5263
  let installedSha256 = null;
5541
- if (existsSync11(destAbs)) {
5264
+ if (existsSync10(destAbs)) {
5542
5265
  const onDisk = await sha256File(destAbs);
5543
5266
  installedSha256 = onDisk === sourceSha256 ? sourceSha256 : null;
5544
5267
  }
@@ -5559,14 +5282,14 @@ async function writeOwnershipManifest(ctx, templatesDir) {
5559
5282
  if (!manifest)
5560
5283
  return null;
5561
5284
  const mp = ownershipManifestPath(ctx);
5562
- await mkdir8(join25(ctx.dataDir, ".vortex"), { recursive: true });
5285
+ await mkdir8(join23(ctx.dataDir, ".vortex"), { recursive: true });
5563
5286
  await atomicWriteFile(mp, JSON.stringify(manifest, null, 2) + "\n");
5564
5287
  return { path: mp, fileCount: manifest.files.length };
5565
5288
  }
5566
5289
  async function inspectOwnership(ctx, templatesDir) {
5567
5290
  let own = await readOwnershipManifest(ctx);
5568
5291
  if (!own) {
5569
- const malformed = existsSync11(ownershipManifestPath(ctx));
5292
+ const malformed = existsSync10(ownershipManifestPath(ctx));
5570
5293
  return { present: false, malformed, total: 0, pristine: 0, modified: 0, missing: 0, unmanaged: 0 };
5571
5294
  }
5572
5295
  if (templatesDir && own.schema === OWNERSHIP_SCHEMA_V1) {
@@ -5581,8 +5304,8 @@ async function inspectOwnership(ctx, templatesDir) {
5581
5304
  unmanaged++;
5582
5305
  continue;
5583
5306
  }
5584
- const abs = join25(ctx.repoRoot, e.path);
5585
- if (!existsSync11(abs)) {
5307
+ const abs = join23(ctx.repoRoot, e.path);
5308
+ if (!existsSync10(abs)) {
5586
5309
  missing++;
5587
5310
  continue;
5588
5311
  }
@@ -5599,7 +5322,7 @@ async function inspectOwnership(ctx, templatesDir) {
5599
5322
  }
5600
5323
  async function repairOwnershipManifest(ctx, templatesDir) {
5601
5324
  const mp = ownershipManifestPath(ctx);
5602
- if (existsSync11(mp)) {
5325
+ if (existsSync10(mp)) {
5603
5326
  const existing = await readOwnershipManifest(ctx);
5604
5327
  return existing ? { status: "already-present", path: mp, fileCount: existing.files.length } : { status: "unreadable", path: mp };
5605
5328
  }
@@ -5608,7 +5331,7 @@ async function repairOwnershipManifest(ctx, templatesDir) {
5608
5331
  }
5609
5332
  async function readOwnershipManifest(ctx) {
5610
5333
  const mp = ownershipManifestPath(ctx);
5611
- if (!existsSync11(mp))
5334
+ if (!existsSync10(mp))
5612
5335
  return null;
5613
5336
  try {
5614
5337
  const parsed = JSON.parse(await readFile20(mp, "utf8"));
@@ -5632,13 +5355,13 @@ async function migrateOwnershipToV2(own, ctx, templatesDir) {
5632
5355
  if (index) {
5633
5356
  for (const idx of index.files) {
5634
5357
  if (templateDestRelPath(idx.path))
5635
- tmplAbsById.set(idx.templateId, join25(templatesDir, idx.path));
5358
+ tmplAbsById.set(idx.templateId, join23(templatesDir, idx.path));
5636
5359
  }
5637
5360
  }
5638
5361
  const files = [];
5639
5362
  for (const e of own.files) {
5640
5363
  const tmplAbs = tmplAbsById.get(e.templateId);
5641
- if (!tmplAbs || !existsSync11(tmplAbs)) {
5364
+ if (!tmplAbs || !existsSync10(tmplAbs)) {
5642
5365
  files.push(e);
5643
5366
  continue;
5644
5367
  }
@@ -5649,10 +5372,10 @@ async function migrateOwnershipToV2(own, ctx, templatesDir) {
5649
5372
  continue;
5650
5373
  }
5651
5374
  const srcUnchanged = matchesLegacyRawHash(e.sourceSha256, tmplBuf);
5652
- const destAbs = join25(ctx.repoRoot, e.path);
5375
+ const destAbs = join23(ctx.repoRoot, e.path);
5653
5376
  let diskPristine = false;
5654
5377
  let normDisk = null;
5655
- if (existsSync11(destAbs)) {
5378
+ if (existsSync10(destAbs)) {
5656
5379
  try {
5657
5380
  const diskBuf = await readFile20(destAbs);
5658
5381
  normDisk = sha256(diskBuf);
@@ -5721,15 +5444,15 @@ async function runTemplatesUpdate(ctx, templatesDir, options = {}) {
5721
5444
  continue;
5722
5445
  seenDest.add(destRel);
5723
5446
  seenTemplateIds.add(idx.templateId);
5724
- const shippedAbs = join25(templatesDir, idx.path);
5725
- if (!existsSync11(shippedAbs))
5447
+ const shippedAbs = join23(templatesDir, idx.path);
5448
+ if (!existsSync10(shippedAbs))
5726
5449
  continue;
5727
5450
  const newSource = await sha256File(shippedAbs);
5728
- const destAbs = join25(ctx.repoRoot, destRel);
5451
+ const destAbs = join23(ctx.repoRoot, destRel);
5729
5452
  assertUnderRoot(ctx.repoRoot, destAbs);
5730
5453
  const path = toPosix(destRel);
5731
5454
  const templateId = idx.templateId;
5732
- const exists = existsSync11(destAbs);
5455
+ const exists = existsSync10(destAbs);
5733
5456
  const curHash = exists ? await sha256File(destAbs) : null;
5734
5457
  const prior = ownByTemplateId.get(templateId);
5735
5458
  if (adopt.has(path)) {
@@ -5772,7 +5495,7 @@ async function runTemplatesUpdate(ctx, templatesDir, options = {}) {
5772
5495
  templateId,
5773
5496
  action: "conflict",
5774
5497
  detail: "a file already exists in a newly-shipped slot \u2014 wrote .new",
5775
- newFilePath: toPosix(relative4(ctx.repoRoot, destAbs + ".new"))
5498
+ newFilePath: toPosix(relative3(ctx.repoRoot, destAbs + ".new"))
5776
5499
  },
5777
5500
  shippedAbs,
5778
5501
  destAbs,
@@ -5830,7 +5553,7 @@ async function runTemplatesUpdate(ctx, templatesDir, options = {}) {
5830
5553
  templateId,
5831
5554
  action: "conflict",
5832
5555
  detail: "you edited this and the template changed \u2014 wrote .new; your file is untouched",
5833
- newFilePath: toPosix(relative4(ctx.repoRoot, destAbs + ".new"))
5556
+ newFilePath: toPosix(relative3(ctx.repoRoot, destAbs + ".new"))
5834
5557
  },
5835
5558
  shippedAbs,
5836
5559
  destAbs,
@@ -5852,18 +5575,18 @@ async function runTemplatesUpdate(ctx, templatesDir, options = {}) {
5852
5575
  const allOps = [...ops, ...orphanOps];
5853
5576
  const appliedActions = [];
5854
5577
  const finalEntries = [];
5855
- const backupRoot = join25(ctx.dataDir, ".vortex", "backups", (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
5578
+ const backupRoot = join23(ctx.dataDir, ".vortex", "backups", (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"));
5856
5579
  let applyError = false;
5857
5580
  const writeDotNew = async (destAbs, content) => {
5858
5581
  const newPath = destAbs + ".new";
5859
- if (existsSync11(newPath)) {
5582
+ if (existsSync10(newPath)) {
5860
5583
  if (await readFile20(newPath, "utf8") === content)
5861
5584
  return void 0;
5862
- const backupAbs = join25(backupRoot, toPosix(relative4(ctx.repoRoot, newPath)));
5585
+ const backupAbs = join23(backupRoot, toPosix(relative3(ctx.repoRoot, newPath)));
5863
5586
  await mkdir8(dirname4(backupAbs), { recursive: true });
5864
5587
  await copyFile(newPath, backupAbs);
5865
5588
  await atomicWriteFile(newPath, content);
5866
- return toPosix(relative4(ctx.repoRoot, backupAbs));
5589
+ return toPosix(relative3(ctx.repoRoot, backupAbs));
5867
5590
  }
5868
5591
  await atomicWriteFile(newPath, content);
5869
5592
  return void 0;
@@ -5878,15 +5601,15 @@ async function runTemplatesUpdate(ctx, templatesDir, options = {}) {
5878
5601
  const newSource = op.entry ? op.entry.sourceSha256 : sha256(content);
5879
5602
  if (action.action === "replace") {
5880
5603
  const prior = ownByTemplateId.get(action.templateId);
5881
- if (!existsSync11(destAbs)) {
5604
+ if (!existsSync10(destAbs)) {
5882
5605
  await mkdir8(dirname4(destAbs), { recursive: true });
5883
5606
  await atomicWriteFile(destAbs, content);
5884
5607
  } else if (await sha256File(destAbs) === (prior?.installedSha256 ?? null)) {
5885
- const backupAbs = join25(backupRoot, action.path);
5608
+ const backupAbs = join23(backupRoot, action.path);
5886
5609
  await mkdir8(dirname4(backupAbs), { recursive: true });
5887
5610
  await copyFile(destAbs, backupAbs);
5888
5611
  await atomicWriteFile(destAbs, content);
5889
- action = { ...action, backupPath: toPosix(relative4(ctx.repoRoot, backupAbs)) };
5612
+ action = { ...action, backupPath: toPosix(relative3(ctx.repoRoot, backupAbs)) };
5890
5613
  } else {
5891
5614
  const backupPath = await writeDotNew(destAbs, content);
5892
5615
  action = {
@@ -5894,20 +5617,20 @@ async function runTemplatesUpdate(ctx, templatesDir, options = {}) {
5894
5617
  templateId: action.templateId,
5895
5618
  action: "conflict",
5896
5619
  detail: "file changed since planning \u2014 wrote .new instead of overwriting",
5897
- newFilePath: toPosix(relative4(ctx.repoRoot, destAbs + ".new")),
5620
+ newFilePath: toPosix(relative3(ctx.repoRoot, destAbs + ".new")),
5898
5621
  ...backupPath ? { backupPath } : {}
5899
5622
  };
5900
5623
  entry = { templateId: action.templateId, path: action.path, sourceSha256: newSource, installedSha256: prior?.installedSha256 ?? null };
5901
5624
  }
5902
5625
  } else if (action.action === "restore" || action.action === "install") {
5903
- if (existsSync11(destAbs) && await sha256File(destAbs) !== newSource) {
5626
+ if (existsSync10(destAbs) && await sha256File(destAbs) !== newSource) {
5904
5627
  const backupPath = await writeDotNew(destAbs, content);
5905
5628
  action = {
5906
5629
  path: action.path,
5907
5630
  templateId: action.templateId,
5908
5631
  action: "conflict",
5909
5632
  detail: "target appeared since planning \u2014 wrote .new instead of overwriting",
5910
- newFilePath: toPosix(relative4(ctx.repoRoot, destAbs + ".new")),
5633
+ newFilePath: toPosix(relative3(ctx.repoRoot, destAbs + ".new")),
5911
5634
  ...backupPath ? { backupPath } : {}
5912
5635
  };
5913
5636
  entry = { templateId: action.templateId, path: action.path, sourceSha256: newSource, installedSha256: null };
@@ -5921,11 +5644,11 @@ async function runTemplatesUpdate(ctx, templatesDir, options = {}) {
5921
5644
  if (backupPath)
5922
5645
  action = { ...action, backupPath };
5923
5646
  } else if (action.action === "adopt") {
5924
- if (existsSync11(destAbs)) {
5925
- const backupAbs = join25(backupRoot, action.path);
5647
+ if (existsSync10(destAbs)) {
5648
+ const backupAbs = join23(backupRoot, action.path);
5926
5649
  await mkdir8(dirname4(backupAbs), { recursive: true });
5927
5650
  await copyFile(destAbs, backupAbs);
5928
- action = { ...action, backupPath: toPosix(relative4(ctx.repoRoot, backupAbs)) };
5651
+ action = { ...action, backupPath: toPosix(relative3(ctx.repoRoot, backupAbs)) };
5929
5652
  }
5930
5653
  await mkdir8(dirname4(destAbs), { recursive: true });
5931
5654
  await atomicWriteFile(destAbs, content);
@@ -5954,7 +5677,7 @@ async function runTemplatesUpdate(ctx, templatesDir, options = {}) {
5954
5677
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5955
5678
  files: newEntries
5956
5679
  };
5957
- await mkdir8(join25(ctx.dataDir, ".vortex"), { recursive: true });
5680
+ await mkdir8(join23(ctx.dataDir, ".vortex"), { recursive: true });
5958
5681
  await atomicWriteFile(ownershipManifestPath(ctx), JSON.stringify(manifest, null, 2) + "\n");
5959
5682
  }
5960
5683
  const summary = summarize(appliedActions);
@@ -6210,15 +5933,15 @@ var DEFAULT_INIT_TASK = "Setting up my VortEX instance";
6210
5933
  function resolveTemplatesDir() {
6211
5934
  const here = dirname5(fileURLToPath(import.meta.url));
6212
5935
  const candidates = [
6213
- join26(here, "..", "..", "templates"),
5936
+ join24(here, "..", "..", "templates"),
6214
5937
  // session-rituals: dist/commands -> templates
6215
- join26(here, "..", "templates"),
5938
+ join24(here, "..", "templates"),
6216
5939
  // base aggregate: dist -> templates
6217
- join26(here, "templates")
5940
+ join24(here, "templates")
6218
5941
  // defensive: alongside the bundle
6219
5942
  ];
6220
5943
  for (const c of candidates) {
6221
- if (existsSync12(join26(c, "commands")) || existsSync12(join26(c, "routers")))
5944
+ if (existsSync11(join24(c, "commands")) || existsSync11(join24(c, "routers")))
6222
5945
  return c;
6223
5946
  }
6224
5947
  return null;
@@ -6226,19 +5949,19 @@ function resolveTemplatesDir() {
6226
5949
  async function installCommandTemplates(repoRoot, templatesDir) {
6227
5950
  if (!templatesDir)
6228
5951
  return [];
6229
- const commandsDir = join26(templatesDir, "commands");
6230
- if (!existsSync12(commandsDir))
5952
+ const commandsDir = join24(templatesDir, "commands");
5953
+ if (!existsSync11(commandsDir))
6231
5954
  return [];
6232
- const destDir = join26(repoRoot, ".claude", "commands");
5955
+ const destDir = join24(repoRoot, ".claude", "commands");
6233
5956
  await mkdir9(destDir, { recursive: true });
6234
5957
  const written = [];
6235
5958
  for (const name of await readdir16(commandsDir)) {
6236
5959
  if (!name.endsWith(".md"))
6237
5960
  continue;
6238
- const dest = join26(destDir, name);
6239
- if (existsSync12(dest))
5961
+ const dest = join24(destDir, name);
5962
+ if (existsSync11(dest))
6240
5963
  continue;
6241
- await copyFile2(join26(commandsDir, name), dest);
5964
+ await copyFile2(join24(commandsDir, name), dest);
6242
5965
  written.push(dest);
6243
5966
  }
6244
5967
  return written;
@@ -6253,16 +5976,16 @@ var ROUTER_FILES = [
6253
5976
  async function installRouterTemplates(repoRoot, templatesDir) {
6254
5977
  if (!templatesDir)
6255
5978
  return [];
6256
- const routersDir = join26(templatesDir, "routers");
6257
- if (!existsSync12(routersDir))
5979
+ const routersDir = join24(templatesDir, "routers");
5980
+ if (!existsSync11(routersDir))
6258
5981
  return [];
6259
5982
  const written = [];
6260
5983
  for (const name of ROUTER_FILES) {
6261
- const src = join26(routersDir, name);
6262
- if (!existsSync12(src))
5984
+ const src = join24(routersDir, name);
5985
+ if (!existsSync11(src))
6263
5986
  continue;
6264
- const dest = join26(repoRoot, name);
6265
- if (existsSync12(dest))
5987
+ const dest = join24(repoRoot, name);
5988
+ if (existsSync11(dest))
6266
5989
  continue;
6267
5990
  await copyFile2(src, dest);
6268
5991
  written.push(dest);
@@ -6271,15 +5994,15 @@ async function installRouterTemplates(repoRoot, templatesDir) {
6271
5994
  }
6272
5995
  async function seedInstanceConfig(repoRoot, templatesDir) {
6273
5996
  const written = [];
6274
- const agentDir = join26(repoRoot, ".agent");
6275
- const vortexJson = join26(agentDir, "vortex.json");
6276
- if (!existsSync12(vortexJson)) {
5997
+ const agentDir = join24(repoRoot, ".agent");
5998
+ const vortexJson = join24(agentDir, "vortex.json");
5999
+ if (!existsSync11(vortexJson)) {
6277
6000
  await mkdir9(agentDir, { recursive: true });
6278
- const tmpl = templatesDir ? join26(templatesDir, "config", "vortex.json") : null;
6279
- if (tmpl && existsSync12(tmpl)) {
6001
+ const tmpl = templatesDir ? join24(templatesDir, "config", "vortex.json") : null;
6002
+ if (tmpl && existsSync11(tmpl)) {
6280
6003
  await copyFile2(tmpl, vortexJson);
6281
6004
  } else {
6282
- await writeFile11(vortexJson, JSON.stringify({
6005
+ await writeFile10(vortexJson, JSON.stringify({
6283
6006
  autoRecord: {
6284
6007
  sessionStart: true,
6285
6008
  worklog: true,
@@ -6294,9 +6017,9 @@ async function seedInstanceConfig(repoRoot, templatesDir) {
6294
6017
  }
6295
6018
  written.push(vortexJson);
6296
6019
  }
6297
- const pkgPath = join26(repoRoot, "package.json");
6298
- if (!existsSync12(pkgPath)) {
6299
- await writeFile11(pkgPath, JSON.stringify({
6020
+ const pkgPath = join24(repoRoot, "package.json");
6021
+ if (!existsSync11(pkgPath)) {
6022
+ await writeFile10(pkgPath, JSON.stringify({
6300
6023
  name: "vortex-instance",
6301
6024
  version: "0.0.0",
6302
6025
  private: true,
@@ -6313,8 +6036,8 @@ async function runInit(input, tokens) {
6313
6036
  const templatesDir = resolveTemplatesDir();
6314
6037
  const requiredDirs = ["_memory", "worklog", "decision-log", "hubs", "inbox", "runbooks"];
6315
6038
  for (const d2 of requiredDirs) {
6316
- const p = join26(dataDir, d2);
6317
- if (!existsSync12(p))
6039
+ const p = join24(dataDir, d2);
6040
+ if (!existsSync11(p))
6318
6041
  await mkdir9(p, { recursive: true });
6319
6042
  }
6320
6043
  const scaffolded = [];
@@ -6326,8 +6049,8 @@ async function runInit(input, tokens) {
6326
6049
  scaffolded.push(...await seedInstanceConfig(repoRoot, templatesDir));
6327
6050
  } catch {
6328
6051
  }
6329
- const profilePath = join26(dataDir, "_memory", "user_profile.md");
6330
- if (existsSync12(profilePath) && !args.force) {
6052
+ const profilePath = join24(dataDir, "_memory", "user_profile.md");
6053
+ if (existsSync11(profilePath) && !args.force) {
6331
6054
  const manifestNotes = [];
6332
6055
  try {
6333
6056
  const m2 = await writeOwnershipManifest(input.context, templatesDir);
@@ -6388,24 +6111,24 @@ async function runInit(input, tokens) {
6388
6111
  const name = args.name.trim();
6389
6112
  const role = args.role.trim();
6390
6113
  const task = args.task?.trim() || DEFAULT_INIT_TASK;
6391
- await writeFile11(profilePath, renderUserProfile(name, role, task, today2), "utf8");
6114
+ await writeFile10(profilePath, renderUserProfile(name, role, task, today2), "utf8");
6392
6115
  created.push(profilePath);
6393
6116
  const [year, month] = today2.split("-");
6394
- const worklogDir = join26(dataDir, "worklog", year, month);
6117
+ const worklogDir = join24(dataDir, "worklog", year, month);
6395
6118
  await mkdir9(worklogDir, { recursive: true });
6396
- const worklogPath = join26(worklogDir, `${today2}-vortex-init.md`);
6397
- await writeFile11(worklogPath, renderFirstWorklog(name, role, task, today2), "utf8");
6119
+ const worklogPath = join24(worklogDir, `${today2}-vortex-init.md`);
6120
+ await writeFile10(worklogPath, renderFirstWorklog(name, role, task, today2), "utf8");
6398
6121
  created.push(worklogPath);
6399
6122
  const hookNotes = [];
6400
6123
  try {
6401
- const settingsPath = join26(input.context.repoRoot, ".claude", "settings.json");
6402
- const existingText = existsSync12(settingsPath) ? await readFile21(settingsPath, "utf8") : null;
6403
- const { settings, added, alreadyWired } = ensureVortexHooks(parseSettings(existingText));
6124
+ const settingsPath = join24(input.context.repoRoot, ".claude", "settings.json");
6125
+ const existingText = existsSync11(settingsPath) ? await readFile21(settingsPath, "utf8") : null;
6126
+ const { settings, added, alreadyWired } = ensureVortexHooks(parseSettings(existingText), { guard: true });
6404
6127
  if (!alreadyWired) {
6405
- await mkdir9(join26(input.context.repoRoot, ".claude"), { recursive: true });
6406
- await writeFile11(settingsPath, serializeSettings(settings), "utf8");
6128
+ await mkdir9(join24(input.context.repoRoot, ".claude"), { recursive: true });
6129
+ await writeFile10(settingsPath, serializeSettings(settings), "utf8");
6407
6130
  created.push(settingsPath);
6408
- hookNotes.push(`Wired ${added.join(" + ")} hook(s) into .claude/settings.json \u2014 the VortEX boot report runs automatically at session start.`);
6131
+ hookNotes.push(`Wired ${added.join(" + ")} hook(s) into .claude/settings.json \u2014 the VortEX boot report runs automatically at session start` + (added.includes("PreToolUse") ? ", and the write guard now denies literal control bytes in file writes (remove the PreToolUse group to opt out)." : "."));
6409
6132
  } else {
6410
6133
  hookNotes.push("Session hooks already wired in .claude/settings.json.");
6411
6134
  }
@@ -6666,18 +6389,18 @@ var COUNT_KEY_TO_DIR = {
6666
6389
  };
6667
6390
  async function runStatus(input) {
6668
6391
  const { dataDir } = input.context;
6669
- const profilePath = join26(dataDir, "_memory", "user_profile.md");
6670
- const initialized = existsSync12(profilePath);
6392
+ const profilePath = join24(dataDir, "_memory", "user_profile.md");
6393
+ const initialized = existsSync11(profilePath);
6671
6394
  const counts = {
6672
- memory: await safeCount(join26(dataDir, "_memory"), false),
6673
- worklog: await safeCount(join26(dataDir, "worklog"), true),
6674
- decisionLog: await safeCount(join26(dataDir, "decision-log"), false),
6675
- runbooks: await safeCount(join26(dataDir, "runbooks"), false),
6676
- hubs: await safeCount(join26(dataDir, "hubs"), false)
6395
+ memory: await safeCount(join24(dataDir, "_memory"), false),
6396
+ worklog: await safeCount(join24(dataDir, "worklog"), true),
6397
+ decisionLog: await safeCount(join24(dataDir, "decision-log"), false),
6398
+ runbooks: await safeCount(join24(dataDir, "runbooks"), false),
6399
+ hubs: await safeCount(join24(dataDir, "hubs"), false)
6677
6400
  };
6678
6401
  let latestWorklog;
6679
6402
  try {
6680
- const store = new WorklogStore(join26(dataDir, "worklog"));
6403
+ const store = new WorklogStore(join24(dataDir, "worklog"));
6681
6404
  const latest = await store.getLatest();
6682
6405
  if (latest) {
6683
6406
  latestWorklog = {
@@ -6704,8 +6427,8 @@ async function runStatus(input) {
6704
6427
  for (const [key, count] of Object.entries(counts)) {
6705
6428
  if (count === 0) {
6706
6429
  const dirName = COUNT_KEY_TO_DIR[key];
6707
- const dirPath = join26(dataDir, dirName);
6708
- missing.push(existsSync12(dirPath) ? `${dirName}/ is empty` : `${dirName}/ does not exist`);
6430
+ const dirPath = join24(dataDir, dirName);
6431
+ missing.push(existsSync11(dirPath) ? `${dirName}/ is empty` : `${dirName}/ does not exist`);
6709
6432
  }
6710
6433
  }
6711
6434
  const nextActions = [];
@@ -6740,7 +6463,7 @@ function extractProfile(body) {
6740
6463
  return out;
6741
6464
  }
6742
6465
  async function safeCount(dir, recursive) {
6743
- if (!existsSync12(dir))
6466
+ if (!existsSync11(dir))
6744
6467
  return 0;
6745
6468
  try {
6746
6469
  return await countMarkdown2(dir, recursive);
@@ -6764,7 +6487,7 @@ async function countMarkdown2(dir, recursive) {
6764
6487
  } else if (e.isDirectory() && recursive) {
6765
6488
  if (e.name.startsWith(".") || e.name.startsWith("_"))
6766
6489
  continue;
6767
- total += await countMarkdown2(join26(dir, e.name), recursive);
6490
+ total += await countMarkdown2(join24(dir, e.name), recursive);
6768
6491
  }
6769
6492
  }
6770
6493
  return total;
@@ -6899,7 +6622,7 @@ async function runImport(input, tokens) {
6899
6622
  ]
6900
6623
  };
6901
6624
  }
6902
- if (!existsSync12(args.from)) {
6625
+ if (!existsSync11(args.from)) {
6903
6626
  return {
6904
6627
  subcommand: "import",
6905
6628
  status: "source-missing",
@@ -6933,8 +6656,8 @@ async function runImport(input, tokens) {
6933
6656
  const systemDirsCreated = [];
6934
6657
  if (!args.dryRun) {
6935
6658
  for (const d2 of systemDirs) {
6936
- const p = join26(dataDir, d2);
6937
- if (!existsSync12(p)) {
6659
+ const p = join24(dataDir, d2);
6660
+ if (!existsSync11(p)) {
6938
6661
  await mkdir9(p, { recursive: true });
6939
6662
  systemDirsCreated.push(d2);
6940
6663
  }
@@ -7030,7 +6753,7 @@ async function runImport(input, tokens) {
7030
6753
  async function walkAndImport(rootSource, currentDir, dataDir, dryRun, stats) {
7031
6754
  const entries = await readdir16(currentDir, { withFileTypes: true });
7032
6755
  for (const e of entries) {
7033
- const sourcePath = join26(currentDir, e.name);
6756
+ const sourcePath = join24(currentDir, e.name);
7034
6757
  if (e.isDirectory()) {
7035
6758
  if (IMPORT_SKIP_DIRS.has(e.name.toLowerCase()))
7036
6759
  continue;
@@ -7071,7 +6794,7 @@ async function walkAndImport(rootSource, currentDir, dataDir, dryRun, stats) {
7071
6794
  body: parsed.body
7072
6795
  });
7073
6796
  try {
7074
- await writeFile11(targetPath, out, { encoding: "utf8", flag: "wx" });
6797
+ await writeFile10(targetPath, out, { encoding: "utf8", flag: "wx" });
7075
6798
  stats.copied++;
7076
6799
  } catch (e2) {
7077
6800
  if (e2.code === "EEXIST") {
@@ -7104,7 +6827,7 @@ async function importAttachment(sourcePath, relPath, filename, dataDir, dryRun,
7104
6827
  stats.importedExtensions.add(ext);
7105
6828
  if (dryRun)
7106
6829
  return;
7107
- const targetPath = join26(dataDir, relPath);
6830
+ const targetPath = join24(dataDir, relPath);
7108
6831
  await mkdir9(dirname5(targetPath), { recursive: true });
7109
6832
  try {
7110
6833
  await copyFile2(sourcePath, targetPath, constants.COPYFILE_EXCL);
@@ -7168,27 +6891,27 @@ function computeTargetPath(category, sourcePath, rootSource, dataDir, filename)
7168
6891
  const mdName = withMdExtension(filename);
7169
6892
  if (category === "preserved") {
7170
6893
  const relPath = withMdExtension(sourcePath.substring(rootSource.length).replace(/^[/\\]/, ""));
7171
- return join26(dataDir, relPath);
6894
+ return join24(dataDir, relPath);
7172
6895
  }
7173
6896
  if (category === "worklog") {
7174
6897
  const match = mdName.match(/^(\d{4})-(\d{2})-/);
7175
6898
  if (match) {
7176
- return join26(dataDir, "worklog", match[1], match[2], mdName);
6899
+ return join24(dataDir, "worklog", match[1], match[2], mdName);
7177
6900
  }
7178
6901
  const d2 = /* @__PURE__ */ new Date();
7179
6902
  const y2 = String(d2.getFullYear());
7180
6903
  const m2 = String(d2.getMonth() + 1).padStart(2, "0");
7181
- return join26(dataDir, "worklog", y2, m2, mdName);
6904
+ return join24(dataDir, "worklog", y2, m2, mdName);
7182
6905
  }
7183
6906
  if (category === "decisionLog")
7184
- return join26(dataDir, "decision-log", mdName);
6907
+ return join24(dataDir, "decision-log", mdName);
7185
6908
  if (category === "runbooks")
7186
- return join26(dataDir, "runbooks", mdName);
6909
+ return join24(dataDir, "runbooks", mdName);
7187
6910
  if (category === "hubs")
7188
- return join26(dataDir, "hubs", mdName);
6911
+ return join24(dataDir, "hubs", mdName);
7189
6912
  if (category === "memory")
7190
- return join26(dataDir, "_memory", mdName);
7191
- return join26(dataDir, mdName);
6913
+ return join24(dataDir, "_memory", mdName);
6914
+ return join24(dataDir, mdName);
7192
6915
  }
7193
6916
  function withMdExtension(name) {
7194
6917
  const ext = extname11(name);
@@ -7335,7 +7058,7 @@ async function checkControlBytes(dataDir) {
7335
7058
  return;
7336
7059
  }
7337
7060
  for (const e of entries) {
7338
- const p = join26(dir, e.name);
7061
+ const p = join24(dir, e.name);
7339
7062
  if (e.isDirectory()) {
7340
7063
  if (SKIP_DIRS.has(e.name))
7341
7064
  continue;
@@ -7346,7 +7069,7 @@ async function checkControlBytes(dataDir) {
7346
7069
  for (let i = 0; i < buf.length; i++) {
7347
7070
  const x2 = buf[i];
7348
7071
  if (x2 < 32 && x2 !== 9 && x2 !== 10 && x2 !== 13) {
7349
- offenders.push(`${relative5(dataDir, p).replace(/\\/g, "/")} @ byte ${i}`);
7072
+ offenders.push(`${relative4(dataDir, p).replace(/\\/g, "/")} @ byte ${i}`);
7350
7073
  break;
7351
7074
  }
7352
7075
  }
@@ -7369,7 +7092,7 @@ async function checkControlBytes(dataDir) {
7369
7092
  };
7370
7093
  }
7371
7094
  function checkSystemDirs(dataDir) {
7372
- const missing = DOCTOR_SYSTEM_DIRS.filter((d2) => !existsSync12(join26(dataDir, d2)));
7095
+ const missing = DOCTOR_SYSTEM_DIRS.filter((d2) => !existsSync11(join24(dataDir, d2)));
7373
7096
  if (missing.length === 0) {
7374
7097
  return {
7375
7098
  id: "system-dirs",
@@ -7385,8 +7108,8 @@ function checkSystemDirs(dataDir) {
7385
7108
  };
7386
7109
  }
7387
7110
  function checkUserProfile(dataDir) {
7388
- const profilePath = join26(dataDir, "_memory", "user_profile.md");
7389
- if (existsSync12(profilePath)) {
7111
+ const profilePath = join24(dataDir, "_memory", "user_profile.md");
7112
+ if (existsSync11(profilePath)) {
7390
7113
  return {
7391
7114
  id: "user-profile",
7392
7115
  label: "user_profile.md exists",
@@ -7403,11 +7126,11 @@ function checkUserProfile(dataDir) {
7403
7126
  async function checkIndexes(dataDir) {
7404
7127
  const missing = [];
7405
7128
  for (const d2 of DOCTOR_SYSTEM_DIRS) {
7406
- const dirPath = join26(dataDir, d2);
7407
- if (!existsSync12(dirPath))
7129
+ const dirPath = join24(dataDir, d2);
7130
+ if (!existsSync11(dirPath))
7408
7131
  continue;
7409
- const indexPath = join26(dirPath, "_INDEX.md");
7410
- if (!existsSync12(indexPath))
7132
+ const indexPath = join24(dirPath, "_INDEX.md");
7133
+ if (!existsSync11(indexPath))
7411
7134
  missing.push(`${d2}/_INDEX.md`);
7412
7135
  }
7413
7136
  if (missing.length === 0) {
@@ -7440,7 +7163,7 @@ async function collectAttachmentExtensions(dataDir) {
7440
7163
  if (e.name.startsWith(".") || e.name === "_session-archive" || e.name === "node_modules") {
7441
7164
  continue;
7442
7165
  }
7443
- stack.push(join26(current, e.name));
7166
+ stack.push(join24(current, e.name));
7444
7167
  } else if (e.isFile()) {
7445
7168
  const ext = extname11(e.name);
7446
7169
  if (ext && ext.toLowerCase() !== ".md")
@@ -7537,8 +7260,8 @@ async function checkFrontmatterLint(dataDir, additionalExtensions = []) {
7537
7260
  }
7538
7261
  }
7539
7262
  async function checkRunbookAging(dataDir) {
7540
- const runbooksDir = join26(dataDir, "runbooks");
7541
- if (!existsSync12(runbooksDir)) {
7263
+ const runbooksDir = join24(dataDir, "runbooks");
7264
+ if (!existsSync11(runbooksDir)) {
7542
7265
  return {
7543
7266
  id: "runbook-aging",
7544
7267
  label: `runbooks tested within ${RUNBOOK_AGING_DAYS} days`,
@@ -7558,7 +7281,7 @@ async function checkRunbookAging(dataDir) {
7558
7281
  continue;
7559
7282
  }
7560
7283
  total++;
7561
- const filePath = join26(runbooksDir, e.name);
7284
+ const filePath = join24(runbooksDir, e.name);
7562
7285
  const raw = await readFile21(filePath, "utf8");
7563
7286
  const { frontmatter } = parseFrontmatter(raw);
7564
7287
  if (!frontmatter.last_tested) {
@@ -7621,8 +7344,8 @@ function checkNodeVersion() {
7621
7344
  };
7622
7345
  }
7623
7346
  async function checkGitRemote(repoRoot) {
7624
- const gitConfig = join26(repoRoot, ".git", "config");
7625
- if (!existsSync12(gitConfig)) {
7347
+ const gitConfig = join24(repoRoot, ".git", "config");
7348
+ if (!existsSync11(gitConfig)) {
7626
7349
  return {
7627
7350
  id: "git-remote",
7628
7351
  label: "git remote for sync",
@@ -7661,11 +7384,11 @@ async function detectExternalFolders(excludePath) {
7661
7384
  if (!home)
7662
7385
  return void 0;
7663
7386
  const candidates = [
7664
- join26(home, "Documents", "obsidian-vault"),
7665
- join26(home, "Documents", "notes"),
7666
- join26(home, "Documents", "Notebook"),
7667
- join26(home, "notes"),
7668
- join26(home, "Notes")
7387
+ join24(home, "Documents", "obsidian-vault"),
7388
+ join24(home, "Documents", "notes"),
7389
+ join24(home, "Documents", "Notebook"),
7390
+ join24(home, "notes"),
7391
+ join24(home, "Notes")
7669
7392
  ];
7670
7393
  const excludeNorm = excludePath.replace(/[/\\]+$/, "");
7671
7394
  const found = [];
@@ -7674,7 +7397,7 @@ async function detectExternalFolders(excludePath) {
7674
7397
  if (candNorm === excludeNorm || candNorm.startsWith(excludeNorm + "/") || candNorm.startsWith(excludeNorm + "\\") || excludeNorm.startsWith(candNorm + "/") || excludeNorm.startsWith(candNorm + "\\")) {
7675
7398
  continue;
7676
7399
  }
7677
- if (!existsSync12(candidate))
7400
+ if (!existsSync11(candidate))
7678
7401
  continue;
7679
7402
  let mdCount = 0;
7680
7403
  try {
@@ -7798,7 +7521,7 @@ async function runSync(input, tokens) {
7798
7521
  var SYNC_TAIL_LENGTH = 1e3;
7799
7522
  async function runShellCommand(cmd, cmdArgs, cwd) {
7800
7523
  const start = Date.now();
7801
- return new Promise((resolve5) => {
7524
+ return new Promise((resolve3) => {
7802
7525
  let stdout = "";
7803
7526
  let stderr = "";
7804
7527
  const child = spawn(cmd, [...cmdArgs], { cwd, shell: true });
@@ -7809,7 +7532,7 @@ async function runShellCommand(cmd, cmdArgs, cwd) {
7809
7532
  stderr += chunk.toString("utf8");
7810
7533
  });
7811
7534
  child.on("close", (code) => {
7812
- resolve5({
7535
+ resolve3({
7813
7536
  exitCode: code ?? -1,
7814
7537
  durationMs: Date.now() - start,
7815
7538
  stdoutTail: tailString(stdout, SYNC_TAIL_LENGTH),
@@ -7817,7 +7540,7 @@ async function runShellCommand(cmd, cmdArgs, cwd) {
7817
7540
  });
7818
7541
  });
7819
7542
  child.on("error", (err) => {
7820
- resolve5({
7543
+ resolve3({
7821
7544
  exitCode: -1,
7822
7545
  durationMs: Date.now() - start,
7823
7546
  stdoutTail: tailString(stdout, SYNC_TAIL_LENGTH),
@@ -7863,22 +7586,22 @@ function createRitualRegistry(options) {
7863
7586
 
7864
7587
  // ../plugins/session-rituals/dist/cli-dispatch.js
7865
7588
  import { execFileSync as execFileSync2, spawn as spawn2 } from "child_process";
7866
- import { existsSync as existsSync16, readFileSync as readFileSync4, mkdirSync, openSync, writeSync, closeSync, linkSync, rmSync, statSync } from "fs";
7589
+ import { existsSync as existsSync15, readFileSync as readFileSync3, mkdirSync, openSync, writeSync, closeSync, linkSync, rmSync, statSync } from "fs";
7867
7590
  import { createRequire } from "module";
7868
7591
  import { hostname } from "os";
7869
- import { isAbsolute as isAbsolute5, join as join30 } from "path";
7592
+ import { isAbsolute as isAbsolute4, join as join28 } from "path";
7870
7593
 
7871
7594
  // ../plugins/session-rituals/dist/update-check.js
7872
7595
  import { execSync } from "child_process";
7873
- import { existsSync as existsSync13, readFileSync as readFileSync3 } from "fs";
7874
- import { join as join27 } from "path";
7596
+ import { existsSync as existsSync12, readFileSync as readFileSync2 } from "fs";
7597
+ import { join as join25 } from "path";
7875
7598
  var PKG = "@vortex-os/base";
7876
7599
  var NPM_TIMEOUT_MS = 4e3;
7877
7600
  function readInstalledBaseVersion(templatesDir = resolveTemplatesDir()) {
7878
7601
  if (!templatesDir)
7879
7602
  return null;
7880
7603
  try {
7881
- const m2 = JSON.parse(readFileSync3(join27(templatesDir, "manifest.json"), "utf8"));
7604
+ const m2 = JSON.parse(readFileSync2(join25(templatesDir, "manifest.json"), "utf8"));
7882
7605
  return typeof m2.baseVersion === "string" && parseCore(m2.baseVersion) ? m2.baseVersion.trim() : null;
7883
7606
  } catch {
7884
7607
  return null;
@@ -7950,8 +7673,8 @@ function isStableUpdate(latest, installed) {
7950
7673
  return compareSemver(latest, installed) === 1;
7951
7674
  }
7952
7675
  function buildInstallCommand(repoRoot) {
7953
- const has = (f) => existsSync13(join27(repoRoot, f));
7954
- const local = existsSync13(join27(repoRoot, "node_modules", "@vortex-os", "base"));
7676
+ const has = (f) => existsSync12(join25(repoRoot, f));
7677
+ const local = existsSync12(join25(repoRoot, "node_modules", "@vortex-os", "base"));
7955
7678
  let installPart;
7956
7679
  if (!local) {
7957
7680
  installPart = `npm i -g ${PKG}@latest`;
@@ -7979,9 +7702,9 @@ function checkBaseUpdate(ctx) {
7979
7702
  }
7980
7703
 
7981
7704
  // ../plugins/session-rituals/dist/session-start-report.js
7982
- import { existsSync as existsSync14 } from "fs";
7705
+ import { existsSync as existsSync13 } from "fs";
7983
7706
  import { readdir as readdir17, readFile as readFile22, stat as stat9 } from "fs/promises";
7984
- import { join as join28 } from "path";
7707
+ import { join as join26 } from "path";
7985
7708
  var COUNTED_DIRS2 = ["_memory", "worklog", "decision-log"];
7986
7709
  var DEFAULT_GAP_WINDOW_DAYS = 30;
7987
7710
  function gapWindowSinceArg() {
@@ -7998,8 +7721,8 @@ async function collectSessionStartReport(ctx, opts) {
7998
7721
  const counts = {};
7999
7722
  const missing = [];
8000
7723
  for (const name of COUNTED_DIRS2) {
8001
- const dir = join28(ctx.dataDir, name);
8002
- if (!existsSync14(dir)) {
7724
+ const dir = join26(ctx.dataDir, name);
7725
+ if (!existsSync13(dir)) {
8003
7726
  missing.push(name);
8004
7727
  counts[name] = 0;
8005
7728
  continue;
@@ -8009,7 +7732,7 @@ async function collectSessionStartReport(ctx, opts) {
8009
7732
  const { recent, recentGroup, recentWorklogsOmitted, dates, latestBodies } = await scanWorklog(ctx.dataDir);
8010
7733
  const cutoff = isoDate2(addDays2(now, -(opts?.gapWindowDays ?? DEFAULT_GAP_WINDOW_DAYS)));
8011
7734
  const recentWorklogDates = dates.filter((d2) => d2 >= cutoff);
8012
- const mem = await scanMemoryTiers(join28(ctx.dataDir, "_memory"));
7735
+ const mem = await scanMemoryTiers(join26(ctx.dataDir, "_memory"));
8013
7736
  const ho = await scanHandoffs(ctx.dataDir);
8014
7737
  const handoffs = ho.active.map((h) => ({
8015
7738
  date: h.date,
@@ -8076,7 +7799,7 @@ async function scanMemoryTiers(memoryDir) {
8076
7799
  for (const e of entries) {
8077
7800
  if (!e.isFile() || !e.name.endsWith(".md"))
8078
7801
  continue;
8079
- const full = join28(memoryDir, e.name);
7802
+ const full = join26(memoryDir, e.name);
8080
7803
  if (e.name === "_INDEX.md") {
8081
7804
  indexExists = true;
8082
7805
  try {
@@ -8236,6 +7959,16 @@ function renderSessionStartReport(report, extras) {
8236
7959
  if (carry && carry.uncommitted > 0) {
8237
7960
  lines.push(`- \u21A9\uFE0F ${carry.uncommitted} uncommitted change(s) carried over from a prior session \u2014 likely normal work in progress.`);
8238
7961
  }
7962
+ const fl = extras?.failures;
7963
+ if (fl && fl.warnings.length > 0) {
7964
+ lines.push(`- \u{1F501} recurring failures (open ledger entries: ${fl.totalOpen}):`);
7965
+ for (const w2 of fl.warnings) {
7966
+ const stageText = w2.stage === "promote" ? "3rd+ occurrence \u2014 PROPOSE a deterministic guard to the user (ladder: promote; never self-install)" : `2nd occurrence \u2014 the covering rule's write-time gate is MANDATORY this session${w2.rule ? ` (rule: ${w2.rule})` : ""}`;
7967
+ lines.push(` - ${w2.key} \xD7${w2.count} (last ${w2.lastDate}) \u2014 ${stageText}`);
7968
+ }
7969
+ if (fl.omitted > 0)
7970
+ lines.push(` - \u2026(+${fl.omitted} more \u2014 \`vortex failure list\`)`);
7971
+ }
8239
7972
  const cu = extras?.catchUp;
8240
7973
  if (cu && (cu.ingestedLocal > 0 || cu.indexedPulled > 0 || cu.errors > 0)) {
8241
7974
  const parts = [];
@@ -8305,15 +8038,15 @@ async function countMarkdown3(dir, recursive) {
8305
8038
  } else if (e.isDirectory() && recursive) {
8306
8039
  if (e.name.startsWith(".") || e.name.startsWith("_"))
8307
8040
  continue;
8308
- total += await countMarkdown3(join28(dir, e.name), recursive);
8041
+ total += await countMarkdown3(join26(dir, e.name), recursive);
8309
8042
  }
8310
8043
  }
8311
8044
  return total;
8312
8045
  }
8313
8046
  var MAX_GROUP_READ = 20;
8314
8047
  async function scanWorklog(dataDir) {
8315
- const root = join28(dataDir, "worklog");
8316
- if (!existsSync14(root))
8048
+ const root = join26(dataDir, "worklog");
8049
+ if (!existsSync13(root))
8317
8050
  return { recent: null, recentGroup: [], recentWorklogsOmitted: 0, dates: [], latestBodies: [] };
8318
8051
  const dates = /* @__PURE__ */ new Set();
8319
8052
  const consistent = [];
@@ -8328,7 +8061,7 @@ async function scanWorklog(dataDir) {
8328
8061
  for (const e of entries) {
8329
8062
  const childRel = rel ? `${rel}/${e.name}` : e.name;
8330
8063
  if (e.isDirectory()) {
8331
- await walk5(join28(absDir, e.name), childRel);
8064
+ await walk5(join26(absDir, e.name), childRel);
8332
8065
  } else if (e.isFile()) {
8333
8066
  const m2 = e.name.match(/^(\d{4})-(\d{2})-(\d{2})(?:_\d{4})?-.+\.md$/);
8334
8067
  if (!m2)
@@ -8357,7 +8090,7 @@ async function scanWorklog(dataDir) {
8357
8090
  const recentGroup = [];
8358
8091
  const latestBodies = [];
8359
8092
  for (const g of group) {
8360
- const { title, body } = await readWorklogTitleAndBody(join28(root, g.rel));
8093
+ const { title, body } = await readWorklogTitleAndBody(join26(root, g.rel));
8361
8094
  recentGroup.push({ path: defangReportPath(`worklog/${g.rel}`), title });
8362
8095
  latestBodies.push(body);
8363
8096
  }
@@ -8436,11 +8169,11 @@ function isoDate2(d2) {
8436
8169
  }
8437
8170
 
8438
8171
  // ../plugins/session-rituals/dist/curate-cli.js
8439
- import { existsSync as existsSync15 } from "fs";
8172
+ import { existsSync as existsSync14 } from "fs";
8440
8173
  import { createHash as createHash3 } from "crypto";
8441
8174
  import { readFile as readFile23, readdir as readdir18 } from "fs/promises";
8442
- import { join as join29 } from "path";
8443
- var SYSTEM_META_DIRS3 = /* @__PURE__ */ new Set([
8175
+ import { join as join27 } from "path";
8176
+ var SYSTEM_META_DIRS2 = /* @__PURE__ */ new Set([
8444
8177
  "worklog",
8445
8178
  "decision-log",
8446
8179
  "runbooks",
@@ -8463,7 +8196,7 @@ function firstSegment(rel) {
8463
8196
  }
8464
8197
  function isSystemMetaRel(rel) {
8465
8198
  const first = firstSegment(rel);
8466
- return SYSTEM_META_DIRS3.has(first) || first.startsWith("_");
8199
+ return SYSTEM_META_DIRS2.has(first) || first.startsWith("_");
8467
8200
  }
8468
8201
  function validateCuratePayload(payload) {
8469
8202
  const errors = [];
@@ -8519,10 +8252,10 @@ function joinRel(...parts) {
8519
8252
  }
8520
8253
  async function runCurateCandidates(repoRoot, options) {
8521
8254
  const maxEntries = options?.maxEntries ?? 200;
8522
- const dataDir = join29(repoRoot, "data");
8255
+ const dataDir = join27(repoRoot, "data");
8523
8256
  const candidates = [];
8524
8257
  let truncated = false;
8525
- if (existsSync15(dataDir)) {
8258
+ if (existsSync14(dataDir)) {
8526
8259
  async function visit(absDir, relDir) {
8527
8260
  if (candidates.length >= maxEntries) {
8528
8261
  truncated = true;
@@ -8543,9 +8276,9 @@ async function runCurateCandidates(repoRoot, options) {
8543
8276
  const atRoot = relDir === "";
8544
8277
  if (e.name.startsWith("."))
8545
8278
  continue;
8546
- if (atRoot && (SYSTEM_META_DIRS3.has(e.name) || e.name.startsWith("_")))
8279
+ if (atRoot && (SYSTEM_META_DIRS2.has(e.name) || e.name.startsWith("_")))
8547
8280
  continue;
8548
- await visit(join29(absDir, e.name), joinRel(relDir, e.name));
8281
+ await visit(join27(absDir, e.name), joinRel(relDir, e.name));
8549
8282
  } else if (e.isFile() && e.name.endsWith(".md")) {
8550
8283
  if (NON_DOC_FILES.has(e.name))
8551
8284
  continue;
@@ -8554,7 +8287,7 @@ async function runCurateCandidates(repoRoot, options) {
8554
8287
  let topic = null;
8555
8288
  let tags = [];
8556
8289
  try {
8557
- const raw = await readFile23(join29(absDir, e.name), "utf8");
8290
+ const raw = await readFile23(join27(absDir, e.name), "utf8");
8558
8291
  const parsed = parseFrontmatter(raw);
8559
8292
  if (typeof parsed.frontmatter.topic === "string") {
8560
8293
  topic = parsed.frontmatter.topic.trim().toLowerCase();
@@ -8592,7 +8325,7 @@ async function runCuratePreview(repoRoot, payload, now = /* @__PURE__ */ new Dat
8592
8325
  };
8593
8326
  }
8594
8327
  try {
8595
- validateDataRelativePath(join29(repoRoot, "data"), v2.effectiveRelPath);
8328
+ validateDataRelativePath(join27(repoRoot, "data"), v2.effectiveRelPath);
8596
8329
  } catch (e) {
8597
8330
  return {
8598
8331
  subcommand: "curate-preview",
@@ -8609,10 +8342,10 @@ async function runCuratePreview(repoRoot, payload, now = /* @__PURE__ */ new Dat
8609
8342
  let targetExists;
8610
8343
  let wouldDo;
8611
8344
  if (payload.action === "create-file") {
8612
- targetExists = existsSync15(join29(repoRoot, "data", v2.effectiveRelPath));
8345
+ targetExists = existsSync14(join27(repoRoot, "data", v2.effectiveRelPath));
8613
8346
  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}.`;
8614
8347
  } else {
8615
- targetExists = existsSync15(join29(repoRoot, "data", v2.effectiveRelPath));
8348
+ targetExists = existsSync14(join27(repoRoot, "data", v2.effectiveRelPath));
8616
8349
  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).`;
8617
8350
  }
8618
8351
  const nextActions = [];
@@ -8757,13 +8490,13 @@ function readCuratePayload(args) {
8757
8490
  break;
8758
8491
  }
8759
8492
  if (t === "--payload-file" && i + 1 < args.length) {
8760
- raw = readFileSync4(args[++i], "utf8");
8493
+ raw = readFileSync3(args[++i], "utf8");
8761
8494
  break;
8762
8495
  }
8763
8496
  }
8764
8497
  if (raw === null) {
8765
8498
  try {
8766
- raw = readFileSync4(0, "utf8");
8499
+ raw = readFileSync3(0, "utf8");
8767
8500
  } catch {
8768
8501
  raw = "";
8769
8502
  }
@@ -8785,8 +8518,24 @@ function readCuratePayload(args) {
8785
8518
  async function runVortexCli(argv, io) {
8786
8519
  const out = io?.stdout ?? ((s) => process.stdout.write(s));
8787
8520
  const err = io?.stderr ?? ((s) => process.stderr.write(s));
8788
- const repoRoot = resolveRepoRoot();
8789
8521
  try {
8522
+ if (argv[0] === "statusline") {
8523
+ const { runStatuslineCli: runStatuslineCli2 } = await import("./statusline-6KSHISXO.js");
8524
+ const statuslineRoot = process.env.VORTEX_REPO_ROOT?.trim() || process.cwd();
8525
+ return runStatuslineCli2(argv.slice(1), statuslineRoot, out, err);
8526
+ }
8527
+ if (argv[0] === "guard") {
8528
+ const { runGuardCli: runGuardCli2 } = await import("./guard-IMJR6ET7.js");
8529
+ return runGuardCli2(argv.slice(1), out, err);
8530
+ }
8531
+ const repoRoot = resolveRepoRoot();
8532
+ if (argv[0] === "failure") {
8533
+ const { runFailureCli: runFailureCli2 } = await import("./failures-PMURLMVB.js");
8534
+ const { resolveInstanceRoot: resolveInstanceRoot2 } = await import("./guard-IMJR6ET7.js");
8535
+ const root = resolveInstanceRoot2(process.cwd()) ?? repoRoot;
8536
+ const ctx = makeContext(root);
8537
+ return runFailureCli2(argv.slice(1), ctx.dataDir, out, err);
8538
+ }
8790
8539
  if (argv[0] === "session-start") {
8791
8540
  await runSessionStart(repoRoot, out);
8792
8541
  return 0;
@@ -8825,6 +8574,9 @@ ${names}
8825
8574
  session-start \u2014 emit the start-of-session boot report (git pull + data counts + catch-up)
8826
8575
  session-end \u2014 no-op (kept for hook compatibility; worklog gap handling is at session-start)
8827
8576
  check-updates \u2014 check the npm registry for a newer @vortex-os/base (read-only; prints the exact update command)
8577
+ statusline \u2014 render the Claude Code status bar from stdin JSON (\`lite\` for 1-line; \`install [--lite]\` wires .claude/settings.json)
8578
+ failure \u2014 failure ledger (\`record\` an occurrence by recurrence key / \`list\` open groups with their escalation stage)
8579
+ guard \u2014 deterministic write-time guards (\`write\` = PreToolUse hook body; wired by \`vortex init\`)
8828
8580
 
8829
8581
  Instance shortcuts (also available as \`/vortex <sub>\`):
8830
8582
  init \u2014 first-time setup: routers + data/ + hooks + slash-commands
@@ -8891,12 +8643,12 @@ function memoryExtendedPresent() {
8891
8643
  }
8892
8644
  var VECTORIZE_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
8893
8645
  function vectorizeLockPath(ctx) {
8894
- return join30(ctx.dataDir, "_indexes", ".vectorize.lock");
8646
+ return join28(ctx.dataDir, "_indexes", ".vectorize.lock");
8895
8647
  }
8896
8648
  function vectorizeSetupInProgress(ctx) {
8897
8649
  const lock = vectorizeLockPath(ctx);
8898
8650
  try {
8899
- if (!existsSync16(lock))
8651
+ if (!existsSync15(lock))
8900
8652
  return false;
8901
8653
  return Date.now() - statSync(lock).mtimeMs < VECTORIZE_LOCK_TTL_MS;
8902
8654
  } catch {
@@ -8917,9 +8669,9 @@ function spawnVectorizeSetup(repoRoot) {
8917
8669
  }
8918
8670
  async function runVectorizeSetup(repoRoot, out, err) {
8919
8671
  const ctx = makeContext(repoRoot);
8920
- const indexDir = join30(ctx.dataDir, "_indexes");
8921
- const finalDb = join30(indexDir, "memory.sqlite");
8922
- if (existsSync16(finalDb)) {
8672
+ const indexDir = join28(ctx.dataDir, "_indexes");
8673
+ const finalDb = join28(indexDir, "memory.sqlite");
8674
+ if (existsSync15(finalDb)) {
8923
8675
  out("recall index already present \u2014 nothing to do\n");
8924
8676
  return;
8925
8677
  }
@@ -8950,7 +8702,7 @@ async function runVectorizeSetup(repoRoot, out, err) {
8950
8702
  return;
8951
8703
  }
8952
8704
  }
8953
- const tmpDb = join30(indexDir, `memory.sqlite.building-${process.pid}`);
8705
+ const tmpDb = join28(indexDir, `memory.sqlite.building-${process.pid}`);
8954
8706
  const tmpSidecars = [tmpDb + "-wal", tmpDb + "-shm", tmpDb + "-journal"];
8955
8707
  const cleanTmp = () => {
8956
8708
  rmSync(tmpDb, { force: true });
@@ -8960,7 +8712,7 @@ async function runVectorizeSetup(repoRoot, out, err) {
8960
8712
  let tokenWritten = false;
8961
8713
  const releaseLock = () => {
8962
8714
  try {
8963
- const cur = existsSync16(lockPath) ? readFileSync4(lockPath, "utf8").trim() : "";
8715
+ const cur = existsSync15(lockPath) ? readFileSync3(lockPath, "utf8").trim() : "";
8964
8716
  if (cur === token || cur === "" && !tokenWritten)
8965
8717
  rmSync(lockPath, { force: true });
8966
8718
  } catch {
@@ -8973,12 +8725,12 @@ async function runVectorizeSetup(repoRoot, out, err) {
8973
8725
  } finally {
8974
8726
  closeSync(lockFd);
8975
8727
  }
8976
- if (existsSync16(finalDb)) {
8728
+ if (existsSync15(finalDb)) {
8977
8729
  out("recall index already present \u2014 nothing to do\n");
8978
8730
  return;
8979
8731
  }
8980
8732
  cleanTmp();
8981
- const { vectorizeIndex } = await import("./vectorize-RBDBTSTW.js");
8733
+ const { vectorizeIndex } = await import("./vectorize-PN4Y7XMO.js");
8982
8734
  const result = await vectorizeIndex(ctx, { dbPath: tmpDb, allowDownload: true });
8983
8735
  const sqliteSpecifier = "better-sqlite3";
8984
8736
  const mod = await import(sqliteSpecifier);
@@ -8989,7 +8741,7 @@ async function runVectorizeSetup(repoRoot, out, err) {
8989
8741
  } finally {
8990
8742
  db.close();
8991
8743
  }
8992
- if (existsSync16(tmpDb + "-wal")) {
8744
+ if (existsSync15(tmpDb + "-wal")) {
8993
8745
  throw new Error("temp index retained a WAL sidecar after consolidation; refusing to publish");
8994
8746
  }
8995
8747
  try {
@@ -9055,7 +8807,7 @@ async function runSessionStart(repoRoot, out) {
9055
8807
  let catchUp = null;
9056
8808
  if (config.autoRecord.archive) {
9057
8809
  try {
9058
- const { catchUpSessions: catchUpSessions2 } = await import("./catch-up-KIHTAUPX.js");
8810
+ const { catchUpSessions: catchUpSessions2 } = await import("./catch-up-GDDKPZHJ.js");
9059
8811
  catchUp = await catchUpSessions2(ctx);
9060
8812
  } catch {
9061
8813
  }
@@ -9073,7 +8825,7 @@ async function runSessionStart(repoRoot, out) {
9073
8825
  let vectorized = null;
9074
8826
  let vectorizeSetupStarted = false;
9075
8827
  if (config.autoRecord.vectorize) {
9076
- const dbExists = existsSync16(join30(ctx.dataDir, "_indexes", "memory.sqlite"));
8828
+ const dbExists = existsSync15(join28(ctx.dataDir, "_indexes", "memory.sqlite"));
9077
8829
  const action = decideVectorizeAction({
9078
8830
  vectorizeOn: true,
9079
8831
  dbExists,
@@ -9084,7 +8836,7 @@ async function runSessionStart(repoRoot, out) {
9084
8836
  });
9085
8837
  if (action === "inline") {
9086
8838
  try {
9087
- const { vectorizeIndex } = await import("./vectorize-RBDBTSTW.js");
8839
+ const { vectorizeIndex } = await import("./vectorize-PN4Y7XMO.js");
9088
8840
  vectorized = await vectorizeIndex(ctx);
9089
8841
  } catch {
9090
8842
  }
@@ -9096,6 +8848,16 @@ async function runSessionStart(repoRoot, out) {
9096
8848
  }
9097
8849
  }
9098
8850
  }
8851
+ let failures = null;
8852
+ if (config.autoRecord.failures) {
8853
+ try {
8854
+ const { scanFailures: scanFailures2, failureReportSlice: failureReportSlice2 } = await import("./failures-PMURLMVB.js");
8855
+ const slice = failureReportSlice2(await scanFailures2(ctx.dataDir));
8856
+ if (slice.warnings.length > 0)
8857
+ failures = slice;
8858
+ } catch {
8859
+ }
8860
+ }
9099
8861
  let templateUpdate = null;
9100
8862
  try {
9101
8863
  const td = resolveTemplatesDir();
@@ -9135,7 +8897,8 @@ async function runSessionStart(repoRoot, out) {
9135
8897
  updateCheck: updateCheck ?? void 0,
9136
8898
  globalSetupOffer: globalSetupOffer || void 0,
9137
8899
  carryover: carryover ?? void 0,
9138
- handoffPrune: handoffPrune ?? void 0
8900
+ handoffPrune: handoffPrune ?? void 0,
8901
+ failures: failures ?? void 0
9139
8902
  }));
9140
8903
  }
9141
8904
  async function runSessionEnd(_repoRoot, _out) {
@@ -9162,7 +8925,7 @@ function detectInterruptedGitOp(repoRoot) {
9162
8925
  const resolved = gitOut(repoRoot, args).split(/\r?\n/).map((s) => s.trim());
9163
8926
  for (let i = 0; i < markers.length; i++) {
9164
8927
  const p = resolved[i];
9165
- if (p && existsSync16(isAbsolute5(p) ? p : join30(repoRoot, p)))
8928
+ if (p && existsSync15(isAbsolute4(p) ? p : join28(repoRoot, p)))
9166
8929
  return markers[i];
9167
8930
  }
9168
8931
  } catch {
@@ -9182,23 +8945,23 @@ function resolveSessionEnvironment(ctx, config) {
9182
8945
  let environment = resolveEnvironment(config, {
9183
8946
  hostname: hostname(),
9184
8947
  env: process.env,
9185
- pathExists: existsSync16
8948
+ pathExists: existsSync15
9186
8949
  });
9187
8950
  if (!environment)
9188
8951
  environment = process.env.VORTEX_ENV?.trim() || null;
9189
8952
  if (!environment) {
9190
- const envFile = join30(ctx.repoRoot, ".agent", "environment");
9191
- if (existsSync16(envFile)) {
9192
- environment = readFileSync4(envFile, "utf8").split(/\r?\n/)[0]?.trim() || null;
8953
+ const envFile = join28(ctx.repoRoot, ".agent", "environment");
8954
+ if (existsSync15(envFile)) {
8955
+ environment = readFileSync3(envFile, "utf8").split(/\r?\n/)[0]?.trim() || null;
9193
8956
  }
9194
8957
  }
9195
8958
  return environment;
9196
8959
  }
9197
8960
 
9198
8961
  // ../plugins/session-rituals/dist/ambient-recall.js
9199
- import { join as join31 } from "path";
8962
+ import { join as join29 } from "path";
9200
8963
  function defaultDbPath2(ctx) {
9201
- return join31(ctx.dataDir, "_indexes", "memory.sqlite");
8964
+ return join29(ctx.dataDir, "_indexes", "memory.sqlite");
9202
8965
  }
9203
8966
  function createAmbientRecaller(ctx, options) {
9204
8967
  const resolveDb = options.dbPath ?? defaultDbPath2;
@@ -9235,14 +8998,14 @@ function createAmbientRecaller(ctx, options) {
9235
8998
  }
9236
8999
 
9237
9000
  // ../plugins/session-rituals/dist/worklog-write.js
9238
- import { mkdir as mkdir10, writeFile as writeFile12 } from "fs/promises";
9239
- import { dirname as dirname6, join as join32 } from "path";
9001
+ import { mkdir as mkdir10, writeFile as writeFile11 } from "fs/promises";
9002
+ import { dirname as dirname6, join as join30 } from "path";
9240
9003
  async function ensureWorklogEntry(ctx, opts) {
9241
9004
  const now = opts?.now ?? /* @__PURE__ */ new Date();
9242
9005
  const date = isoDate3(now);
9243
9006
  const time = isoTime2(now);
9244
9007
  const keyword = (opts?.keyword ?? "worklog").trim() || "worklog";
9245
- const store = new WorklogStore(join32(ctx.dataDir, "worklog"));
9008
+ const store = new WorklogStore(join30(ctx.dataDir, "worklog"));
9246
9009
  const existing = await store.get(date);
9247
9010
  if (existing) {
9248
9011
  return { path: existing.path, date: existing.date, keyword: existing.keyword, created: false };
@@ -9250,7 +9013,7 @@ async function ensureWorklogEntry(ctx, opts) {
9250
9013
  const path = store.pathFor(date, keyword, time);
9251
9014
  const title = opts?.title ?? `${date} worklog`;
9252
9015
  await mkdir10(dirname6(path), { recursive: true });
9253
- await writeFile12(path, renderWorklogFile(date, title, opts?.body ?? ""), "utf8");
9016
+ await writeFile11(path, renderWorklogFile(date, title, opts?.body ?? ""), "utf8");
9254
9017
  return { path, date, keyword, created: true };
9255
9018
  }
9256
9019
  function renderWorklogFile(date, title, body) {