@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.
- package/LICENSE +21 -21
- package/README.md +48 -1
- package/bin/vortex.mjs +17 -17
- package/dist/{catch-up-KIHTAUPX.js → catch-up-GDDKPZHJ.js} +2 -2
- package/dist/chunk-2FVNWW77.js +166 -0
- package/dist/chunk-2FVNWW77.js.map +1 -0
- package/dist/{chunk-7SNLVGBO.js → chunk-3L5DLEGP.js} +1 -1
- package/dist/chunk-3L5DLEGP.js.map +1 -0
- package/dist/chunk-EAKDR5B2.js +501 -0
- package/dist/chunk-EAKDR5B2.js.map +1 -0
- package/dist/chunk-T53UWSTR.js +301 -0
- package/dist/chunk-T53UWSTR.js.map +1 -0
- package/dist/chunk-UV76ZEDC.js +292 -0
- package/dist/chunk-UV76ZEDC.js.map +1 -0
- package/dist/failures-PMURLMVB.js +25 -0
- package/dist/failures-PMURLMVB.js.map +1 -0
- package/dist/guard-IMJR6ET7.js +23 -0
- package/dist/guard-IMJR6ET7.js.map +1 -0
- package/dist/index.d.ts +425 -3
- package/dist/index.js +472 -709
- package/dist/index.js.map +1 -1
- package/dist/statusline-6KSHISXO.js +36 -0
- package/dist/statusline-6KSHISXO.js.map +1 -0
- package/dist/{vectorize-RBDBTSTW.js → vectorize-PN4Y7XMO.js} +1 -1
- package/dist/vectorize-PN4Y7XMO.js.map +1 -0
- package/package.json +1 -1
- package/templates/commands/agenda.md +15 -15
- package/templates/commands/handoff.md +26 -26
- package/templates/commands/resume.md +52 -52
- package/templates/config/vortex.json +13 -13
- package/templates/manifest.json +2 -2
- package/templates/routers/.cursorrules +14 -14
- package/templates/routers/AGENTS.md +27 -27
- package/templates/routers/AI-RULES.md +3 -1
- package/templates/routers/GEMINI.md +16 -16
- package/dist/chunk-7SNLVGBO.js.map +0 -1
- package/dist/vectorize-RBDBTSTW.js.map +0 -1
- /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-
|
|
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
|
|
403
|
-
import { join
|
|
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
|
|
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
|
|
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
|
|
467
|
-
import { join as
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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) =>
|
|
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
|
|
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) =>
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
2207
|
-
const target =
|
|
2208
|
-
if (target !== root && !(target +
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
2352
|
-
const target =
|
|
2353
|
-
if (target !== root && !(target +
|
|
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
|
|
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,
|
|
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 =
|
|
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:
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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,
|
|
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 =
|
|
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 =
|
|
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 =
|
|
2880
|
-
if (rel === ".." || rel.startsWith("../") ||
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2849
|
+
import { dirname as dirname2, join as join13 } from "path";
|
|
3078
2850
|
async function writeDocAction(cwd, action) {
|
|
3079
|
-
const dataDir =
|
|
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 (!
|
|
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
|
|
3100
|
-
import { appendFile as appendFile2, mkdir as mkdir3, readFile as readFile14, writeFile as
|
|
3101
|
-
import { join as
|
|
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
|
|
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(
|
|
2923
|
+
await appendFile2(join14(cwd, STORE_DIR, ACCEPTED_LOG), line + "\n", "utf8");
|
|
3152
2924
|
}
|
|
3153
2925
|
async function resetDeclined(cwd, kind) {
|
|
3154
|
-
const file =
|
|
3155
|
-
if (!
|
|
2926
|
+
const file = join14(cwd, STORE_DIR, DECLINED_FILE);
|
|
2927
|
+
if (!existsSync2(file))
|
|
3156
2928
|
return;
|
|
3157
2929
|
if (kind === void 0) {
|
|
3158
|
-
await
|
|
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
|
|
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 =
|
|
3185
|
-
if (!
|
|
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(
|
|
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
|
|
3207
|
-
import { mkdir as mkdir4, readFile as readFile15, readdir as readdir12, writeFile as
|
|
3208
|
-
import { dirname as dirname3, join as
|
|
3209
|
-
var
|
|
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 (
|
|
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 =
|
|
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
|
|
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 =
|
|
3560
|
-
if (!
|
|
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 =
|
|
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(
|
|
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 &&
|
|
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
|
|
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
|
|
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 =
|
|
3731
|
-
if (!
|
|
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 =
|
|
3736
|
-
if (!
|
|
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(
|
|
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 =
|
|
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 =
|
|
3831
|
-
if (
|
|
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 =
|
|
3726
|
+
const folder = join16(cwd, "data", HUB_DIR);
|
|
3955
3727
|
await mkdir5(folder, { recursive: true });
|
|
3956
|
-
const file =
|
|
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
|
|
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
|
|
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
|
|
4515
|
-
import { join as
|
|
4516
|
-
import { existsSync as
|
|
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 =
|
|
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 (
|
|
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
|
|
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
|
|
4562
|
-
import { readFile as readFile17, writeFile as
|
|
4563
|
-
import { join as
|
|
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 =
|
|
4674
|
-
if (!
|
|
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 =
|
|
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
|
|
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 =
|
|
4722
|
-
if (!
|
|
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 =
|
|
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
|
|
4548
|
+
await writeFile8(indexPath, body, "utf8");
|
|
4748
4549
|
status = "written";
|
|
4749
4550
|
}
|
|
4750
|
-
if (
|
|
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
|
|
4565
|
+
import { existsSync as existsSync7 } from "fs";
|
|
4765
4566
|
import { readdir as readdir14 } from "fs/promises";
|
|
4766
|
-
import { join as
|
|
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 =
|
|
4777
|
-
if (!
|
|
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(
|
|
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
|
|
4856
|
-
import { mkdir as mkdir6, open, readdir as readdir15, readFile as readFile18, rename
|
|
4857
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
5098
|
-
if (!
|
|
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 =
|
|
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 =
|
|
5133
|
-
if (!
|
|
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 =
|
|
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 =
|
|
5150
|
-
let to =
|
|
5151
|
-
if (
|
|
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 (
|
|
4955
|
+
while (existsSync8(join21(archiveDir, `${stem}-${i}.md`)))
|
|
5155
4956
|
i++;
|
|
5156
|
-
to =
|
|
4957
|
+
to = join21(archiveDir, `${stem}-${i}.md`);
|
|
5157
4958
|
}
|
|
5158
4959
|
try {
|
|
5159
|
-
await
|
|
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
|
|
5208
|
-
import { copyFile as copyFile2, mkdir as mkdir9, readdir as readdir16, readFile as readFile21, stat as stat8, writeFile as
|
|
5209
|
-
import { basename as basename7, dirname as dirname5, extname as extname11, join as
|
|
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
|
|
5293
|
-
import { mkdir as mkdir7, readFile as readFile19, writeFile as
|
|
5294
|
-
import { isAbsolute as
|
|
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 &&
|
|
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
|
|
5031
|
+
return join22(home, ".claude");
|
|
5309
5032
|
}
|
|
5310
5033
|
function globalSettingsPath(home = homedir()) {
|
|
5311
|
-
return
|
|
5034
|
+
return join22(globalClaudeDir(home), "settings.json");
|
|
5312
5035
|
}
|
|
5313
5036
|
function globalStatePath(home = homedir()) {
|
|
5314
|
-
return
|
|
5037
|
+
return join22(globalClaudeDir(home), "vortex-global.json");
|
|
5315
5038
|
}
|
|
5316
5039
|
function globalMemoryPath(home = homedir()) {
|
|
5317
|
-
return
|
|
5040
|
+
return join22(globalClaudeDir(home), "CLAUDE.md");
|
|
5318
5041
|
}
|
|
5319
5042
|
function readGlobalStateRaw(home = homedir()) {
|
|
5320
5043
|
try {
|
|
5321
|
-
const parsed = JSON.parse(
|
|
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
|
|
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(
|
|
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 =
|
|
5105
|
+
const instSettingsPath = join22(instanceRoot, ".claude", "settings.json");
|
|
5383
5106
|
const mdPath = globalMemoryPath(home);
|
|
5384
|
-
const hadState =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
5167
|
+
return join23(ctx.dataDir, ".vortex", "ownership.json");
|
|
5445
5168
|
}
|
|
5446
5169
|
function frameworkBookkeepingPrefix(ctx) {
|
|
5447
|
-
return toPosix(
|
|
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(
|
|
5181
|
+
out.add(toPosix(relative3(ctx.repoRoot, ownershipManifestPath(ctx))));
|
|
5459
5182
|
return [...out];
|
|
5460
5183
|
}
|
|
5461
5184
|
function toPosix(p) {
|
|
5462
|
-
return p.split(
|
|
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
|
|
5216
|
+
return join23(".claude", "commands", tail);
|
|
5494
5217
|
if (top === "config")
|
|
5495
|
-
return
|
|
5218
|
+
return join23(".agent", tail);
|
|
5496
5219
|
return null;
|
|
5497
5220
|
}
|
|
5498
5221
|
function assertUnderRoot(rootAbs, candidateAbs) {
|
|
5499
|
-
const rel =
|
|
5500
|
-
const up = ".." +
|
|
5501
|
-
const winsensitive =
|
|
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) ||
|
|
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 =
|
|
5510
|
-
if (!
|
|
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 =
|
|
5535
|
-
if (!
|
|
5257
|
+
const shippedAbs = join23(templatesDir, entry.path);
|
|
5258
|
+
if (!existsSync10(shippedAbs))
|
|
5536
5259
|
continue;
|
|
5537
5260
|
const sourceSha256 = await sha256File(shippedAbs);
|
|
5538
|
-
const destAbs =
|
|
5261
|
+
const destAbs = join23(ctx.repoRoot, destRel);
|
|
5539
5262
|
assertUnderRoot(ctx.repoRoot, destAbs);
|
|
5540
5263
|
let installedSha256 = null;
|
|
5541
|
-
if (
|
|
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(
|
|
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 =
|
|
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 =
|
|
5585
|
-
if (!
|
|
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 (
|
|
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 (!
|
|
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,
|
|
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 || !
|
|
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 =
|
|
5375
|
+
const destAbs = join23(ctx.repoRoot, e.path);
|
|
5653
5376
|
let diskPristine = false;
|
|
5654
5377
|
let normDisk = null;
|
|
5655
|
-
if (
|
|
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 =
|
|
5725
|
-
if (!
|
|
5447
|
+
const shippedAbs = join23(templatesDir, idx.path);
|
|
5448
|
+
if (!existsSync10(shippedAbs))
|
|
5726
5449
|
continue;
|
|
5727
5450
|
const newSource = await sha256File(shippedAbs);
|
|
5728
|
-
const destAbs =
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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 (
|
|
5582
|
+
if (existsSync10(newPath)) {
|
|
5860
5583
|
if (await readFile20(newPath, "utf8") === content)
|
|
5861
5584
|
return void 0;
|
|
5862
|
-
const backupAbs =
|
|
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(
|
|
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 (!
|
|
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 =
|
|
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(
|
|
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(
|
|
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 (
|
|
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(
|
|
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 (
|
|
5925
|
-
const backupAbs =
|
|
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(
|
|
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(
|
|
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
|
-
|
|
5936
|
+
join24(here, "..", "..", "templates"),
|
|
6214
5937
|
// session-rituals: dist/commands -> templates
|
|
6215
|
-
|
|
5938
|
+
join24(here, "..", "templates"),
|
|
6216
5939
|
// base aggregate: dist -> templates
|
|
6217
|
-
|
|
5940
|
+
join24(here, "templates")
|
|
6218
5941
|
// defensive: alongside the bundle
|
|
6219
5942
|
];
|
|
6220
5943
|
for (const c of candidates) {
|
|
6221
|
-
if (
|
|
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 =
|
|
6230
|
-
if (!
|
|
5952
|
+
const commandsDir = join24(templatesDir, "commands");
|
|
5953
|
+
if (!existsSync11(commandsDir))
|
|
6231
5954
|
return [];
|
|
6232
|
-
const destDir =
|
|
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 =
|
|
6239
|
-
if (
|
|
5961
|
+
const dest = join24(destDir, name);
|
|
5962
|
+
if (existsSync11(dest))
|
|
6240
5963
|
continue;
|
|
6241
|
-
await copyFile2(
|
|
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 =
|
|
6257
|
-
if (!
|
|
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 =
|
|
6262
|
-
if (!
|
|
5984
|
+
const src = join24(routersDir, name);
|
|
5985
|
+
if (!existsSync11(src))
|
|
6263
5986
|
continue;
|
|
6264
|
-
const dest =
|
|
6265
|
-
if (
|
|
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 =
|
|
6275
|
-
const vortexJson =
|
|
6276
|
-
if (!
|
|
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 ?
|
|
6279
|
-
if (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
|
|
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 =
|
|
6298
|
-
if (!
|
|
6299
|
-
await
|
|
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 =
|
|
6317
|
-
if (!
|
|
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 =
|
|
6330
|
-
if (
|
|
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
|
|
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 =
|
|
6117
|
+
const worklogDir = join24(dataDir, "worklog", year, month);
|
|
6395
6118
|
await mkdir9(worklogDir, { recursive: true });
|
|
6396
|
-
const worklogPath =
|
|
6397
|
-
await
|
|
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 =
|
|
6402
|
-
const existingText =
|
|
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(
|
|
6406
|
-
await
|
|
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 =
|
|
6670
|
-
const initialized =
|
|
6392
|
+
const profilePath = join24(dataDir, "_memory", "user_profile.md");
|
|
6393
|
+
const initialized = existsSync11(profilePath);
|
|
6671
6394
|
const counts = {
|
|
6672
|
-
memory: await safeCount(
|
|
6673
|
-
worklog: await safeCount(
|
|
6674
|
-
decisionLog: await safeCount(
|
|
6675
|
-
runbooks: await safeCount(
|
|
6676
|
-
hubs: await safeCount(
|
|
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(
|
|
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 =
|
|
6708
|
-
missing.push(
|
|
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 (!
|
|
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(
|
|
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 (!
|
|
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 =
|
|
6937
|
-
if (!
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
6904
|
+
return join24(dataDir, "worklog", y2, m2, mdName);
|
|
7182
6905
|
}
|
|
7183
6906
|
if (category === "decisionLog")
|
|
7184
|
-
return
|
|
6907
|
+
return join24(dataDir, "decision-log", mdName);
|
|
7185
6908
|
if (category === "runbooks")
|
|
7186
|
-
return
|
|
6909
|
+
return join24(dataDir, "runbooks", mdName);
|
|
7187
6910
|
if (category === "hubs")
|
|
7188
|
-
return
|
|
6911
|
+
return join24(dataDir, "hubs", mdName);
|
|
7189
6912
|
if (category === "memory")
|
|
7190
|
-
return
|
|
7191
|
-
return
|
|
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 =
|
|
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(`${
|
|
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) => !
|
|
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 =
|
|
7389
|
-
if (
|
|
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 =
|
|
7407
|
-
if (!
|
|
7129
|
+
const dirPath = join24(dataDir, d2);
|
|
7130
|
+
if (!existsSync11(dirPath))
|
|
7408
7131
|
continue;
|
|
7409
|
-
const indexPath =
|
|
7410
|
-
if (!
|
|
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(
|
|
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 =
|
|
7541
|
-
if (!
|
|
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 =
|
|
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 =
|
|
7625
|
-
if (!
|
|
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
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
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 (!
|
|
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((
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
7874
|
-
import { join as
|
|
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(
|
|
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) =>
|
|
7954
|
-
const local =
|
|
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
|
|
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
|
|
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 =
|
|
8002
|
-
if (!
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
8316
|
-
if (!
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
8443
|
-
var
|
|
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
|
|
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 =
|
|
8255
|
+
const dataDir = join27(repoRoot, "data");
|
|
8523
8256
|
const candidates = [];
|
|
8524
8257
|
let truncated = false;
|
|
8525
|
-
if (
|
|
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 && (
|
|
8279
|
+
if (atRoot && (SYSTEM_META_DIRS2.has(e.name) || e.name.startsWith("_")))
|
|
8547
8280
|
continue;
|
|
8548
|
-
await visit(
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
8493
|
+
raw = readFileSync3(args[++i], "utf8");
|
|
8761
8494
|
break;
|
|
8762
8495
|
}
|
|
8763
8496
|
}
|
|
8764
8497
|
if (raw === null) {
|
|
8765
8498
|
try {
|
|
8766
|
-
raw =
|
|
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
|
|
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 (!
|
|
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 =
|
|
8921
|
-
const finalDb =
|
|
8922
|
-
if (
|
|
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 =
|
|
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 =
|
|
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 (
|
|
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-
|
|
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 (
|
|
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-
|
|
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 =
|
|
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-
|
|
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 &&
|
|
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:
|
|
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 =
|
|
9191
|
-
if (
|
|
9192
|
-
environment =
|
|
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
|
|
8962
|
+
import { join as join29 } from "path";
|
|
9200
8963
|
function defaultDbPath2(ctx) {
|
|
9201
|
-
return
|
|
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
|
|
9239
|
-
import { dirname as dirname6, join as
|
|
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(
|
|
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
|
|
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) {
|