dreamcontext 0.8.7 → 0.8.8
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/agents/dreamcontext-explore.md +7 -3
- package/agents/dreamcontext-initializer.md +9 -0
- package/agents/sleep-migration.md +18 -10
- package/agents/sleep-product.md +6 -6
- package/agents/sleep-state.md +3 -3
- package/agents/sleep-tasks.md +4 -3
- package/dist/agents/dreamcontext-explore.md +7 -3
- package/dist/agents/dreamcontext-initializer.md +9 -0
- package/dist/agents/sleep-migration.md +18 -10
- package/dist/agents/sleep-product.md +6 -6
- package/dist/agents/sleep-state.md +3 -3
- package/dist/agents/sleep-tasks.md +4 -3
- package/dist/index.js +1204 -1066
- package/dist/skill-packs/council/SKILL.md +3 -2
- package/dist/skill-packs/council/debate-protocol.md +1 -1
- package/dist/skill-packs/excalidraw/SKILL.md +38 -28
- package/package.json +1 -1
- package/skill/SKILL.md +204 -500
- package/skill/references/cli-reference.md +200 -0
- package/skill/references/improving-dreamcontext.md +39 -0
- package/skill/references/integrations.md +200 -0
- package/skill/references/knowledge-and-recall.md +151 -0
- package/skill/references/sleep.md +88 -0
- package/skill/references/tasks-and-features.md +170 -0
- package/skill-packs/council/SKILL.md +3 -2
- package/skill-packs/council/debate-protocol.md +1 -1
- package/skill-packs/excalidraw/SKILL.md +38 -28
package/dist/index.js
CHANGED
|
@@ -22775,6 +22775,19 @@ async function installCoreForPlatform(platform2, projectRoot, manifest) {
|
|
|
22775
22775
|
const coreSkillRel = `${skillRootRel}/dreamcontext/SKILL.md`;
|
|
22776
22776
|
recordIfManifest2(manifest, coreSkillRel, "core");
|
|
22777
22777
|
installed.push(platformPrefixed(platform2, coreSkillRel));
|
|
22778
|
+
const refsSourceDir = join9(dirname6(skillSource), "references");
|
|
22779
|
+
if (existsSync9(refsSourceDir)) {
|
|
22780
|
+
const refsDestDir = join9(skillDestDir, "references");
|
|
22781
|
+
cpSync2(refsSourceDir, refsDestDir, { recursive: true });
|
|
22782
|
+
const refFiles = readdirSync4(refsSourceDir).filter((f) => f.endsWith(".md"));
|
|
22783
|
+
for (const rf of refFiles) {
|
|
22784
|
+
const refRel = `${skillRootRel}/dreamcontext/references/${rf}`;
|
|
22785
|
+
recordIfManifest2(manifest, refRel, "core");
|
|
22786
|
+
}
|
|
22787
|
+
if (refFiles.length > 0) {
|
|
22788
|
+
installed.push(platformPrefixed(platform2, `${skillRootRel}/dreamcontext/references/ ${source_default.dim(`(${refFiles.length} reference${refFiles.length === 1 ? "" : "s"})`)}`));
|
|
22789
|
+
}
|
|
22790
|
+
}
|
|
22778
22791
|
const agentsSourceDir = findPackageDir("agents");
|
|
22779
22792
|
if (agentsSourceDir) {
|
|
22780
22793
|
const agentFiles = readdirSync4(agentsSourceDir).filter((f) => f.endsWith(".md"));
|
|
@@ -29289,6 +29302,548 @@ var init_tech_stack = __esm({
|
|
|
29289
29302
|
}
|
|
29290
29303
|
});
|
|
29291
29304
|
|
|
29305
|
+
// src/lib/version-check.ts
|
|
29306
|
+
import { existsSync as existsSync13, readFileSync as readFileSync14, mkdirSync as mkdirSync8, writeFileSync as writeFileSync12 } from "fs";
|
|
29307
|
+
import { dirname as dirname8, join as join13 } from "path";
|
|
29308
|
+
import { execFileSync, spawn as spawn2 } from "child_process";
|
|
29309
|
+
function cachePath(root) {
|
|
29310
|
+
return join13(root, CACHE_REL_PATH);
|
|
29311
|
+
}
|
|
29312
|
+
function readVersionCache(root) {
|
|
29313
|
+
const path2 = cachePath(root);
|
|
29314
|
+
if (!existsSync13(path2)) return null;
|
|
29315
|
+
try {
|
|
29316
|
+
const raw = readFileSync14(path2, "utf-8");
|
|
29317
|
+
const parsed = JSON.parse(raw);
|
|
29318
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
29319
|
+
if (typeof parsed.checkedAt !== "number") return null;
|
|
29320
|
+
return {
|
|
29321
|
+
checkedAt: parsed.checkedAt,
|
|
29322
|
+
latestCli: typeof parsed.latestCli === "string" ? parsed.latestCli : null,
|
|
29323
|
+
availablePacks: Array.isArray(parsed.availablePacks) ? parsed.availablePacks.filter((p) => typeof p === "string") : [],
|
|
29324
|
+
ttlHours: typeof parsed.ttlHours === "number" ? parsed.ttlHours : DEFAULT_TTL_HOURS
|
|
29325
|
+
};
|
|
29326
|
+
} catch {
|
|
29327
|
+
return null;
|
|
29328
|
+
}
|
|
29329
|
+
}
|
|
29330
|
+
function writeVersionCache(root, cache) {
|
|
29331
|
+
const path2 = cachePath(root);
|
|
29332
|
+
try {
|
|
29333
|
+
mkdirSync8(dirname8(path2), { recursive: true });
|
|
29334
|
+
writeFileSync12(path2, JSON.stringify(cache, null, 2) + "\n", "utf-8");
|
|
29335
|
+
} catch {
|
|
29336
|
+
}
|
|
29337
|
+
}
|
|
29338
|
+
function isCacheFresh(cache, nowMs) {
|
|
29339
|
+
if (!cache) return false;
|
|
29340
|
+
try {
|
|
29341
|
+
if (typeof cache.checkedAt !== "number" || !isFinite(cache.checkedAt)) return false;
|
|
29342
|
+
const ttlHours = typeof cache.ttlHours === "number" && isFinite(cache.ttlHours) && cache.ttlHours > 0 ? cache.ttlHours : DEFAULT_TTL_HOURS;
|
|
29343
|
+
const ttlMs = ttlHours * 60 * 60 * 1e3;
|
|
29344
|
+
const now = nowMs ?? Date.now();
|
|
29345
|
+
return now - cache.checkedAt < ttlMs;
|
|
29346
|
+
} catch {
|
|
29347
|
+
return false;
|
|
29348
|
+
}
|
|
29349
|
+
}
|
|
29350
|
+
function compareVersions(a, b) {
|
|
29351
|
+
const clean = (v) => v.replace(/[-+].*$/, "").trim();
|
|
29352
|
+
const parseSegments = (v) => clean(v).split(".").map((s) => {
|
|
29353
|
+
const n = parseInt(s, 10);
|
|
29354
|
+
return isFinite(n) ? n : 0;
|
|
29355
|
+
});
|
|
29356
|
+
const segA = parseSegments(a);
|
|
29357
|
+
const segB = parseSegments(b);
|
|
29358
|
+
const len = Math.max(segA.length, segB.length);
|
|
29359
|
+
for (let i = 0; i < len; i++) {
|
|
29360
|
+
const sa = segA[i] ?? 0;
|
|
29361
|
+
const sb = segB[i] ?? 0;
|
|
29362
|
+
if (sa < sb) return -1;
|
|
29363
|
+
if (sa > sb) return 1;
|
|
29364
|
+
}
|
|
29365
|
+
return 0;
|
|
29366
|
+
}
|
|
29367
|
+
function buildNudge(installedCli, cache, installedPacks, catalogPackNames, opts = {}) {
|
|
29368
|
+
if (!cache || cache.latestCli === null) return null;
|
|
29369
|
+
const cliOutdated = compareVersions(installedCli, cache.latestCli) < 0;
|
|
29370
|
+
const showCliNudge = cliOutdated && !opts.suppressCliNudge;
|
|
29371
|
+
const newPacks = catalogPackNames.filter((p) => !installedPacks.includes(p));
|
|
29372
|
+
const hasNewPacks = newPacks.length > 0;
|
|
29373
|
+
if (!showCliNudge && !hasNewPacks) return null;
|
|
29374
|
+
const lines = ["## Update Available\n"];
|
|
29375
|
+
if (showCliNudge) {
|
|
29376
|
+
lines.push(`- **New version available: v${installedCli} \u2192 v${cache.latestCli}.** A new release can add, update, or remove hooks, prompts, sub-agents, and skills. Run \`dreamcontext upgrade\` to get it, then \`dreamcontext update\` to apply those changes to this project.`);
|
|
29377
|
+
}
|
|
29378
|
+
if (hasNewPacks) {
|
|
29379
|
+
lines.push(`- New skill pack${newPacks.length > 1 ? "s" : ""} available: ${newPacks.join(", ")} \u2014 run \`dreamcontext install-skill --packs\``);
|
|
29380
|
+
}
|
|
29381
|
+
return lines.join("\n");
|
|
29382
|
+
}
|
|
29383
|
+
function refreshVersionCache(root, opts) {
|
|
29384
|
+
const runner = opts?.runner ?? ((args) => execFileSync("npm", args, {
|
|
29385
|
+
timeout: NPM_TIMEOUT_MS,
|
|
29386
|
+
encoding: "utf-8",
|
|
29387
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
29388
|
+
}));
|
|
29389
|
+
const catalogPackNames = opts?.catalogPackNames ?? [];
|
|
29390
|
+
let latestCli = null;
|
|
29391
|
+
try {
|
|
29392
|
+
const raw = runner(["view", "dreamcontext", "version"]);
|
|
29393
|
+
const trimmed = (typeof raw === "string" ? raw : "").trim();
|
|
29394
|
+
if (/^\d+\.\d+/.test(trimmed)) {
|
|
29395
|
+
latestCli = trimmed;
|
|
29396
|
+
}
|
|
29397
|
+
} catch {
|
|
29398
|
+
latestCli = null;
|
|
29399
|
+
}
|
|
29400
|
+
const cache = {
|
|
29401
|
+
checkedAt: Date.now(),
|
|
29402
|
+
latestCli,
|
|
29403
|
+
availablePacks: catalogPackNames,
|
|
29404
|
+
ttlHours: DEFAULT_TTL_HOURS
|
|
29405
|
+
};
|
|
29406
|
+
writeVersionCache(root, cache);
|
|
29407
|
+
}
|
|
29408
|
+
function markerPath(root) {
|
|
29409
|
+
return join13(root, AUTO_UPGRADE_MARKER_REL_PATH);
|
|
29410
|
+
}
|
|
29411
|
+
function readAutoUpgradeMarker(root) {
|
|
29412
|
+
const path2 = markerPath(root);
|
|
29413
|
+
if (!existsSync13(path2)) return null;
|
|
29414
|
+
try {
|
|
29415
|
+
const parsed = JSON.parse(readFileSync14(path2, "utf-8"));
|
|
29416
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
29417
|
+
if (typeof parsed.attemptedFor !== "string" || typeof parsed.at !== "number") return null;
|
|
29418
|
+
return { attemptedFor: parsed.attemptedFor, at: parsed.at };
|
|
29419
|
+
} catch {
|
|
29420
|
+
return null;
|
|
29421
|
+
}
|
|
29422
|
+
}
|
|
29423
|
+
function writeAutoUpgradeMarker(root, marker) {
|
|
29424
|
+
const path2 = markerPath(root);
|
|
29425
|
+
try {
|
|
29426
|
+
mkdirSync8(dirname8(path2), { recursive: true });
|
|
29427
|
+
writeFileSync12(path2, JSON.stringify(marker, null, 2) + "\n", "utf-8");
|
|
29428
|
+
} catch {
|
|
29429
|
+
}
|
|
29430
|
+
}
|
|
29431
|
+
function autoUpgradeEnabled(env2 = process.env) {
|
|
29432
|
+
if (env2.DREAMCONTEXT_VERSION_CHECK === "0") return false;
|
|
29433
|
+
return env2.DREAMCONTEXT_AUTO_UPGRADE !== "0";
|
|
29434
|
+
}
|
|
29435
|
+
function shouldAutoUpgrade(installedCli, cache, env2 = process.env) {
|
|
29436
|
+
if (!autoUpgradeEnabled(env2)) return null;
|
|
29437
|
+
if (!cache || cache.latestCli === null) return null;
|
|
29438
|
+
if (compareVersions(installedCli, cache.latestCli) >= 0) return null;
|
|
29439
|
+
return cache.latestCli;
|
|
29440
|
+
}
|
|
29441
|
+
function shouldSuppressCliNudge(target, marker, env2 = process.env, now = Date.now()) {
|
|
29442
|
+
if (!autoUpgradeEnabled(env2)) return false;
|
|
29443
|
+
if (!target || !marker) return false;
|
|
29444
|
+
if (marker.attemptedFor !== target) return false;
|
|
29445
|
+
return now - marker.at < AUTO_UPGRADE_INFLIGHT_MS;
|
|
29446
|
+
}
|
|
29447
|
+
function defaultSpawner(cmd, args) {
|
|
29448
|
+
const child = spawn2(cmd, args, { detached: true, stdio: "ignore" });
|
|
29449
|
+
child.unref();
|
|
29450
|
+
}
|
|
29451
|
+
function maybeAutoUpgrade(root, installedCli, cache, env2 = process.env, deps = {}) {
|
|
29452
|
+
try {
|
|
29453
|
+
const target = shouldAutoUpgrade(installedCli, cache, env2);
|
|
29454
|
+
if (!target) return null;
|
|
29455
|
+
const now = deps.now ?? Date.now();
|
|
29456
|
+
const readMarker = deps.readMarker ?? readAutoUpgradeMarker;
|
|
29457
|
+
const writeMarker = deps.writeMarker ?? writeAutoUpgradeMarker;
|
|
29458
|
+
const marker = readMarker(root);
|
|
29459
|
+
const recentlyAttempted = marker !== null && marker.attemptedFor === target && now - marker.at < AUTO_UPGRADE_RETRY_MS;
|
|
29460
|
+
if (recentlyAttempted) return null;
|
|
29461
|
+
writeMarker(root, { attemptedFor: target, at: now });
|
|
29462
|
+
const spawner = deps.spawner ?? defaultSpawner;
|
|
29463
|
+
spawner("npm", ["install", "-g", "dreamcontext@latest"]);
|
|
29464
|
+
return `\u2B06 Auto-upgrading dreamcontext v${installedCli} \u2192 v${target} in the background (takes effect next session).`;
|
|
29465
|
+
} catch {
|
|
29466
|
+
return null;
|
|
29467
|
+
}
|
|
29468
|
+
}
|
|
29469
|
+
var CACHE_REL_PATH, AUTO_UPGRADE_MARKER_REL_PATH, DEFAULT_TTL_HOURS, NPM_TIMEOUT_MS, AUTO_UPGRADE_RETRY_MS, AUTO_UPGRADE_INFLIGHT_MS;
|
|
29470
|
+
var init_version_check = __esm({
|
|
29471
|
+
"src/lib/version-check.ts"() {
|
|
29472
|
+
"use strict";
|
|
29473
|
+
CACHE_REL_PATH = "_dream_context/state/.version-check.json";
|
|
29474
|
+
AUTO_UPGRADE_MARKER_REL_PATH = "_dream_context/state/.auto-upgrade.json";
|
|
29475
|
+
DEFAULT_TTL_HOURS = 24;
|
|
29476
|
+
NPM_TIMEOUT_MS = 5e3;
|
|
29477
|
+
AUTO_UPGRADE_RETRY_MS = 24 * 60 * 60 * 1e3;
|
|
29478
|
+
AUTO_UPGRADE_INFLIGHT_MS = 60 * 60 * 1e3;
|
|
29479
|
+
}
|
|
29480
|
+
});
|
|
29481
|
+
|
|
29482
|
+
// src/cli/commands/app.ts
|
|
29483
|
+
import { execFileSync as execFileSync2, spawn as spawnProcess } from "child_process";
|
|
29484
|
+
import {
|
|
29485
|
+
existsSync as existsSync14,
|
|
29486
|
+
mkdirSync as mkdirSync9,
|
|
29487
|
+
mkdtempSync,
|
|
29488
|
+
readFileSync as readFileSync15,
|
|
29489
|
+
writeFileSync as writeFileSync13,
|
|
29490
|
+
rmSync as rmSync2,
|
|
29491
|
+
renameSync,
|
|
29492
|
+
readdirSync as readdirSync5
|
|
29493
|
+
} from "fs";
|
|
29494
|
+
import { homedir, tmpdir } from "os";
|
|
29495
|
+
import { join as join14, resolve as resolve3, dirname as dirname9 } from "path";
|
|
29496
|
+
import { createHash } from "crypto";
|
|
29497
|
+
function detectPlatform(platform2 = process.platform, arch2 = process.arch) {
|
|
29498
|
+
const os3 = platform2 === "darwin" ? "darwin" : platform2 === "win32" ? "win32" : platform2 === "linux" ? "linux" : "other";
|
|
29499
|
+
const a = arch2 === "arm64" ? "aarch64" : arch2 === "x64" ? "x86_64" : "other";
|
|
29500
|
+
return { os: os3, arch: a };
|
|
29501
|
+
}
|
|
29502
|
+
function pickAssetForArch(assetNames, arch2) {
|
|
29503
|
+
const appAssets = assetNames.filter((n) => n.endsWith(".app.tar.gz"));
|
|
29504
|
+
const exact = appAssets.find((n) => n.includes(`_${arch2}.`));
|
|
29505
|
+
return exact ?? null;
|
|
29506
|
+
}
|
|
29507
|
+
function defaultInstallDir(home = homedir()) {
|
|
29508
|
+
return join14(home, "Applications");
|
|
29509
|
+
}
|
|
29510
|
+
function appManifestPath(home = homedir()) {
|
|
29511
|
+
return join14(home, ".dreamcontext", "app.json");
|
|
29512
|
+
}
|
|
29513
|
+
function readAppManifest(home = homedir()) {
|
|
29514
|
+
const p = appManifestPath(home);
|
|
29515
|
+
if (!existsSync14(p)) return null;
|
|
29516
|
+
try {
|
|
29517
|
+
const parsed = JSON.parse(readFileSync15(p, "utf-8"));
|
|
29518
|
+
if (!parsed || typeof parsed.version !== "string" || typeof parsed.path !== "string") return null;
|
|
29519
|
+
return {
|
|
29520
|
+
version: parsed.version,
|
|
29521
|
+
path: parsed.path,
|
|
29522
|
+
installedAt: typeof parsed.installedAt === "number" ? parsed.installedAt : 0,
|
|
29523
|
+
source: typeof parsed.source === "string" ? parsed.source : "unknown"
|
|
29524
|
+
};
|
|
29525
|
+
} catch {
|
|
29526
|
+
return null;
|
|
29527
|
+
}
|
|
29528
|
+
}
|
|
29529
|
+
function writeAppManifest(manifest, home = homedir()) {
|
|
29530
|
+
const p = appManifestPath(home);
|
|
29531
|
+
mkdirSync9(dirname9(p), { recursive: true });
|
|
29532
|
+
writeFileSync13(p, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
29533
|
+
}
|
|
29534
|
+
function run(cmd, args) {
|
|
29535
|
+
execFileSync2(cmd, args, { stdio: ["ignore", "ignore", "pipe"] });
|
|
29536
|
+
}
|
|
29537
|
+
function runCapture(cmd, args) {
|
|
29538
|
+
return execFileSync2(cmd, args, { encoding: "utf-8" }).toString().trim();
|
|
29539
|
+
}
|
|
29540
|
+
function validateAppBundle(appDir) {
|
|
29541
|
+
if (!appDir.endsWith(".app") || !existsSync14(appDir)) {
|
|
29542
|
+
throw new Error(`Not a .app bundle: ${appDir}`);
|
|
29543
|
+
}
|
|
29544
|
+
const macos = join14(appDir, "Contents", "MacOS");
|
|
29545
|
+
const plist = join14(appDir, "Contents", "Info.plist");
|
|
29546
|
+
if (!existsSync14(macos) || !existsSync14(plist)) {
|
|
29547
|
+
throw new Error(`Malformed .app (missing Contents/MacOS or Info.plist): ${appDir}`);
|
|
29548
|
+
}
|
|
29549
|
+
}
|
|
29550
|
+
function readBundleVersion(appDir) {
|
|
29551
|
+
const plist = join14(appDir, "Contents", "Info.plist");
|
|
29552
|
+
try {
|
|
29553
|
+
return runCapture("plutil", ["-extract", "CFBundleShortVersionString", "raw", "-o", "-", plist]) || null;
|
|
29554
|
+
} catch {
|
|
29555
|
+
return null;
|
|
29556
|
+
}
|
|
29557
|
+
}
|
|
29558
|
+
function findAppInDir(dir) {
|
|
29559
|
+
const entries = readdirSync5(dir).filter((e) => e.endsWith(".app"));
|
|
29560
|
+
return entries.length > 0 ? join14(dir, entries[0]) : null;
|
|
29561
|
+
}
|
|
29562
|
+
function materializeAppBundle(source, workDir) {
|
|
29563
|
+
const src = resolve3(source);
|
|
29564
|
+
if (!existsSync14(src)) throw new Error(`Source not found: ${src}`);
|
|
29565
|
+
if (src.endsWith(".app")) {
|
|
29566
|
+
return src;
|
|
29567
|
+
}
|
|
29568
|
+
if (src.endsWith(".tar.gz") || src.endsWith(".tgz")) {
|
|
29569
|
+
run("tar", ["-xzf", src, "-C", workDir]);
|
|
29570
|
+
} else if (src.endsWith(".zip")) {
|
|
29571
|
+
run("ditto", ["-x", "-k", src, workDir]);
|
|
29572
|
+
} else {
|
|
29573
|
+
throw new Error(`Unsupported source (expect .app, .tar.gz, or .zip): ${src}`);
|
|
29574
|
+
}
|
|
29575
|
+
const app = findAppInDir(workDir);
|
|
29576
|
+
if (!app) throw new Error(`No .app found inside archive: ${src}`);
|
|
29577
|
+
return app;
|
|
29578
|
+
}
|
|
29579
|
+
function verifyCodesign(appDir) {
|
|
29580
|
+
try {
|
|
29581
|
+
execFileSync2("codesign", ["--verify", "--deep", appDir], { stdio: ["ignore", "ignore", "ignore"] });
|
|
29582
|
+
return true;
|
|
29583
|
+
} catch {
|
|
29584
|
+
return false;
|
|
29585
|
+
}
|
|
29586
|
+
}
|
|
29587
|
+
function isAppRunning() {
|
|
29588
|
+
try {
|
|
29589
|
+
const out = execFileSync2("pgrep", ["-f", `${APP_BUNDLE_NAME}/Contents/MacOS/`], { encoding: "utf-8" }).toString().trim();
|
|
29590
|
+
return out.length > 0;
|
|
29591
|
+
} catch {
|
|
29592
|
+
return false;
|
|
29593
|
+
}
|
|
29594
|
+
}
|
|
29595
|
+
function installAppBundle(source, opts = {}) {
|
|
29596
|
+
if (detectPlatform().os !== "darwin") {
|
|
29597
|
+
throw new Error("Desktop app install is currently macOS-only.");
|
|
29598
|
+
}
|
|
29599
|
+
const home = opts.home ?? homedir();
|
|
29600
|
+
const installDir = opts.installDir ?? defaultInstallDir(home);
|
|
29601
|
+
mkdirSync9(installDir, { recursive: true });
|
|
29602
|
+
const workDir = mkdtempSync(join14(tmpdir(), "dc-app-"));
|
|
29603
|
+
try {
|
|
29604
|
+
const appDir = materializeAppBundle(source, workDir);
|
|
29605
|
+
validateAppBundle(appDir);
|
|
29606
|
+
const target = join14(installDir, APP_BUNDLE_NAME);
|
|
29607
|
+
const staging = join14(installDir, `.${APP_BUNDLE_NAME}.new-${process.pid}`);
|
|
29608
|
+
const backup = join14(installDir, `.${APP_BUNDLE_NAME}.old-${process.pid}`);
|
|
29609
|
+
rmSync2(staging, { recursive: true, force: true });
|
|
29610
|
+
rmSync2(backup, { recursive: true, force: true });
|
|
29611
|
+
let wasRunning;
|
|
29612
|
+
let replaced;
|
|
29613
|
+
try {
|
|
29614
|
+
run("ditto", [appDir, staging]);
|
|
29615
|
+
try {
|
|
29616
|
+
run("xattr", ["-dr", "com.apple.quarantine", staging]);
|
|
29617
|
+
} catch {
|
|
29618
|
+
}
|
|
29619
|
+
wasRunning = isAppRunning();
|
|
29620
|
+
replaced = existsSync14(target);
|
|
29621
|
+
if (replaced) renameSync(target, backup);
|
|
29622
|
+
renameSync(staging, target);
|
|
29623
|
+
} catch (e) {
|
|
29624
|
+
if (existsSync14(target) === false && existsSync14(backup)) {
|
|
29625
|
+
try {
|
|
29626
|
+
renameSync(backup, target);
|
|
29627
|
+
} catch {
|
|
29628
|
+
}
|
|
29629
|
+
}
|
|
29630
|
+
rmSync2(staging, { recursive: true, force: true });
|
|
29631
|
+
throw e;
|
|
29632
|
+
}
|
|
29633
|
+
rmSync2(backup, { recursive: true, force: true });
|
|
29634
|
+
const version = readBundleVersion(target);
|
|
29635
|
+
writeAppManifest(
|
|
29636
|
+
{
|
|
29637
|
+
version: version ?? "unknown",
|
|
29638
|
+
path: target,
|
|
29639
|
+
installedAt: Date.now(),
|
|
29640
|
+
source: opts.sourceLabel ?? "local"
|
|
29641
|
+
},
|
|
29642
|
+
home
|
|
29643
|
+
);
|
|
29644
|
+
const signatureValid = verifyCodesign(target);
|
|
29645
|
+
return { version, path: target, replaced, wasRunning, signatureValid };
|
|
29646
|
+
} finally {
|
|
29647
|
+
rmSync2(workDir, { recursive: true, force: true });
|
|
29648
|
+
}
|
|
29649
|
+
}
|
|
29650
|
+
function versionFromTag(tag) {
|
|
29651
|
+
return tag.replace(/^v/, "");
|
|
29652
|
+
}
|
|
29653
|
+
async function fetchLatestRelease(repo = APP_RELEASE_REPO, fetchImpl = fetch) {
|
|
29654
|
+
try {
|
|
29655
|
+
const res = await fetchImpl(`https://api.github.com/repos/${repo}/releases/latest`, {
|
|
29656
|
+
headers: { Accept: "application/vnd.github+json", "User-Agent": "dreamcontext-cli" }
|
|
29657
|
+
});
|
|
29658
|
+
if (!res.ok) return null;
|
|
29659
|
+
const json = await res.json();
|
|
29660
|
+
if (!json || typeof json.tag_name !== "string" || !Array.isArray(json.assets)) return null;
|
|
29661
|
+
return json;
|
|
29662
|
+
} catch {
|
|
29663
|
+
return null;
|
|
29664
|
+
}
|
|
29665
|
+
}
|
|
29666
|
+
async function downloadTo(url, destFile, fetchImpl = fetch) {
|
|
29667
|
+
const res = await fetchImpl(url, { headers: { "User-Agent": "dreamcontext-cli" } });
|
|
29668
|
+
if (!res.ok) throw new Error(`Download failed (${res.status}): ${url}`);
|
|
29669
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
29670
|
+
writeFileSync13(destFile, buf);
|
|
29671
|
+
}
|
|
29672
|
+
function sha256File(file) {
|
|
29673
|
+
return createHash("sha256").update(readFileSync15(file)).digest("hex");
|
|
29674
|
+
}
|
|
29675
|
+
async function downloadLatestArtifact(repo = APP_RELEASE_REPO, fetchImpl = fetch) {
|
|
29676
|
+
const plat = detectPlatform();
|
|
29677
|
+
if (plat.os !== "darwin") return null;
|
|
29678
|
+
const release2 = await fetchLatestRelease(repo, fetchImpl);
|
|
29679
|
+
if (!release2) return null;
|
|
29680
|
+
const assetName = pickAssetForArch(release2.assets.map((a) => a.name), plat.arch);
|
|
29681
|
+
if (!assetName) return null;
|
|
29682
|
+
const asset = release2.assets.find((a) => a.name === assetName);
|
|
29683
|
+
const sumAsset = release2.assets.find((a) => a.name === `${assetName}.sha256`);
|
|
29684
|
+
if (!sumAsset) {
|
|
29685
|
+
throw new Error(
|
|
29686
|
+
`Release ${release2.tag_name} is missing ${assetName}.sha256 \u2014 refusing to install an unverified binary.`
|
|
29687
|
+
);
|
|
29688
|
+
}
|
|
29689
|
+
const workDir = mkdtempSync(join14(tmpdir(), "dc-app-dl-"));
|
|
29690
|
+
try {
|
|
29691
|
+
const archivePath = join14(workDir, assetName);
|
|
29692
|
+
await downloadTo(asset.browser_download_url, archivePath, fetchImpl);
|
|
29693
|
+
const sumFile = join14(workDir, `${assetName}.sha256`);
|
|
29694
|
+
await downloadTo(sumAsset.browser_download_url, sumFile, fetchImpl);
|
|
29695
|
+
const expected = readFileSync15(sumFile, "utf-8").trim().split(/\s+/)[0].toLowerCase();
|
|
29696
|
+
const actual = sha256File(archivePath).toLowerCase();
|
|
29697
|
+
if (!expected || expected !== actual) {
|
|
29698
|
+
throw new Error(`Checksum mismatch for ${assetName}: expected ${expected || "(empty)"}, got ${actual}`);
|
|
29699
|
+
}
|
|
29700
|
+
return { archivePath, version: versionFromTag(release2.tag_name) };
|
|
29701
|
+
} catch (e) {
|
|
29702
|
+
rmSync2(workDir, { recursive: true, force: true });
|
|
29703
|
+
throw e;
|
|
29704
|
+
}
|
|
29705
|
+
}
|
|
29706
|
+
function appAutoUpdateEnabled(env2 = process.env) {
|
|
29707
|
+
if (env2.DREAMCONTEXT_VERSION_CHECK === "0") return false;
|
|
29708
|
+
return env2.DREAMCONTEXT_APP_AUTO_UPDATE !== "0";
|
|
29709
|
+
}
|
|
29710
|
+
function defaultAppUpdateSpawner() {
|
|
29711
|
+
const child = spawnProcess(process.execPath, [process.argv[1], "app", "update"], {
|
|
29712
|
+
detached: true,
|
|
29713
|
+
stdio: "ignore"
|
|
29714
|
+
});
|
|
29715
|
+
child.unref();
|
|
29716
|
+
}
|
|
29717
|
+
function maybeTriggerAppUpdate(env2 = process.env, deps = {}) {
|
|
29718
|
+
try {
|
|
29719
|
+
if (detectPlatform().os !== "darwin") return false;
|
|
29720
|
+
if (!appAutoUpdateEnabled(env2)) return false;
|
|
29721
|
+
const installed = deps.manifest !== void 0 ? deps.manifest : readAppManifest();
|
|
29722
|
+
if (!installed) return false;
|
|
29723
|
+
(deps.spawner ?? defaultAppUpdateSpawner)();
|
|
29724
|
+
return true;
|
|
29725
|
+
} catch {
|
|
29726
|
+
return false;
|
|
29727
|
+
}
|
|
29728
|
+
}
|
|
29729
|
+
async function doInstall(from, dir) {
|
|
29730
|
+
const plat = detectPlatform();
|
|
29731
|
+
if (plat.os !== "darwin") {
|
|
29732
|
+
console.log(source_default.yellow("The desktop app is currently macOS-only. Windows/Linux support is planned."));
|
|
29733
|
+
return;
|
|
29734
|
+
}
|
|
29735
|
+
let tempToClean = null;
|
|
29736
|
+
let source = from;
|
|
29737
|
+
let sourceLabel = "local";
|
|
29738
|
+
if (!source) {
|
|
29739
|
+
console.log(source_default.cyan("Fetching the latest desktop app from GitHub Releases\u2026"));
|
|
29740
|
+
let dl = null;
|
|
29741
|
+
try {
|
|
29742
|
+
dl = await downloadLatestArtifact();
|
|
29743
|
+
} catch (e) {
|
|
29744
|
+
console.log(source_default.red(`Install aborted: ${e.message}`));
|
|
29745
|
+
return;
|
|
29746
|
+
}
|
|
29747
|
+
if (!dl) {
|
|
29748
|
+
console.log(
|
|
29749
|
+
source_default.yellow(
|
|
29750
|
+
"No published desktop release found yet.\nBuild one locally and install it with: dreamcontext app install --from <path-to.app|.tar.gz>"
|
|
29751
|
+
)
|
|
29752
|
+
);
|
|
29753
|
+
return;
|
|
29754
|
+
}
|
|
29755
|
+
source = dl.archivePath;
|
|
29756
|
+
sourceLabel = "github";
|
|
29757
|
+
tempToClean = dirname9(dl.archivePath);
|
|
29758
|
+
}
|
|
29759
|
+
try {
|
|
29760
|
+
const res = installAppBundle(source, { installDir: dir, sourceLabel });
|
|
29761
|
+
console.log(source_default.green(`\u2713 Installed dreamcontext-beta ${res.version ?? ""}`.trim()) + source_default.dim(` \u2192 ${res.path}`));
|
|
29762
|
+
if (res.signatureValid === false) {
|
|
29763
|
+
console.log(
|
|
29764
|
+
source_default.yellow(
|
|
29765
|
+
"Warning: the installed app failed code-signature verification. It may still launch (ad-hoc),\nbut the published artifact should be properly ad-hoc deep-signed at build time."
|
|
29766
|
+
)
|
|
29767
|
+
);
|
|
29768
|
+
}
|
|
29769
|
+
if (res.wasRunning) {
|
|
29770
|
+
console.log(source_default.yellow("The app is currently running \u2014 restart it to apply the update."));
|
|
29771
|
+
} else {
|
|
29772
|
+
console.log(source_default.dim(`Launch it: open "${res.path}"`));
|
|
29773
|
+
}
|
|
29774
|
+
} finally {
|
|
29775
|
+
if (tempToClean) rmSync2(tempToClean, { recursive: true, force: true });
|
|
29776
|
+
}
|
|
29777
|
+
}
|
|
29778
|
+
async function doUpdate(from, dir) {
|
|
29779
|
+
const installed = readAppManifest();
|
|
29780
|
+
if (!installed) {
|
|
29781
|
+
console.log(source_default.dim("No installed app recorded \u2014 running a fresh install."));
|
|
29782
|
+
await doInstall(from, dir);
|
|
29783
|
+
return;
|
|
29784
|
+
}
|
|
29785
|
+
if (from) {
|
|
29786
|
+
await doInstall(from, dir);
|
|
29787
|
+
return;
|
|
29788
|
+
}
|
|
29789
|
+
let dl = null;
|
|
29790
|
+
try {
|
|
29791
|
+
dl = await downloadLatestArtifact();
|
|
29792
|
+
} catch (e) {
|
|
29793
|
+
console.log(source_default.red(`Update aborted: ${e.message}`));
|
|
29794
|
+
return;
|
|
29795
|
+
}
|
|
29796
|
+
if (!dl) {
|
|
29797
|
+
console.log(source_default.yellow("No published desktop release available to update to."));
|
|
29798
|
+
return;
|
|
29799
|
+
}
|
|
29800
|
+
try {
|
|
29801
|
+
if (compareVersions(installed.version, dl.version) >= 0) {
|
|
29802
|
+
console.log(source_default.green(`Desktop app is up to date (${installed.version}).`));
|
|
29803
|
+
return;
|
|
29804
|
+
}
|
|
29805
|
+
const res = installAppBundle(dl.archivePath, { installDir: dir, sourceLabel: "github" });
|
|
29806
|
+
console.log(source_default.green(`\u2713 Updated dreamcontext-beta ${installed.version} \u2192 ${res.version ?? dl.version}`));
|
|
29807
|
+
if (res.wasRunning) console.log(source_default.yellow("Restart the app to apply the update."));
|
|
29808
|
+
} finally {
|
|
29809
|
+
rmSync2(dirname9(dl.archivePath), { recursive: true, force: true });
|
|
29810
|
+
}
|
|
29811
|
+
}
|
|
29812
|
+
function doStatus() {
|
|
29813
|
+
const installed = readAppManifest();
|
|
29814
|
+
if (!installed) {
|
|
29815
|
+
console.log("Desktop app: not installed (run `dreamcontext app install`).");
|
|
29816
|
+
return;
|
|
29817
|
+
}
|
|
29818
|
+
const onDisk = existsSync14(installed.path);
|
|
29819
|
+
console.log(`Desktop app: ${installed.version}`);
|
|
29820
|
+
console.log(` path: ${installed.path}${onDisk ? "" : source_default.red(" (missing!)")}`);
|
|
29821
|
+
console.log(` source: ${installed.source}`);
|
|
29822
|
+
console.log(` running: ${isAppRunning() ? "yes" : "no"}`);
|
|
29823
|
+
}
|
|
29824
|
+
function registerAppCommand(program2) {
|
|
29825
|
+
const app = program2.command("app").description("Manage the dreamcontext desktop app (install / update / status)");
|
|
29826
|
+
app.command("install").description("Install the desktop app to ~/Applications (no quarantine, no admin)").option("--from <path>", "Install from a local .app, .tar.gz, or .zip instead of GitHub Releases").option("--dir <dir>", "Install directory (default: ~/Applications)").action(async (opts) => {
|
|
29827
|
+
await doInstall(opts.from, opts.dir);
|
|
29828
|
+
});
|
|
29829
|
+
app.command("update").description("Update the installed desktop app to the latest version").option("--from <path>", "Update from a local artifact instead of GitHub Releases").option("--dir <dir>", "Install directory (default: ~/Applications)").action(async (opts) => {
|
|
29830
|
+
await doUpdate(opts.from, opts.dir);
|
|
29831
|
+
});
|
|
29832
|
+
app.command("status").description("Show the installed desktop app version and state").action(() => {
|
|
29833
|
+
doStatus();
|
|
29834
|
+
});
|
|
29835
|
+
}
|
|
29836
|
+
var APP_BUNDLE_NAME, APP_RELEASE_REPO;
|
|
29837
|
+
var init_app = __esm({
|
|
29838
|
+
"src/cli/commands/app.ts"() {
|
|
29839
|
+
"use strict";
|
|
29840
|
+
init_source();
|
|
29841
|
+
init_version_check();
|
|
29842
|
+
APP_BUNDLE_NAME = "dreamcontext-beta.app";
|
|
29843
|
+
APP_RELEASE_REPO = "meanllbrl/dreamcontext";
|
|
29844
|
+
}
|
|
29845
|
+
});
|
|
29846
|
+
|
|
29292
29847
|
// src/cli/commands/setup.ts
|
|
29293
29848
|
var setup_exports = {};
|
|
29294
29849
|
__export(setup_exports, {
|
|
@@ -29296,7 +29851,8 @@ __export(setup_exports, {
|
|
|
29296
29851
|
registerSetupCommand: () => registerSetupCommand,
|
|
29297
29852
|
runSetup: () => runSetup
|
|
29298
29853
|
});
|
|
29299
|
-
import { existsSync as
|
|
29854
|
+
import { existsSync as existsSync15 } from "fs";
|
|
29855
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
29300
29856
|
function parsePlatformsOption3(raw) {
|
|
29301
29857
|
if (!raw) return [];
|
|
29302
29858
|
const parsed = parsePlatformList(raw);
|
|
@@ -29355,6 +29911,38 @@ async function installPlatformIntegration(projectRoot, opts) {
|
|
|
29355
29911
|
});
|
|
29356
29912
|
return { installed, notes, fileCount: Object.keys(manifest.files).length };
|
|
29357
29913
|
}
|
|
29914
|
+
async function maybeInstallApp(opts) {
|
|
29915
|
+
if (opts.skipApp) return;
|
|
29916
|
+
if (process.env.DREAMCONTEXT_INSTALL_NO_APP === "1") return;
|
|
29917
|
+
try {
|
|
29918
|
+
if (detectPlatform().os !== "darwin") return;
|
|
29919
|
+
} catch {
|
|
29920
|
+
return;
|
|
29921
|
+
}
|
|
29922
|
+
const installed = (opts.appInstalledCheck ?? (() => readAppManifest() !== null))();
|
|
29923
|
+
if (installed) {
|
|
29924
|
+
info(source_default.dim("Desktop app already installed \u2014 skipping."));
|
|
29925
|
+
return;
|
|
29926
|
+
}
|
|
29927
|
+
const interactive = process.stdin.isTTY === true && !opts.defaults;
|
|
29928
|
+
let proceed = opts.installApp === true || !!opts.yes && interactive;
|
|
29929
|
+
if (!proceed && interactive) {
|
|
29930
|
+
proceed = await esm_default4({
|
|
29931
|
+
message: "Install the macOS desktop app too? (manage all your vaults in one window)",
|
|
29932
|
+
default: true
|
|
29933
|
+
});
|
|
29934
|
+
}
|
|
29935
|
+
if (!proceed) {
|
|
29936
|
+
info(source_default.dim("Desktop app not installed \u2014 add it anytime with `dreamcontext app install`."));
|
|
29937
|
+
return;
|
|
29938
|
+
}
|
|
29939
|
+
info("Installing the desktop app...");
|
|
29940
|
+
try {
|
|
29941
|
+
(opts.appInstaller ?? (() => execFileSync3("npx", ["dreamcontext", "app", "install"], { stdio: "inherit" })))();
|
|
29942
|
+
} catch (e) {
|
|
29943
|
+
info(source_default.yellow(`Desktop app install skipped: ${e.message}`));
|
|
29944
|
+
}
|
|
29945
|
+
}
|
|
29358
29946
|
async function runSetup(opts) {
|
|
29359
29947
|
const projectRoot = process.cwd();
|
|
29360
29948
|
const useDefaults = !!opts.defaults;
|
|
@@ -29418,7 +30006,7 @@ async function runSetup(opts) {
|
|
|
29418
30006
|
}
|
|
29419
30007
|
}
|
|
29420
30008
|
const contextDir = getInitPath();
|
|
29421
|
-
if (!
|
|
30009
|
+
if (!existsSync15(contextDir)) {
|
|
29422
30010
|
info("Running init...");
|
|
29423
30011
|
const { registerInitCommand: registerInitCommand2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
29424
30012
|
const tempProgram = new Command();
|
|
@@ -29438,6 +30026,7 @@ async function runSetup(opts) {
|
|
|
29438
30026
|
multiProduct,
|
|
29439
30027
|
disableNativeMemory
|
|
29440
30028
|
});
|
|
30029
|
+
await maybeInstallApp(opts);
|
|
29441
30030
|
const manifestPath2 = "_dream_context/state/.install-manifest.json";
|
|
29442
30031
|
console.log();
|
|
29443
30032
|
console.log(miniBox([
|
|
@@ -29464,7 +30053,7 @@ async function runSetup(opts) {
|
|
|
29464
30053
|
}
|
|
29465
30054
|
}
|
|
29466
30055
|
function registerSetupCommand(program2) {
|
|
29467
|
-
program2.command("setup").description("One-shot setup: init + install-skill + install-instructions").option("--defaults", "Skip prompts; use claude platform, no packs, single-product").option("-y, --yes", "Accept all confirmation prompts").option("--platforms <list>", `Comma-separated platforms: ${formatSupportedPlatforms()}`).option("--packs <list>", "Comma-separated pack names to install").option("--multi-product <list>", "Comma-separated product names for multi-product setup").option("--keep-native-memory", "Keep Claude Code's native auto-memory (default: disabled so dreamcontext owns memory)").action(async (opts) => {
|
|
30056
|
+
program2.command("setup").description("One-shot setup: init + install-skill + install-instructions").option("--defaults", "Skip prompts; use claude platform, no packs, single-product").option("-y, --yes", "Accept all confirmation prompts").option("--platforms <list>", `Comma-separated platforms: ${formatSupportedPlatforms()}`).option("--packs <list>", "Comma-separated pack names to install").option("--multi-product <list>", "Comma-separated product names for multi-product setup").option("--keep-native-memory", "Keep Claude Code's native auto-memory (default: disabled so dreamcontext owns memory)").option("--install-app", "Also install the macOS desktop app (non-interactive)").option("--skip-app", "Do not install the desktop app").action(async (opts) => {
|
|
29468
30057
|
try {
|
|
29469
30058
|
await runSetup(opts);
|
|
29470
30059
|
} catch (err) {
|
|
@@ -29485,6 +30074,7 @@ var init_setup = __esm({
|
|
|
29485
30074
|
init_source();
|
|
29486
30075
|
init_esm16();
|
|
29487
30076
|
init_format();
|
|
30077
|
+
init_app();
|
|
29488
30078
|
init_context_path();
|
|
29489
30079
|
init_platforms();
|
|
29490
30080
|
init_install_skill();
|
|
@@ -29501,27 +30091,27 @@ var init_exports = {};
|
|
|
29501
30091
|
__export(init_exports, {
|
|
29502
30092
|
registerInitCommand: () => registerInitCommand
|
|
29503
30093
|
});
|
|
29504
|
-
import { existsSync as
|
|
29505
|
-
import { join as
|
|
30094
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync16, writeFileSync as writeFileSync14, copyFileSync as copyFileSync2, readdirSync as readdirSync6, statSync as statSync2 } from "fs";
|
|
30095
|
+
import { join as join15 } from "path";
|
|
29506
30096
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
29507
30097
|
function getTemplateDir(subdir = "init") {
|
|
29508
30098
|
const candidates = [
|
|
29509
|
-
|
|
29510
|
-
|
|
29511
|
-
|
|
30099
|
+
join15(__dirname5, "..", "..", "templates", subdir),
|
|
30100
|
+
join15(__dirname5, "..", "templates", subdir),
|
|
30101
|
+
join15(__dirname5, "templates", subdir)
|
|
29512
30102
|
];
|
|
29513
30103
|
for (const dir of candidates) {
|
|
29514
|
-
if (
|
|
30104
|
+
if (existsSync16(dir)) return dir;
|
|
29515
30105
|
}
|
|
29516
|
-
return
|
|
30106
|
+
return join15(__dirname5, "..", "..", "templates", subdir);
|
|
29517
30107
|
}
|
|
29518
30108
|
function copyObsidianConfig(destDir) {
|
|
29519
30109
|
const src = getTemplateDir("obsidian");
|
|
29520
|
-
if (!
|
|
29521
|
-
|
|
29522
|
-
for (const entry of
|
|
29523
|
-
const from =
|
|
29524
|
-
const to =
|
|
30110
|
+
if (!existsSync16(src)) return false;
|
|
30111
|
+
mkdirSync10(destDir, { recursive: true });
|
|
30112
|
+
for (const entry of readdirSync6(src)) {
|
|
30113
|
+
const from = join15(src, entry);
|
|
30114
|
+
const to = join15(destDir, entry);
|
|
29525
30115
|
if (statSync2(from).isFile()) {
|
|
29526
30116
|
copyFileSync2(from, to);
|
|
29527
30117
|
}
|
|
@@ -29538,7 +30128,7 @@ function replaceTokens(content, tokens) {
|
|
|
29538
30128
|
function registerInitCommand(program2) {
|
|
29539
30129
|
program2.command("init").description("Initialize _dream_context/ in the current directory").option("-y, --yes", "Skip prompts and use defaults").option("--name <name>", "Project name").option("--description <desc>", "Project description").option("--user <user>", "Target user").option("--stack <stack>", "Tech stack").option("--priority <priority>", "Current priority").option("--platforms <list>", `Comma-separated platforms: ${formatSupportedPlatforms()}`).option("--multi-product <list>", "Comma-separated product names for monorepos (lowercase kebab-case). Skips the interactive prompt.").action(async (opts) => {
|
|
29540
30130
|
const contextDir = getInitPath();
|
|
29541
|
-
if (
|
|
30131
|
+
if (existsSync16(contextDir)) {
|
|
29542
30132
|
error("_dream_context/ already exists in this directory.");
|
|
29543
30133
|
return;
|
|
29544
30134
|
}
|
|
@@ -29643,13 +30233,13 @@ function registerInitCommand(program2) {
|
|
|
29643
30233
|
PRIORITY: priority,
|
|
29644
30234
|
DATE: dateStr
|
|
29645
30235
|
};
|
|
29646
|
-
|
|
29647
|
-
|
|
29648
|
-
|
|
29649
|
-
|
|
29650
|
-
|
|
29651
|
-
|
|
29652
|
-
const obsidianInstalled = copyObsidianConfig(
|
|
30236
|
+
mkdirSync10(join15(contextDir, "core", "features"), { recursive: true });
|
|
30237
|
+
mkdirSync10(join15(contextDir, "knowledge"), { recursive: true });
|
|
30238
|
+
mkdirSync10(join15(contextDir, "knowledge", "data-structures"), { recursive: true });
|
|
30239
|
+
mkdirSync10(join15(contextDir, "knowledge", "products"), { recursive: true });
|
|
30240
|
+
mkdirSync10(join15(contextDir, "state"), { recursive: true });
|
|
30241
|
+
mkdirSync10(join15(contextDir, "inbox"), { recursive: true });
|
|
30242
|
+
const obsidianInstalled = copyObsidianConfig(join15(contextDir, ".obsidian"));
|
|
29653
30243
|
const templateDir = getTemplateDir();
|
|
29654
30244
|
const templateFiles = [
|
|
29655
30245
|
"0.soul.md",
|
|
@@ -29659,26 +30249,26 @@ function registerInitCommand(program2) {
|
|
|
29659
30249
|
"4.tech_stack.md"
|
|
29660
30250
|
];
|
|
29661
30251
|
for (const file of templateFiles) {
|
|
29662
|
-
const templatePath =
|
|
29663
|
-
const destPath =
|
|
29664
|
-
if (
|
|
29665
|
-
const content =
|
|
29666
|
-
|
|
30252
|
+
const templatePath = join15(templateDir, file);
|
|
30253
|
+
const destPath = join15(contextDir, "core", file);
|
|
30254
|
+
if (existsSync16(templatePath)) {
|
|
30255
|
+
const content = readFileSync16(templatePath, "utf-8");
|
|
30256
|
+
writeFileSync14(destPath, replaceTokens(content, tokens), "utf-8");
|
|
29667
30257
|
} else {
|
|
29668
|
-
|
|
30258
|
+
writeFileSync14(destPath, `# ${file}
|
|
29669
30259
|
|
|
29670
30260
|
Created: ${dateStr}
|
|
29671
30261
|
`, "utf-8");
|
|
29672
30262
|
}
|
|
29673
30263
|
}
|
|
29674
|
-
const dataStructuresTemplate =
|
|
30264
|
+
const dataStructuresTemplate = join15(templateDir, "data-structures", "default.md");
|
|
29675
30265
|
const dataStructuresFallback = "---\nname: {{PRODUCT_NAME}}\ndescription: Data structures for {{PRODUCT_NAME}}\ntype: data-structures\nproduct: {{PRODUCT_NAME}}\ntags:\n - data-structures\n - database\n - schema\nupdated: {{DATE}}\n---\n\n# Data Structures \u2014 {{PRODUCT_NAME}}\n\nDocument schemas, models, and API contracts here.\n";
|
|
29676
|
-
const dsTemplateContent =
|
|
30266
|
+
const dsTemplateContent = existsSync16(dataStructuresTemplate) ? readFileSync16(dataStructuresTemplate, "utf-8") : dataStructuresFallback;
|
|
29677
30267
|
const productList = multiProduct === false ? ["default"] : multiProduct;
|
|
29678
30268
|
for (const product of productList) {
|
|
29679
30269
|
const productTokens = { ...tokens, PRODUCT_NAME: product };
|
|
29680
|
-
const destPath =
|
|
29681
|
-
|
|
30270
|
+
const destPath = join15(contextDir, "knowledge", "data-structures", `${product}.md`);
|
|
30271
|
+
writeFileSync14(destPath, replaceTokens(dsTemplateContent, productTokens), "utf-8");
|
|
29682
30272
|
}
|
|
29683
30273
|
if (multiProduct !== false) {
|
|
29684
30274
|
for (const product of multiProduct) {
|
|
@@ -29695,12 +30285,12 @@ tags:
|
|
|
29695
30285
|
|
|
29696
30286
|
Product-scoped knowledge. Cross-cutting findings still go to top-level \`knowledge/\`.
|
|
29697
30287
|
`;
|
|
29698
|
-
|
|
30288
|
+
writeFileSync14(join15(contextDir, "knowledge", "products", `${product}.md`), knowledgeStub, "utf-8");
|
|
29699
30289
|
}
|
|
29700
30290
|
}
|
|
29701
30291
|
const jsonFiles = ["CHANGELOG.json", "RELEASES.json"];
|
|
29702
30292
|
for (const file of jsonFiles) {
|
|
29703
|
-
|
|
30293
|
+
writeFileSync14(join15(contextDir, "core", file), "[]\n", "utf-8");
|
|
29704
30294
|
}
|
|
29705
30295
|
ensureTaxonomyFile(contextDir);
|
|
29706
30296
|
updateSetupConfig(process.cwd(), {
|
|
@@ -29709,7 +30299,7 @@ Product-scoped knowledge. Cross-cutting findings still go to top-level \`knowled
|
|
|
29709
30299
|
setupVersion: dreamcontextVersion()
|
|
29710
30300
|
});
|
|
29711
30301
|
writeProjectPlatformDefaults(process.cwd(), selectedPlatforms);
|
|
29712
|
-
insertToJsonArray(
|
|
30302
|
+
insertToJsonArray(join15(contextDir, "core", "CHANGELOG.json"), {
|
|
29713
30303
|
date: dateStr,
|
|
29714
30304
|
type: "chore",
|
|
29715
30305
|
scope: "project",
|
|
@@ -29760,7 +30350,7 @@ Product-scoped knowledge. Cross-cutting findings still go to top-level \`knowled
|
|
|
29760
30350
|
}
|
|
29761
30351
|
const viaSetup = process.env[SETUP_INTERNAL_ENV] === "1";
|
|
29762
30352
|
const integrationPresent = selectedPlatforms.every(
|
|
29763
|
-
(p) =>
|
|
30353
|
+
(p) => existsSync16(join15(platformSkillRoot(process.cwd(), p), "dreamcontext", "SKILL.md"))
|
|
29764
30354
|
);
|
|
29765
30355
|
let integrationInstalled = false;
|
|
29766
30356
|
if (!viaSetup && !integrationPresent && !useDefaults && process.stdin.isTTY) {
|
|
@@ -29841,14 +30431,14 @@ var init_init = __esm({
|
|
|
29841
30431
|
});
|
|
29842
30432
|
|
|
29843
30433
|
// src/lib/release-discovery.ts
|
|
29844
|
-
import { join as
|
|
29845
|
-
import { existsSync as
|
|
30434
|
+
import { join as join16, basename as basename4 } from "path";
|
|
30435
|
+
import { existsSync as existsSync17 } from "fs";
|
|
29846
30436
|
function changelogFingerprint(entry) {
|
|
29847
30437
|
return `${entry.date}|${entry.type}|${entry.scope}|${entry.description}`;
|
|
29848
30438
|
}
|
|
29849
30439
|
function getExistingReleases(root) {
|
|
29850
|
-
const releasesPath =
|
|
29851
|
-
if (!
|
|
30440
|
+
const releasesPath = join16(root, "core", "RELEASES.json");
|
|
30441
|
+
if (!existsSync17(releasesPath)) return [];
|
|
29852
30442
|
try {
|
|
29853
30443
|
const entries = readJsonArray(releasesPath);
|
|
29854
30444
|
for (const entry of entries) {
|
|
@@ -29862,8 +30452,8 @@ function getExistingReleases(root) {
|
|
|
29862
30452
|
function findUnreleasedTasks(root) {
|
|
29863
30453
|
const releases = getExistingReleases(root);
|
|
29864
30454
|
const releasedTaskIds = new Set(releases.flatMap((r) => r.tasks ?? []));
|
|
29865
|
-
const stateDir =
|
|
29866
|
-
if (!
|
|
30455
|
+
const stateDir = join16(root, "state");
|
|
30456
|
+
if (!existsSync17(stateDir)) return [];
|
|
29867
30457
|
const files = import_fast_glob2.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
29868
30458
|
const result = [];
|
|
29869
30459
|
for (const file of files) {
|
|
@@ -29884,8 +30474,8 @@ function findUnreleasedTasks(root) {
|
|
|
29884
30474
|
return result;
|
|
29885
30475
|
}
|
|
29886
30476
|
function findUnreleasedFeatures(root) {
|
|
29887
|
-
const featuresDir =
|
|
29888
|
-
if (!
|
|
30477
|
+
const featuresDir = join16(root, "core", "features");
|
|
30478
|
+
if (!existsSync17(featuresDir)) return [];
|
|
29889
30479
|
const files = import_fast_glob2.default.sync("*.md", { cwd: featuresDir, absolute: true });
|
|
29890
30480
|
const result = [];
|
|
29891
30481
|
for (const file of files) {
|
|
@@ -29910,8 +30500,8 @@ function findUnreleasedChangelog(root) {
|
|
|
29910
30500
|
releasedFingerprints.add(changelogFingerprint(entry));
|
|
29911
30501
|
}
|
|
29912
30502
|
}
|
|
29913
|
-
const changelogPath =
|
|
29914
|
-
if (!
|
|
30503
|
+
const changelogPath = join16(root, "core", "CHANGELOG.json");
|
|
30504
|
+
if (!existsSync17(changelogPath)) return [];
|
|
29915
30505
|
try {
|
|
29916
30506
|
const entries = readJsonArray(changelogPath);
|
|
29917
30507
|
const result = [];
|
|
@@ -29937,11 +30527,11 @@ var init_release_discovery = __esm({
|
|
|
29937
30527
|
});
|
|
29938
30528
|
|
|
29939
30529
|
// src/lib/release-backpopulate.ts
|
|
29940
|
-
import { join as
|
|
29941
|
-
import { existsSync as
|
|
30530
|
+
import { join as join17 } from "path";
|
|
30531
|
+
import { existsSync as existsSync18 } from "fs";
|
|
29942
30532
|
function backPopulateFeatures(root, featureIds, version) {
|
|
29943
|
-
const featuresDir =
|
|
29944
|
-
if (!
|
|
30533
|
+
const featuresDir = join17(root, "core", "features");
|
|
30534
|
+
if (!existsSync18(featuresDir)) return;
|
|
29945
30535
|
const files = import_fast_glob3.default.sync("*.md", { cwd: featuresDir, absolute: true });
|
|
29946
30536
|
const idSet = new Set(featureIds);
|
|
29947
30537
|
for (const file of files) {
|
|
@@ -29969,14 +30559,14 @@ var init_release_backpopulate = __esm({
|
|
|
29969
30559
|
});
|
|
29970
30560
|
|
|
29971
30561
|
// src/lib/active-version.ts
|
|
29972
|
-
import { existsSync as
|
|
29973
|
-
import { join as
|
|
30562
|
+
import { existsSync as existsSync19 } from "fs";
|
|
30563
|
+
import { join as join18 } from "path";
|
|
29974
30564
|
function statePath() {
|
|
29975
|
-
return
|
|
30565
|
+
return join18(ensureContextRoot(), "state", ".active-version.json");
|
|
29976
30566
|
}
|
|
29977
30567
|
function getActivePlanningVersion() {
|
|
29978
30568
|
const path2 = statePath();
|
|
29979
|
-
if (!
|
|
30569
|
+
if (!existsSync19(path2)) return null;
|
|
29980
30570
|
let stored;
|
|
29981
30571
|
try {
|
|
29982
30572
|
const data = readJsonObject(path2);
|
|
@@ -30018,13 +30608,13 @@ var init_active_version = __esm({
|
|
|
30018
30608
|
});
|
|
30019
30609
|
|
|
30020
30610
|
// src/cli/commands/core.ts
|
|
30021
|
-
import { join as
|
|
30611
|
+
import { join as join19 } from "path";
|
|
30022
30612
|
function registerCoreCommand(program2) {
|
|
30023
30613
|
const core = program2.command("core").description("Add changelog and release entries");
|
|
30024
30614
|
const changelog = core.command("changelog").description("Manage CHANGELOG.json");
|
|
30025
30615
|
changelog.command("add").description("Add a changelog entry").option("--type <type>", "Type (feat|fix|refactor|chore|docs|perf|test|change)").option("--scope <scope>", "Scope (e.g., auth, ui, api)").option("--description <desc>", "Description (long-form, full body)").option("--summary <summary>", "Optional \u2264200-char one-liner for snapshot display").option("--references <refs>", "Optional comma-separated references (commit:<sha>, file:<path>, knowledge:<slug>, feature:<slug>, task:<slug>, url:<href>)").option("--authors <list>", 'Optional comma-separated people involved (e.g. "mehmet,ada")').option("--supersedes <key>", 'Optional pointer to prior entry this supersedes (e.g., "2026-05-09|sleep")').option("--breaking", "Mark as a breaking change", false).action(async (opts) => {
|
|
30026
30616
|
const root = ensureContextRoot();
|
|
30027
|
-
const filePath =
|
|
30617
|
+
const filePath = join19(root, "core", "CHANGELOG.json");
|
|
30028
30618
|
const type = opts.type ?? await esm_default11({
|
|
30029
30619
|
message: "Type:",
|
|
30030
30620
|
choices: [
|
|
@@ -30078,7 +30668,7 @@ function registerCoreCommand(program2) {
|
|
|
30078
30668
|
const releases = core.command("releases").description("Manage RELEASES.json");
|
|
30079
30669
|
releases.command("add").description("Create a release with auto-discovered tasks, features, and changelog entries").option("-V, --ver <version>", "Version string (e.g., 1.2.0)").option("-s, --summary <summary>", "Release summary").option("--status <status>", "Release status: planning or released (default: released)").option("-y, --yes", "Skip interactive selection, include all discovered items").action(async (opts) => {
|
|
30080
30670
|
const root = ensureContextRoot();
|
|
30081
|
-
const releasesPath =
|
|
30671
|
+
const releasesPath = join19(root, "core", "RELEASES.json");
|
|
30082
30672
|
const auto = !!opts.yes;
|
|
30083
30673
|
const releaseStatus = opts.status === "planning" ? "planning" : "released";
|
|
30084
30674
|
const version = opts.ver ?? (auto ? "" : await esm_default5({ message: "Version (e.g., 1.2.0):" }));
|
|
@@ -30283,7 +30873,7 @@ var init_core = __esm({
|
|
|
30283
30873
|
});
|
|
30284
30874
|
|
|
30285
30875
|
// src/lib/markdown.ts
|
|
30286
|
-
import { readFileSync as
|
|
30876
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
30287
30877
|
function parseSections(content) {
|
|
30288
30878
|
const lines = content.split("\n");
|
|
30289
30879
|
const sections = [];
|
|
@@ -30311,13 +30901,13 @@ function findSection(sections, sectionName) {
|
|
|
30311
30901
|
return sections.find((s) => normalizeName(s.name) === normalized) ?? null;
|
|
30312
30902
|
}
|
|
30313
30903
|
function listSections(filePath) {
|
|
30314
|
-
const raw =
|
|
30904
|
+
const raw = readFileSync17(filePath, "utf-8");
|
|
30315
30905
|
const parsed = (0, import_gray_matter3.default)(raw);
|
|
30316
30906
|
const sections = parseSections(parsed.content);
|
|
30317
30907
|
return sections.map((s) => s.name);
|
|
30318
30908
|
}
|
|
30319
30909
|
function readSection(filePath, sectionName) {
|
|
30320
|
-
const raw =
|
|
30910
|
+
const raw = readFileSync17(filePath, "utf-8");
|
|
30321
30911
|
const parsed = (0, import_gray_matter3.default)(raw);
|
|
30322
30912
|
const sections = parseSections(parsed.content);
|
|
30323
30913
|
const section2 = findSection(sections, sectionName);
|
|
@@ -30373,7 +30963,7 @@ function stripPlaceholderBody(lines, section2) {
|
|
|
30373
30963
|
return originalCount - kept.length;
|
|
30374
30964
|
}
|
|
30375
30965
|
function insertToSection(filePath, sectionName, newContent, position = "top", createIfMissing = false, replacePlaceholders = false) {
|
|
30376
|
-
const raw =
|
|
30966
|
+
const raw = readFileSync17(filePath, "utf-8");
|
|
30377
30967
|
const parsed = (0, import_gray_matter3.default)(raw);
|
|
30378
30968
|
let lines = parsed.content.split("\n");
|
|
30379
30969
|
let section2 = findSection(parseSections(lines.join("\n")), sectionName);
|
|
@@ -30405,7 +30995,7 @@ function insertToSection(filePath, sectionName, newContent, position = "top", cr
|
|
|
30405
30995
|
lines.splice(insertAt, 0, ...block);
|
|
30406
30996
|
}
|
|
30407
30997
|
const output = import_gray_matter3.default.stringify(lines.join("\n"), parsed.data);
|
|
30408
|
-
|
|
30998
|
+
writeFileSync15(filePath, output, "utf-8");
|
|
30409
30999
|
}
|
|
30410
31000
|
function extractMermaidNodes(content) {
|
|
30411
31001
|
const fence = content.match(/```mermaid\s+([\s\S]*?)```/);
|
|
@@ -30609,20 +31199,20 @@ var init_feature_freshness = __esm({
|
|
|
30609
31199
|
});
|
|
30610
31200
|
|
|
30611
31201
|
// src/cli/commands/features.ts
|
|
30612
|
-
import { existsSync as
|
|
30613
|
-
import { join as
|
|
31202
|
+
import { existsSync as existsSync20, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
31203
|
+
import { join as join20, basename as basename5 } from "path";
|
|
30614
31204
|
function parseCsv(value) {
|
|
30615
31205
|
return value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
30616
31206
|
}
|
|
30617
31207
|
function getFeaturesDir() {
|
|
30618
31208
|
const root = ensureContextRoot();
|
|
30619
|
-
return
|
|
31209
|
+
return join20(root, "core", "features");
|
|
30620
31210
|
}
|
|
30621
31211
|
function findFeatureFile(name) {
|
|
30622
31212
|
const dir = getFeaturesDir();
|
|
30623
31213
|
const slug = slugify(name);
|
|
30624
|
-
const exact =
|
|
30625
|
-
if (
|
|
31214
|
+
const exact = join20(dir, `${slug}.md`);
|
|
31215
|
+
if (existsSync20(exact)) return exact;
|
|
30626
31216
|
const files = import_fast_glob4.default.sync("*.md", { cwd: dir, absolute: true });
|
|
30627
31217
|
const exactGlob = files.find((f) => basename5(f, ".md") === slug);
|
|
30628
31218
|
if (exactGlob) return exactGlob;
|
|
@@ -30642,12 +31232,12 @@ function findFeatureFile(name) {
|
|
|
30642
31232
|
}
|
|
30643
31233
|
function getFeatureTemplate() {
|
|
30644
31234
|
const candidates = [
|
|
30645
|
-
|
|
30646
|
-
|
|
31235
|
+
join20(new URL(".", import.meta.url).pathname, "..", "..", "templates", "feature.md"),
|
|
31236
|
+
join20(new URL(".", import.meta.url).pathname, "..", "templates", "feature.md")
|
|
30647
31237
|
];
|
|
30648
31238
|
for (const path2 of candidates) {
|
|
30649
|
-
if (
|
|
30650
|
-
return
|
|
31239
|
+
if (existsSync20(path2)) {
|
|
31240
|
+
return readFileSync18(path2, "utf-8");
|
|
30651
31241
|
}
|
|
30652
31242
|
}
|
|
30653
31243
|
return `---
|
|
@@ -30695,8 +31285,8 @@ function registerFeaturesCommand(program2) {
|
|
|
30695
31285
|
features.command("create").argument("<name>").option("-w, --why <why>", "Why are we building this?").option("-t, --tags <tags>", "Comma-separated tags").option("-s, --status <status>", `Status (${VALID_FEATURE_STATUSES.join(", ")})`).option("--related-tasks <slugs>", "Comma-separated related task slugs").description("Create a new feature document").action(async (name, opts) => {
|
|
30696
31286
|
const dir = getFeaturesDir();
|
|
30697
31287
|
const slug = slugify(name);
|
|
30698
|
-
const filePath =
|
|
30699
|
-
if (
|
|
31288
|
+
const filePath = join20(dir, `${slug}.md`);
|
|
31289
|
+
if (existsSync20(filePath)) {
|
|
30700
31290
|
error(`Feature already exists: ${slug}.md`);
|
|
30701
31291
|
return;
|
|
30702
31292
|
}
|
|
@@ -30707,7 +31297,7 @@ function registerFeaturesCommand(program2) {
|
|
|
30707
31297
|
const why = opts.why || await promptInput({ message: "Why are we building this?" });
|
|
30708
31298
|
const template = getFeatureTemplate();
|
|
30709
31299
|
const content = template.replaceAll("{{ID}}", generateId("feat")).replaceAll("{{DATE}}", today()).replaceAll("{{WHY}}", why || "(To be defined)");
|
|
30710
|
-
|
|
31300
|
+
writeFileSync16(filePath, content, "utf-8");
|
|
30711
31301
|
const fields = {};
|
|
30712
31302
|
if (opts.tags) fields.tags = parseCsv(opts.tags);
|
|
30713
31303
|
if (opts.status) fields.status = opts.status;
|
|
@@ -30773,8 +31363,8 @@ function registerFeaturesCommand(program2) {
|
|
|
30773
31363
|
features.command("doctor").description("Check feature PRDs for staleness, orphans, and dangling task references (read-only)").action(() => {
|
|
30774
31364
|
const root = ensureContextRoot();
|
|
30775
31365
|
const featuresDir = getFeaturesDir();
|
|
30776
|
-
const stateDir =
|
|
30777
|
-
const featureFiles =
|
|
31366
|
+
const stateDir = join20(root, "state");
|
|
31367
|
+
const featureFiles = existsSync20(featuresDir) ? import_fast_glob4.default.sync("*.md", { cwd: featuresDir, absolute: true }) : [];
|
|
30778
31368
|
const featureRefs = [];
|
|
30779
31369
|
for (const file of featureFiles) {
|
|
30780
31370
|
try {
|
|
@@ -30789,7 +31379,7 @@ function registerFeaturesCommand(program2) {
|
|
|
30789
31379
|
} catch {
|
|
30790
31380
|
}
|
|
30791
31381
|
}
|
|
30792
|
-
const taskFiles =
|
|
31382
|
+
const taskFiles = existsSync20(stateDir) ? import_fast_glob4.default.sync("*.md", { cwd: stateDir, absolute: true }) : [];
|
|
30793
31383
|
const taskRefs = [];
|
|
30794
31384
|
for (const file of taskFiles) {
|
|
30795
31385
|
const taskSlug = basename5(file, ".md");
|
|
@@ -31067,13 +31657,13 @@ var init_types = __esm({
|
|
|
31067
31657
|
});
|
|
31068
31658
|
|
|
31069
31659
|
// src/lib/task-backend/local.ts
|
|
31070
|
-
import { existsSync as
|
|
31071
|
-
import { basename as basename6, join as
|
|
31660
|
+
import { existsSync as existsSync21, readFileSync as readFileSync19, rmSync as rmSync3, writeFileSync as writeFileSync17 } from "fs";
|
|
31661
|
+
import { basename as basename6, join as join21, resolve as resolve4, sep as sep2 } from "path";
|
|
31072
31662
|
function isSafeTaskSlug(slug) {
|
|
31073
31663
|
if (!slug || slug.includes("\0")) return false;
|
|
31074
|
-
const base =
|
|
31075
|
-
const target =
|
|
31076
|
-
return target ===
|
|
31664
|
+
const base = resolve4(sep2, "dc-slug-check");
|
|
31665
|
+
const target = resolve4(base, `${slug}.md`);
|
|
31666
|
+
return target === join21(base, `${slug}.md`) && target.startsWith(base + sep2);
|
|
31077
31667
|
}
|
|
31078
31668
|
function hasBacklogTag(tags) {
|
|
31079
31669
|
return Array.isArray(tags) && tags.some((t) => String(t).toLowerCase() === BACKLOG_TAG);
|
|
@@ -31094,12 +31684,12 @@ function normalizeBacklogFields(prev, patch) {
|
|
|
31094
31684
|
}
|
|
31095
31685
|
function getTaskTemplate() {
|
|
31096
31686
|
const candidates = [
|
|
31097
|
-
|
|
31098
|
-
|
|
31687
|
+
join21(new URL(".", import.meta.url).pathname, "..", "..", "templates", "task.md"),
|
|
31688
|
+
join21(new URL(".", import.meta.url).pathname, "..", "templates", "task.md")
|
|
31099
31689
|
];
|
|
31100
31690
|
for (const path2 of candidates) {
|
|
31101
|
-
if (
|
|
31102
|
-
return
|
|
31691
|
+
if (existsSync21(path2)) {
|
|
31692
|
+
return readFileSync19(path2, "utf-8");
|
|
31103
31693
|
}
|
|
31104
31694
|
}
|
|
31105
31695
|
return `---
|
|
@@ -31233,20 +31823,20 @@ var init_local = __esm({
|
|
|
31233
31823
|
}
|
|
31234
31824
|
name = "local";
|
|
31235
31825
|
taskPath(slug) {
|
|
31236
|
-
return
|
|
31826
|
+
return join21(this.stateDir, `${slug}.md`);
|
|
31237
31827
|
}
|
|
31238
31828
|
requirePath(slug) {
|
|
31239
31829
|
if (!isSafeTaskSlug(slug)) {
|
|
31240
31830
|
throw new TaskBackendError("invalid_input", `Invalid task slug: ${slug}`);
|
|
31241
31831
|
}
|
|
31242
31832
|
const path2 = this.taskPath(slug);
|
|
31243
|
-
if (!
|
|
31833
|
+
if (!existsSync21(path2)) {
|
|
31244
31834
|
throw new TaskBackendError("not_found", `Task not found: ${slug}`);
|
|
31245
31835
|
}
|
|
31246
31836
|
return path2;
|
|
31247
31837
|
}
|
|
31248
31838
|
taskFiles() {
|
|
31249
|
-
if (!
|
|
31839
|
+
if (!existsSync21(this.stateDir)) return [];
|
|
31250
31840
|
return import_fast_glob5.default.sync("*.md", { cwd: this.stateDir, absolute: true });
|
|
31251
31841
|
}
|
|
31252
31842
|
async list(filter) {
|
|
@@ -31263,7 +31853,7 @@ var init_local = __esm({
|
|
|
31263
31853
|
async get(slug) {
|
|
31264
31854
|
if (!isSafeTaskSlug(slug)) return null;
|
|
31265
31855
|
const path2 = this.taskPath(slug);
|
|
31266
|
-
if (!
|
|
31856
|
+
if (!existsSync21(path2)) return null;
|
|
31267
31857
|
return readTaskFile(path2);
|
|
31268
31858
|
}
|
|
31269
31859
|
async create(input2) {
|
|
@@ -31275,13 +31865,13 @@ var init_local = __esm({
|
|
|
31275
31865
|
throw new TaskBackendError("invalid_input", `Invalid task name: ${input2.name}`);
|
|
31276
31866
|
}
|
|
31277
31867
|
const filePath = this.taskPath(slug);
|
|
31278
|
-
if (
|
|
31868
|
+
if (existsSync21(filePath)) {
|
|
31279
31869
|
throw new TaskBackendError("already_exists", `Task already exists: ${slug}`);
|
|
31280
31870
|
}
|
|
31281
31871
|
if (input2.variant === "cli") {
|
|
31282
31872
|
const template = getTaskTemplate();
|
|
31283
31873
|
const content = template.replaceAll("{{ID}}", generateId("task")).replaceAll("{{NAME}}", input2.name).replaceAll("{{DESCRIPTION}}", input2.description ?? input2.name).replaceAll("{{PRIORITY}}", input2.priority ?? "medium").replaceAll("{{URGENCY}}", input2.urgency ?? "medium").replaceAll("{{STATUS}}", input2.status ?? "todo").replaceAll("{{TAGS}}", JSON.stringify(input2.tags ?? [])).replaceAll("{{DATE}}", today()).replaceAll("{{WHY}}", input2.why || "(To be defined)").replaceAll("{{VERSION}}", input2.version ? `"${input2.version}"` : "null");
|
|
31284
|
-
|
|
31874
|
+
writeFileSync17(filePath, content, "utf-8");
|
|
31285
31875
|
if (input2.rice) {
|
|
31286
31876
|
updateFrontmatterFields(filePath, { rice: input2.rice });
|
|
31287
31877
|
}
|
|
@@ -31345,7 +31935,7 @@ ${input2.why || "(To be defined)"}
|
|
|
31345
31935
|
### ${dateStr} - Created
|
|
31346
31936
|
- Task created.
|
|
31347
31937
|
`;
|
|
31348
|
-
|
|
31938
|
+
writeFileSync17(filePath, content, "utf-8");
|
|
31349
31939
|
if (input2.due_date) {
|
|
31350
31940
|
updateFrontmatterFields(filePath, { due_date: input2.due_date });
|
|
31351
31941
|
}
|
|
@@ -31376,8 +31966,8 @@ ${input2.why || "(To be defined)"}
|
|
|
31376
31966
|
insertToSection(path2, "Changelog", entry, "top");
|
|
31377
31967
|
} catch (err) {
|
|
31378
31968
|
if (!opts?.fallbackAppend) throw err;
|
|
31379
|
-
const existing =
|
|
31380
|
-
|
|
31969
|
+
const existing = readFileSync19(path2, "utf-8");
|
|
31970
|
+
writeFileSync17(path2, existing.trimEnd() + "\n\n" + entry + "\n", "utf-8");
|
|
31381
31971
|
}
|
|
31382
31972
|
}
|
|
31383
31973
|
async complete(slug, summary) {
|
|
@@ -31391,11 +31981,11 @@ ${input2.why || "(To be defined)"}
|
|
|
31391
31981
|
}
|
|
31392
31982
|
async delete(slug) {
|
|
31393
31983
|
const path2 = this.requirePath(slug);
|
|
31394
|
-
|
|
31984
|
+
rmSync3(path2);
|
|
31395
31985
|
}
|
|
31396
31986
|
async resolveSlug(name) {
|
|
31397
31987
|
const slug = slugify(name);
|
|
31398
|
-
if (
|
|
31988
|
+
if (existsSync21(this.taskPath(slug))) return { kind: "match", slug };
|
|
31399
31989
|
const slugs = this.taskFiles().map((f) => basename6(f, ".md"));
|
|
31400
31990
|
const exact = slugs.find((s) => s === slug);
|
|
31401
31991
|
if (exact) return { kind: "match", slug: exact };
|
|
@@ -31902,14 +32492,14 @@ var init_change_tracker = __esm({
|
|
|
31902
32492
|
});
|
|
31903
32493
|
|
|
31904
32494
|
// src/lib/gitignore.ts
|
|
31905
|
-
import { existsSync as
|
|
31906
|
-
import { join as
|
|
32495
|
+
import { existsSync as existsSync22, lstatSync, readFileSync as readFileSync20, writeFileSync as writeFileSync18 } from "fs";
|
|
32496
|
+
import { join as join22 } from "path";
|
|
31907
32497
|
function ensureGitignoreEntries(projectRoot, entries, opts) {
|
|
31908
|
-
const path2 =
|
|
31909
|
-
if (
|
|
32498
|
+
const path2 = join22(projectRoot, ".gitignore");
|
|
32499
|
+
if (existsSync22(path2) && !lstatSync(path2).isFile()) {
|
|
31910
32500
|
throw new Error(`.gitignore at ${path2} is not a regular file`);
|
|
31911
32501
|
}
|
|
31912
|
-
const current =
|
|
32502
|
+
const current = existsSync22(path2) ? readFileSync20(path2, "utf-8") : "";
|
|
31913
32503
|
const have = new Set(
|
|
31914
32504
|
current.split("\n").map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#"))
|
|
31915
32505
|
);
|
|
@@ -31919,7 +32509,7 @@ function ensureGitignoreEntries(projectRoot, entries, opts) {
|
|
|
31919
32509
|
if (current.length > 0 && !current.endsWith("\n")) lines.push("");
|
|
31920
32510
|
if (opts?.comment) lines.push("", `# ${opts.comment}`);
|
|
31921
32511
|
lines.push(...missing);
|
|
31922
|
-
|
|
32512
|
+
writeFileSync18(path2, current + lines.join("\n") + "\n", "utf-8");
|
|
31923
32513
|
return missing;
|
|
31924
32514
|
}
|
|
31925
32515
|
var init_gitignore = __esm({
|
|
@@ -31929,16 +32519,16 @@ var init_gitignore = __esm({
|
|
|
31929
32519
|
});
|
|
31930
32520
|
|
|
31931
32521
|
// src/lib/task-backend/secrets.ts
|
|
31932
|
-
import { chmodSync, existsSync as
|
|
31933
|
-
import { dirname as
|
|
32522
|
+
import { chmodSync, existsSync as existsSync23, mkdirSync as mkdirSync11, readFileSync as readFileSync21, writeFileSync as writeFileSync19 } from "fs";
|
|
32523
|
+
import { dirname as dirname10, join as join23 } from "path";
|
|
31934
32524
|
function secretsPath(projectRoot) {
|
|
31935
|
-
return
|
|
32525
|
+
return join23(projectRoot, SECRETS_REL_PATH);
|
|
31936
32526
|
}
|
|
31937
32527
|
function readSecretsFile(projectRoot) {
|
|
31938
32528
|
const path2 = secretsPath(projectRoot);
|
|
31939
|
-
if (!
|
|
32529
|
+
if (!existsSync23(path2)) return {};
|
|
31940
32530
|
try {
|
|
31941
|
-
const parsed = JSON.parse(
|
|
32531
|
+
const parsed = JSON.parse(readFileSync21(path2, "utf-8"));
|
|
31942
32532
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
31943
32533
|
return parsed;
|
|
31944
32534
|
} catch {
|
|
@@ -31959,7 +32549,7 @@ function writeClickUpToken(projectRoot, token, user) {
|
|
|
31959
32549
|
);
|
|
31960
32550
|
}
|
|
31961
32551
|
const path2 = secretsPath(projectRoot);
|
|
31962
|
-
|
|
32552
|
+
mkdirSync11(dirname10(path2), { recursive: true });
|
|
31963
32553
|
const secrets = readSecretsFile(projectRoot);
|
|
31964
32554
|
secrets.clickup = secrets.clickup ?? {};
|
|
31965
32555
|
if (user && user.trim()) {
|
|
@@ -31967,7 +32557,7 @@ function writeClickUpToken(projectRoot, token, user) {
|
|
|
31967
32557
|
} else {
|
|
31968
32558
|
secrets.clickup.token = token.trim();
|
|
31969
32559
|
}
|
|
31970
|
-
|
|
32560
|
+
writeFileSync19(path2, JSON.stringify(secrets, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
31971
32561
|
try {
|
|
31972
32562
|
chmodSync(path2, 384);
|
|
31973
32563
|
} catch {
|
|
@@ -31992,7 +32582,7 @@ function resolveClickUpToken(projectRoot, opts) {
|
|
|
31992
32582
|
return null;
|
|
31993
32583
|
}
|
|
31994
32584
|
function hasSecretsFile(projectRoot) {
|
|
31995
|
-
return
|
|
32585
|
+
return existsSync23(secretsPath(projectRoot));
|
|
31996
32586
|
}
|
|
31997
32587
|
function maskToken(token) {
|
|
31998
32588
|
const t = token.trim();
|
|
@@ -32010,14 +32600,14 @@ var init_secrets = __esm({
|
|
|
32010
32600
|
});
|
|
32011
32601
|
|
|
32012
32602
|
// src/lib/task-backend/identity.ts
|
|
32013
|
-
import { existsSync as
|
|
32014
|
-
import { join as
|
|
32603
|
+
import { existsSync as existsSync24, readFileSync as readFileSync22 } from "fs";
|
|
32604
|
+
import { join as join24 } from "path";
|
|
32015
32605
|
function seedRolesFromTeamOwners(contextRoot) {
|
|
32016
|
-
const path2 =
|
|
32017
|
-
if (!
|
|
32606
|
+
const path2 = join24(contextRoot, "knowledge", "team_owners.md");
|
|
32607
|
+
if (!existsSync24(path2)) return {};
|
|
32018
32608
|
const roles = {};
|
|
32019
32609
|
try {
|
|
32020
|
-
const lines =
|
|
32610
|
+
const lines = readFileSync22(path2, "utf-8").split("\n");
|
|
32021
32611
|
for (const line of lines) {
|
|
32022
32612
|
const bullet = line.match(/^\s*[-*]\s*([^:|]+):\s*(.+)\s*$/);
|
|
32023
32613
|
if (bullet) {
|
|
@@ -32235,23 +32825,23 @@ var init_paths = __esm({
|
|
|
32235
32825
|
});
|
|
32236
32826
|
|
|
32237
32827
|
// src/lib/task-backend/sync-state.ts
|
|
32238
|
-
import { createHash } from "crypto";
|
|
32239
|
-
import { existsSync as
|
|
32240
|
-
import { dirname as
|
|
32828
|
+
import { createHash as createHash2 } from "crypto";
|
|
32829
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync12, readFileSync as readFileSync23, rmSync as rmSync4, statSync as statSync3, writeFileSync as writeFileSync20 } from "fs";
|
|
32830
|
+
import { dirname as dirname11, join as join25 } from "path";
|
|
32241
32831
|
function readJson(path2, fallback) {
|
|
32242
|
-
if (!
|
|
32832
|
+
if (!existsSync25(path2)) return fallback;
|
|
32243
32833
|
try {
|
|
32244
|
-
return JSON.parse(
|
|
32834
|
+
return JSON.parse(readFileSync23(path2, "utf-8"));
|
|
32245
32835
|
} catch {
|
|
32246
32836
|
return fallback;
|
|
32247
32837
|
}
|
|
32248
32838
|
}
|
|
32249
32839
|
function writeJson(path2, data) {
|
|
32250
|
-
|
|
32251
|
-
|
|
32840
|
+
mkdirSync12(dirname11(path2), { recursive: true });
|
|
32841
|
+
writeFileSync20(path2, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
32252
32842
|
}
|
|
32253
32843
|
function hashContent(content) {
|
|
32254
|
-
return
|
|
32844
|
+
return createHash2("sha256").update(content, "utf-8").digest("hex");
|
|
32255
32845
|
}
|
|
32256
32846
|
var SyncLedger;
|
|
32257
32847
|
var init_sync_state = __esm({
|
|
@@ -32263,16 +32853,16 @@ var init_sync_state = __esm({
|
|
|
32263
32853
|
this.contextRoot = contextRoot;
|
|
32264
32854
|
}
|
|
32265
32855
|
get mapPath() {
|
|
32266
|
-
return
|
|
32856
|
+
return join25(this.contextRoot, TASKS_MAP_REL);
|
|
32267
32857
|
}
|
|
32268
32858
|
get syncPath() {
|
|
32269
|
-
return
|
|
32859
|
+
return join25(this.contextRoot, TASKS_SYNC_REL);
|
|
32270
32860
|
}
|
|
32271
32861
|
get queuePath() {
|
|
32272
|
-
return
|
|
32862
|
+
return join25(this.contextRoot, TASKS_QUEUE_REL);
|
|
32273
32863
|
}
|
|
32274
32864
|
conflictsDir() {
|
|
32275
|
-
return
|
|
32865
|
+
return join25(this.contextRoot, CONFLICTS_DIR_REL);
|
|
32276
32866
|
}
|
|
32277
32867
|
// ── id-map (committed) ──
|
|
32278
32868
|
readMap() {
|
|
@@ -32384,17 +32974,17 @@ var init_sync_state = __esm({
|
|
|
32384
32974
|
*/
|
|
32385
32975
|
reset() {
|
|
32386
32976
|
let backupPath2 = null;
|
|
32387
|
-
if (
|
|
32977
|
+
if (existsSync25(this.mapPath)) {
|
|
32388
32978
|
backupPath2 = this.mapPath.replace(/\.json$/, `.backup-${Date.now()}.json`);
|
|
32389
|
-
|
|
32390
|
-
|
|
32979
|
+
writeFileSync20(backupPath2, readFileSync23(this.mapPath));
|
|
32980
|
+
rmSync4(this.mapPath);
|
|
32391
32981
|
}
|
|
32392
|
-
if (
|
|
32393
|
-
if (
|
|
32982
|
+
if (existsSync25(this.syncPath)) rmSync4(this.syncPath);
|
|
32983
|
+
if (existsSync25(this.queuePath)) rmSync4(this.queuePath);
|
|
32394
32984
|
return { backupPath: backupPath2 };
|
|
32395
32985
|
}
|
|
32396
32986
|
get lockPath() {
|
|
32397
|
-
return
|
|
32987
|
+
return join25(this.contextRoot, TASKS_LOCK_REL);
|
|
32398
32988
|
}
|
|
32399
32989
|
/**
|
|
32400
32990
|
* SYNC LOCK — at most one sync engine per project at a time. Sync fires
|
|
@@ -32406,10 +32996,10 @@ var init_sync_state = __esm({
|
|
|
32406
32996
|
* (JSON timestamp first, file mtime as the fallback for garbage content).
|
|
32407
32997
|
*/
|
|
32408
32998
|
acquireSyncLock(nowMs, staleMs) {
|
|
32409
|
-
|
|
32999
|
+
mkdirSync12(dirname11(this.lockPath), { recursive: true });
|
|
32410
33000
|
const tryCreate = () => {
|
|
32411
33001
|
try {
|
|
32412
|
-
|
|
33002
|
+
writeFileSync20(this.lockPath, JSON.stringify({ pid: process.pid, at: nowMs }) + "\n", { flag: "wx" });
|
|
32413
33003
|
return true;
|
|
32414
33004
|
} catch {
|
|
32415
33005
|
return false;
|
|
@@ -32418,7 +33008,7 @@ var init_sync_state = __esm({
|
|
|
32418
33008
|
if (tryCreate()) return true;
|
|
32419
33009
|
let heldSince = null;
|
|
32420
33010
|
try {
|
|
32421
|
-
const info2 = JSON.parse(
|
|
33011
|
+
const info2 = JSON.parse(readFileSync23(this.lockPath, "utf-8"));
|
|
32422
33012
|
if (typeof info2.at === "number") heldSince = info2.at;
|
|
32423
33013
|
} catch {
|
|
32424
33014
|
}
|
|
@@ -32431,14 +33021,14 @@ var init_sync_state = __esm({
|
|
|
32431
33021
|
}
|
|
32432
33022
|
if (nowMs - heldSince <= staleMs) return false;
|
|
32433
33023
|
try {
|
|
32434
|
-
|
|
33024
|
+
rmSync4(this.lockPath, { force: true });
|
|
32435
33025
|
} catch {
|
|
32436
33026
|
}
|
|
32437
33027
|
return tryCreate();
|
|
32438
33028
|
}
|
|
32439
33029
|
releaseSyncLock() {
|
|
32440
33030
|
try {
|
|
32441
|
-
|
|
33031
|
+
rmSync4(this.lockPath, { force: true });
|
|
32442
33032
|
} catch {
|
|
32443
33033
|
}
|
|
32444
33034
|
}
|
|
@@ -32450,8 +33040,8 @@ var init_sync_state = __esm({
|
|
|
32450
33040
|
});
|
|
32451
33041
|
|
|
32452
33042
|
// src/lib/task-backend/clickup.ts
|
|
32453
|
-
import { existsSync as
|
|
32454
|
-
import { basename as basename7, dirname as
|
|
33043
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync13, readFileSync as readFileSync24, writeFileSync as writeFileSync21 } from "fs";
|
|
33044
|
+
import { basename as basename7, dirname as dirname12, join as join26 } from "path";
|
|
32455
33045
|
function stripPersonTags(tags) {
|
|
32456
33046
|
return tags.filter((t) => !t.startsWith(PERSON_TAG_PREFIX));
|
|
32457
33047
|
}
|
|
@@ -32556,7 +33146,7 @@ var init_clickup = __esm({
|
|
|
32556
33146
|
CLICKUP_MAX_RETRIES = 5;
|
|
32557
33147
|
ClickUpTaskBackend = class _ClickUpTaskBackend extends LocalTaskBackend {
|
|
32558
33148
|
constructor(contextRoot, config, deps = {}) {
|
|
32559
|
-
super(
|
|
33149
|
+
super(join26(contextRoot, "state"));
|
|
32560
33150
|
this.contextRoot = contextRoot;
|
|
32561
33151
|
this.config = config;
|
|
32562
33152
|
this.deps = deps;
|
|
@@ -32571,7 +33161,7 @@ var init_clickup = __esm({
|
|
|
32571
33161
|
return (this.deps.now ?? Date.now)();
|
|
32572
33162
|
}
|
|
32573
33163
|
get projectRoot() {
|
|
32574
|
-
return
|
|
33164
|
+
return dirname12(this.contextRoot);
|
|
32575
33165
|
}
|
|
32576
33166
|
getAdapter() {
|
|
32577
33167
|
if (this.deps.adapter) return this.deps.adapter;
|
|
@@ -32905,7 +33495,7 @@ var init_clickup = __esm({
|
|
|
32905
33495
|
for (const file of this.taskFiles()) {
|
|
32906
33496
|
const slug = basename7(file, ".md");
|
|
32907
33497
|
const entry = state.tasks[slug];
|
|
32908
|
-
const hash = hashContent(
|
|
33498
|
+
const hash = hashContent(readFileSync24(file, "utf-8"));
|
|
32909
33499
|
if (!entry?.localHash || entry.localHash !== hash) candidates.add(slug);
|
|
32910
33500
|
}
|
|
32911
33501
|
for (const slug of [...candidates].sort()) {
|
|
@@ -32919,7 +33509,7 @@ var init_clickup = __esm({
|
|
|
32919
33509
|
}
|
|
32920
33510
|
async pushTask(slug, adapter, listId, report) {
|
|
32921
33511
|
const path2 = this.taskPath(slug);
|
|
32922
|
-
if (!
|
|
33512
|
+
if (!existsSync26(path2)) return;
|
|
32923
33513
|
const task = await super.get(slug);
|
|
32924
33514
|
const enqueueCutoff = this.nowMs();
|
|
32925
33515
|
const entry = this.ledger.taskSync(slug);
|
|
@@ -33024,7 +33614,7 @@ var init_clickup = __esm({
|
|
|
33024
33614
|
serverTime = serverTimeMs(comment.date) ?? serverTime;
|
|
33025
33615
|
report.commentsAdded++;
|
|
33026
33616
|
}
|
|
33027
|
-
const raw =
|
|
33617
|
+
const raw = readFileSync24(path2, "utf-8");
|
|
33028
33618
|
this.ledger.updateTaskSync(slug, {
|
|
33029
33619
|
last_synced_at: serverTime ?? entry?.last_synced_at ?? 0,
|
|
33030
33620
|
base_snapshot: { hash: hashContent(raw), body: raw },
|
|
@@ -33112,8 +33702,8 @@ var init_clickup = __esm({
|
|
|
33112
33702
|
if (pendingDeletes.has(entry.remoteId)) continue;
|
|
33113
33703
|
const path2 = this.taskPath(entry.slug);
|
|
33114
33704
|
try {
|
|
33115
|
-
if (
|
|
33116
|
-
const raw =
|
|
33705
|
+
if (existsSync26(path2)) {
|
|
33706
|
+
const raw = readFileSync24(path2, "utf-8");
|
|
33117
33707
|
const syncEntry = this.ledger.taskSync(entry.slug);
|
|
33118
33708
|
const localChanged = !syncEntry?.localHash || hashContent(raw) !== syncEntry.localHash;
|
|
33119
33709
|
if (localChanged) {
|
|
@@ -33165,7 +33755,7 @@ var init_clickup = __esm({
|
|
|
33165
33755
|
)
|
|
33166
33756
|
].sort();
|
|
33167
33757
|
let slug = this.ledger.slugForRemoteId(remote.id);
|
|
33168
|
-
if (!slug || !
|
|
33758
|
+
if (!slug || !existsSync26(this.taskPath(slug))) {
|
|
33169
33759
|
slug = slug ?? this.uniqueSlugFor(remote.name);
|
|
33170
33760
|
const fm2 = {
|
|
33171
33761
|
id: generateId("task"),
|
|
@@ -33208,7 +33798,7 @@ var init_clickup = __esm({
|
|
|
33208
33798
|
}
|
|
33209
33799
|
const path2 = this.taskPath(slug);
|
|
33210
33800
|
const entry = this.ledger.taskSync(slug);
|
|
33211
|
-
const localRaw =
|
|
33801
|
+
const localRaw = readFileSync24(path2, "utf-8");
|
|
33212
33802
|
const local = await this.getLocal(slug);
|
|
33213
33803
|
const localChanged = entry?.localHash ? hashContent(localRaw) !== entry.localHash : true;
|
|
33214
33804
|
const localChangedAt = entry?.lastLocalChangeAt ?? null;
|
|
@@ -33420,7 +34010,7 @@ var init_clickup = __esm({
|
|
|
33420
34010
|
const baseSlug = slugify(name) || "task";
|
|
33421
34011
|
let candidate = baseSlug;
|
|
33422
34012
|
let n = 1;
|
|
33423
|
-
while (
|
|
34013
|
+
while (existsSync26(this.taskPath(candidate))) {
|
|
33424
34014
|
n++;
|
|
33425
34015
|
candidate = `${baseSlug}-${n}`;
|
|
33426
34016
|
}
|
|
@@ -33442,7 +34032,7 @@ ${changelog}` : ""}`;
|
|
|
33442
34032
|
const content = this.renderMirror(fm, desc, changelogEntries);
|
|
33443
34033
|
this.applyingRemote = true;
|
|
33444
34034
|
try {
|
|
33445
|
-
|
|
34035
|
+
writeFileSync21(this.taskPath(slug), content, "utf-8");
|
|
33446
34036
|
} finally {
|
|
33447
34037
|
this.applyingRemote = false;
|
|
33448
34038
|
}
|
|
@@ -33451,15 +34041,15 @@ ${changelog}` : ""}`;
|
|
|
33451
34041
|
/** Preserve a losing local copy under state/.conflicts/ — never silent loss. */
|
|
33452
34042
|
saveConflictCopy(slug, localRaw, remoteTime) {
|
|
33453
34043
|
const dir = this.ledger.conflictsDir();
|
|
33454
|
-
|
|
34044
|
+
mkdirSync13(dir, { recursive: true });
|
|
33455
34045
|
const stamp = remoteTime ?? this.nowMs();
|
|
33456
|
-
let path2 =
|
|
34046
|
+
let path2 = join26(dir, `${slug}-${stamp}.md`);
|
|
33457
34047
|
let n = 1;
|
|
33458
|
-
while (
|
|
34048
|
+
while (existsSync26(path2)) {
|
|
33459
34049
|
n++;
|
|
33460
|
-
path2 =
|
|
34050
|
+
path2 = join26(dir, `${slug}-${stamp}-${n}.md`);
|
|
33461
34051
|
}
|
|
33462
|
-
|
|
34052
|
+
writeFileSync21(path2, localRaw, "utf-8");
|
|
33463
34053
|
return path2;
|
|
33464
34054
|
}
|
|
33465
34055
|
};
|
|
@@ -33467,8 +34057,8 @@ ${changelog}` : ""}`;
|
|
|
33467
34057
|
});
|
|
33468
34058
|
|
|
33469
34059
|
// src/lib/task-backend/git-hooks.ts
|
|
33470
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
33471
|
-
import { join as
|
|
34060
|
+
import { chmodSync as chmodSync2, existsSync as existsSync27, readFileSync as readFileSync25, rmSync as rmSync5, writeFileSync as writeFileSync22 } from "fs";
|
|
34061
|
+
import { join as join27 } from "path";
|
|
33472
34062
|
function taskSyncHookScript(cliInvocation) {
|
|
33473
34063
|
return `#!/bin/sh
|
|
33474
34064
|
${MARKER}
|
|
@@ -33489,23 +34079,23 @@ function defaultCliInvocation() {
|
|
|
33489
34079
|
return `${quote(process.execPath)} ${quote(entry)}`;
|
|
33490
34080
|
}
|
|
33491
34081
|
function installTaskSyncHooks(projectRoot, opts = {}) {
|
|
33492
|
-
const hooksDir =
|
|
33493
|
-
if (!
|
|
34082
|
+
const hooksDir = join27(projectRoot, ".git", "hooks");
|
|
34083
|
+
if (!existsSync27(join27(projectRoot, ".git"))) {
|
|
33494
34084
|
return { installed: [], skipped: [], noGit: true };
|
|
33495
34085
|
}
|
|
33496
34086
|
const script = taskSyncHookScript(opts.cliInvocation ?? defaultCliInvocation());
|
|
33497
34087
|
const installed = [];
|
|
33498
34088
|
const skipped = [];
|
|
33499
34089
|
for (const hook of TASK_SYNC_HOOKS) {
|
|
33500
|
-
const path2 =
|
|
33501
|
-
if (
|
|
33502
|
-
const existing =
|
|
34090
|
+
const path2 = join27(hooksDir, hook);
|
|
34091
|
+
if (existsSync27(path2)) {
|
|
34092
|
+
const existing = readFileSync25(path2, "utf-8");
|
|
33503
34093
|
if (!existing.includes(MARKER)) {
|
|
33504
34094
|
skipped.push(hook);
|
|
33505
34095
|
continue;
|
|
33506
34096
|
}
|
|
33507
34097
|
}
|
|
33508
|
-
|
|
34098
|
+
writeFileSync22(path2, script, "utf-8");
|
|
33509
34099
|
try {
|
|
33510
34100
|
chmodSync2(path2, 493);
|
|
33511
34101
|
} catch {
|
|
@@ -33515,12 +34105,12 @@ function installTaskSyncHooks(projectRoot, opts = {}) {
|
|
|
33515
34105
|
return { installed, skipped, noGit: false };
|
|
33516
34106
|
}
|
|
33517
34107
|
function uninstallTaskSyncHooks(projectRoot) {
|
|
33518
|
-
const hooksDir =
|
|
34108
|
+
const hooksDir = join27(projectRoot, ".git", "hooks");
|
|
33519
34109
|
const removed = [];
|
|
33520
34110
|
for (const hook of TASK_SYNC_HOOKS) {
|
|
33521
|
-
const path2 =
|
|
33522
|
-
if (
|
|
33523
|
-
|
|
34111
|
+
const path2 = join27(hooksDir, hook);
|
|
34112
|
+
if (existsSync27(path2) && readFileSync25(path2, "utf-8").includes(MARKER)) {
|
|
34113
|
+
rmSync5(path2);
|
|
33524
34114
|
removed.push(hook);
|
|
33525
34115
|
}
|
|
33526
34116
|
}
|
|
@@ -33530,8 +34120,8 @@ function hasManagedTaskSyncHooks(projectRoot) {
|
|
|
33530
34120
|
return TASK_SYNC_HOOKS.some((hook) => isManagedTaskSyncHook(projectRoot, hook));
|
|
33531
34121
|
}
|
|
33532
34122
|
function isManagedTaskSyncHook(projectRoot, hook) {
|
|
33533
|
-
const path2 =
|
|
33534
|
-
return
|
|
34123
|
+
const path2 = join27(projectRoot, ".git", "hooks", hook);
|
|
34124
|
+
return existsSync27(path2) && readFileSync25(path2, "utf-8").includes(MARKER);
|
|
33535
34125
|
}
|
|
33536
34126
|
var MARKER, TASK_SYNC_HOOKS;
|
|
33537
34127
|
var init_git_hooks = __esm({
|
|
@@ -33543,18 +34133,18 @@ var init_git_hooks = __esm({
|
|
|
33543
34133
|
});
|
|
33544
34134
|
|
|
33545
34135
|
// src/lib/task-backend/index.ts
|
|
33546
|
-
import { existsSync as
|
|
33547
|
-
import { dirname as
|
|
34136
|
+
import { existsSync as existsSync28, readdirSync as readdirSync7 } from "fs";
|
|
34137
|
+
import { dirname as dirname13, join as join28 } from "path";
|
|
33548
34138
|
function getTaskBackend(contextRoot, config, deps) {
|
|
33549
34139
|
const root = contextRoot ?? ensureContextRoot();
|
|
33550
|
-
const cfg = config !== void 0 ? config : readSetupConfig(
|
|
34140
|
+
const cfg = config !== void 0 ? config : readSetupConfig(dirname13(root));
|
|
33551
34141
|
if (cfg?.taskBackend === "clickup") {
|
|
33552
34142
|
return createClickUpBackend(root, cfg ?? null, deps);
|
|
33553
34143
|
}
|
|
33554
|
-
return new LocalTaskBackend(
|
|
34144
|
+
return new LocalTaskBackend(join28(root, "state"));
|
|
33555
34145
|
}
|
|
33556
34146
|
function getTaskSyncStatus(contextRoot, config) {
|
|
33557
|
-
const cfg = config !== void 0 ? config : readSetupConfig(
|
|
34147
|
+
const cfg = config !== void 0 ? config : readSetupConfig(dirname13(contextRoot));
|
|
33558
34148
|
const ledger = new SyncLedger(contextRoot);
|
|
33559
34149
|
const state = ledger.readSyncState();
|
|
33560
34150
|
const conflictsDir = ledger.conflictsDir();
|
|
@@ -33562,7 +34152,7 @@ function getTaskSyncStatus(contextRoot, config) {
|
|
|
33562
34152
|
backend: cfg?.taskBackend ?? "local",
|
|
33563
34153
|
pendingPush: Object.values(state.tasks).filter((t) => t.pendingPush).length,
|
|
33564
34154
|
queuedOps: ledger.readQueue().length,
|
|
33565
|
-
conflicts:
|
|
34155
|
+
conflicts: existsSync28(conflictsDir) ? readdirSync7(conflictsDir).filter((f) => f.endsWith(".md")).length : 0,
|
|
33566
34156
|
watermark: state.watermark
|
|
33567
34157
|
};
|
|
33568
34158
|
}
|
|
@@ -33583,186 +34173,9 @@ var init_task_backend = __esm({
|
|
|
33583
34173
|
}
|
|
33584
34174
|
});
|
|
33585
34175
|
|
|
33586
|
-
// src/lib/version-check.ts
|
|
33587
|
-
import { existsSync as existsSync27, readFileSync as readFileSync24, mkdirSync as mkdirSync12, writeFileSync as writeFileSync21 } from "fs";
|
|
33588
|
-
import { dirname as dirname12, join as join27 } from "path";
|
|
33589
|
-
import { execFileSync, spawn as spawn2 } from "child_process";
|
|
33590
|
-
function cachePath(root) {
|
|
33591
|
-
return join27(root, CACHE_REL_PATH);
|
|
33592
|
-
}
|
|
33593
|
-
function readVersionCache(root) {
|
|
33594
|
-
const path2 = cachePath(root);
|
|
33595
|
-
if (!existsSync27(path2)) return null;
|
|
33596
|
-
try {
|
|
33597
|
-
const raw = readFileSync24(path2, "utf-8");
|
|
33598
|
-
const parsed = JSON.parse(raw);
|
|
33599
|
-
if (!parsed || typeof parsed !== "object") return null;
|
|
33600
|
-
if (typeof parsed.checkedAt !== "number") return null;
|
|
33601
|
-
return {
|
|
33602
|
-
checkedAt: parsed.checkedAt,
|
|
33603
|
-
latestCli: typeof parsed.latestCli === "string" ? parsed.latestCli : null,
|
|
33604
|
-
availablePacks: Array.isArray(parsed.availablePacks) ? parsed.availablePacks.filter((p) => typeof p === "string") : [],
|
|
33605
|
-
ttlHours: typeof parsed.ttlHours === "number" ? parsed.ttlHours : DEFAULT_TTL_HOURS
|
|
33606
|
-
};
|
|
33607
|
-
} catch {
|
|
33608
|
-
return null;
|
|
33609
|
-
}
|
|
33610
|
-
}
|
|
33611
|
-
function writeVersionCache(root, cache) {
|
|
33612
|
-
const path2 = cachePath(root);
|
|
33613
|
-
try {
|
|
33614
|
-
mkdirSync12(dirname12(path2), { recursive: true });
|
|
33615
|
-
writeFileSync21(path2, JSON.stringify(cache, null, 2) + "\n", "utf-8");
|
|
33616
|
-
} catch {
|
|
33617
|
-
}
|
|
33618
|
-
}
|
|
33619
|
-
function isCacheFresh(cache, nowMs) {
|
|
33620
|
-
if (!cache) return false;
|
|
33621
|
-
try {
|
|
33622
|
-
if (typeof cache.checkedAt !== "number" || !isFinite(cache.checkedAt)) return false;
|
|
33623
|
-
const ttlHours = typeof cache.ttlHours === "number" && isFinite(cache.ttlHours) && cache.ttlHours > 0 ? cache.ttlHours : DEFAULT_TTL_HOURS;
|
|
33624
|
-
const ttlMs = ttlHours * 60 * 60 * 1e3;
|
|
33625
|
-
const now = nowMs ?? Date.now();
|
|
33626
|
-
return now - cache.checkedAt < ttlMs;
|
|
33627
|
-
} catch {
|
|
33628
|
-
return false;
|
|
33629
|
-
}
|
|
33630
|
-
}
|
|
33631
|
-
function compareVersions(a, b) {
|
|
33632
|
-
const clean = (v) => v.replace(/[-+].*$/, "").trim();
|
|
33633
|
-
const parseSegments = (v) => clean(v).split(".").map((s) => {
|
|
33634
|
-
const n = parseInt(s, 10);
|
|
33635
|
-
return isFinite(n) ? n : 0;
|
|
33636
|
-
});
|
|
33637
|
-
const segA = parseSegments(a);
|
|
33638
|
-
const segB = parseSegments(b);
|
|
33639
|
-
const len = Math.max(segA.length, segB.length);
|
|
33640
|
-
for (let i = 0; i < len; i++) {
|
|
33641
|
-
const sa = segA[i] ?? 0;
|
|
33642
|
-
const sb = segB[i] ?? 0;
|
|
33643
|
-
if (sa < sb) return -1;
|
|
33644
|
-
if (sa > sb) return 1;
|
|
33645
|
-
}
|
|
33646
|
-
return 0;
|
|
33647
|
-
}
|
|
33648
|
-
function buildNudge(installedCli, cache, installedPacks, catalogPackNames, opts = {}) {
|
|
33649
|
-
if (!cache || cache.latestCli === null) return null;
|
|
33650
|
-
const cliOutdated = compareVersions(installedCli, cache.latestCli) < 0;
|
|
33651
|
-
const showCliNudge = cliOutdated && !opts.suppressCliNudge;
|
|
33652
|
-
const newPacks = catalogPackNames.filter((p) => !installedPacks.includes(p));
|
|
33653
|
-
const hasNewPacks = newPacks.length > 0;
|
|
33654
|
-
if (!showCliNudge && !hasNewPacks) return null;
|
|
33655
|
-
const lines = ["## Update Available\n"];
|
|
33656
|
-
if (showCliNudge) {
|
|
33657
|
-
lines.push(`- **New version available: v${installedCli} \u2192 v${cache.latestCli}.** A new release can add, update, or remove hooks, prompts, sub-agents, and skills. Run \`dreamcontext upgrade\` to get it, then \`dreamcontext update\` to apply those changes to this project.`);
|
|
33658
|
-
}
|
|
33659
|
-
if (hasNewPacks) {
|
|
33660
|
-
lines.push(`- New skill pack${newPacks.length > 1 ? "s" : ""} available: ${newPacks.join(", ")} \u2014 run \`dreamcontext install-skill --packs\``);
|
|
33661
|
-
}
|
|
33662
|
-
return lines.join("\n");
|
|
33663
|
-
}
|
|
33664
|
-
function refreshVersionCache(root, opts) {
|
|
33665
|
-
const runner = opts?.runner ?? ((args) => execFileSync("npm", args, {
|
|
33666
|
-
timeout: NPM_TIMEOUT_MS,
|
|
33667
|
-
encoding: "utf-8",
|
|
33668
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
33669
|
-
}));
|
|
33670
|
-
const catalogPackNames = opts?.catalogPackNames ?? [];
|
|
33671
|
-
let latestCli = null;
|
|
33672
|
-
try {
|
|
33673
|
-
const raw = runner(["view", "dreamcontext", "version"]);
|
|
33674
|
-
const trimmed = (typeof raw === "string" ? raw : "").trim();
|
|
33675
|
-
if (/^\d+\.\d+/.test(trimmed)) {
|
|
33676
|
-
latestCli = trimmed;
|
|
33677
|
-
}
|
|
33678
|
-
} catch {
|
|
33679
|
-
latestCli = null;
|
|
33680
|
-
}
|
|
33681
|
-
const cache = {
|
|
33682
|
-
checkedAt: Date.now(),
|
|
33683
|
-
latestCli,
|
|
33684
|
-
availablePacks: catalogPackNames,
|
|
33685
|
-
ttlHours: DEFAULT_TTL_HOURS
|
|
33686
|
-
};
|
|
33687
|
-
writeVersionCache(root, cache);
|
|
33688
|
-
}
|
|
33689
|
-
function markerPath(root) {
|
|
33690
|
-
return join27(root, AUTO_UPGRADE_MARKER_REL_PATH);
|
|
33691
|
-
}
|
|
33692
|
-
function readAutoUpgradeMarker(root) {
|
|
33693
|
-
const path2 = markerPath(root);
|
|
33694
|
-
if (!existsSync27(path2)) return null;
|
|
33695
|
-
try {
|
|
33696
|
-
const parsed = JSON.parse(readFileSync24(path2, "utf-8"));
|
|
33697
|
-
if (!parsed || typeof parsed !== "object") return null;
|
|
33698
|
-
if (typeof parsed.attemptedFor !== "string" || typeof parsed.at !== "number") return null;
|
|
33699
|
-
return { attemptedFor: parsed.attemptedFor, at: parsed.at };
|
|
33700
|
-
} catch {
|
|
33701
|
-
return null;
|
|
33702
|
-
}
|
|
33703
|
-
}
|
|
33704
|
-
function writeAutoUpgradeMarker(root, marker) {
|
|
33705
|
-
const path2 = markerPath(root);
|
|
33706
|
-
try {
|
|
33707
|
-
mkdirSync12(dirname12(path2), { recursive: true });
|
|
33708
|
-
writeFileSync21(path2, JSON.stringify(marker, null, 2) + "\n", "utf-8");
|
|
33709
|
-
} catch {
|
|
33710
|
-
}
|
|
33711
|
-
}
|
|
33712
|
-
function autoUpgradeEnabled(env2 = process.env) {
|
|
33713
|
-
if (env2.DREAMCONTEXT_VERSION_CHECK === "0") return false;
|
|
33714
|
-
return env2.DREAMCONTEXT_AUTO_UPGRADE !== "0";
|
|
33715
|
-
}
|
|
33716
|
-
function shouldAutoUpgrade(installedCli, cache, env2 = process.env) {
|
|
33717
|
-
if (!autoUpgradeEnabled(env2)) return null;
|
|
33718
|
-
if (!cache || cache.latestCli === null) return null;
|
|
33719
|
-
if (compareVersions(installedCli, cache.latestCli) >= 0) return null;
|
|
33720
|
-
return cache.latestCli;
|
|
33721
|
-
}
|
|
33722
|
-
function shouldSuppressCliNudge(target, marker, env2 = process.env, now = Date.now()) {
|
|
33723
|
-
if (!autoUpgradeEnabled(env2)) return false;
|
|
33724
|
-
if (!target || !marker) return false;
|
|
33725
|
-
if (marker.attemptedFor !== target) return false;
|
|
33726
|
-
return now - marker.at < AUTO_UPGRADE_INFLIGHT_MS;
|
|
33727
|
-
}
|
|
33728
|
-
function defaultSpawner(cmd, args) {
|
|
33729
|
-
const child = spawn2(cmd, args, { detached: true, stdio: "ignore" });
|
|
33730
|
-
child.unref();
|
|
33731
|
-
}
|
|
33732
|
-
function maybeAutoUpgrade(root, installedCli, cache, env2 = process.env, deps = {}) {
|
|
33733
|
-
try {
|
|
33734
|
-
const target = shouldAutoUpgrade(installedCli, cache, env2);
|
|
33735
|
-
if (!target) return null;
|
|
33736
|
-
const now = deps.now ?? Date.now();
|
|
33737
|
-
const readMarker = deps.readMarker ?? readAutoUpgradeMarker;
|
|
33738
|
-
const writeMarker = deps.writeMarker ?? writeAutoUpgradeMarker;
|
|
33739
|
-
const marker = readMarker(root);
|
|
33740
|
-
const recentlyAttempted = marker !== null && marker.attemptedFor === target && now - marker.at < AUTO_UPGRADE_RETRY_MS;
|
|
33741
|
-
if (recentlyAttempted) return null;
|
|
33742
|
-
writeMarker(root, { attemptedFor: target, at: now });
|
|
33743
|
-
const spawner = deps.spawner ?? defaultSpawner;
|
|
33744
|
-
spawner("npm", ["install", "-g", "dreamcontext@latest"]);
|
|
33745
|
-
return `\u2B06 Auto-upgrading dreamcontext v${installedCli} \u2192 v${target} in the background (takes effect next session).`;
|
|
33746
|
-
} catch {
|
|
33747
|
-
return null;
|
|
33748
|
-
}
|
|
33749
|
-
}
|
|
33750
|
-
var CACHE_REL_PATH, AUTO_UPGRADE_MARKER_REL_PATH, DEFAULT_TTL_HOURS, NPM_TIMEOUT_MS, AUTO_UPGRADE_RETRY_MS, AUTO_UPGRADE_INFLIGHT_MS;
|
|
33751
|
-
var init_version_check = __esm({
|
|
33752
|
-
"src/lib/version-check.ts"() {
|
|
33753
|
-
"use strict";
|
|
33754
|
-
CACHE_REL_PATH = "_dream_context/state/.version-check.json";
|
|
33755
|
-
AUTO_UPGRADE_MARKER_REL_PATH = "_dream_context/state/.auto-upgrade.json";
|
|
33756
|
-
DEFAULT_TTL_HOURS = 24;
|
|
33757
|
-
NPM_TIMEOUT_MS = 5e3;
|
|
33758
|
-
AUTO_UPGRADE_RETRY_MS = 24 * 60 * 60 * 1e3;
|
|
33759
|
-
AUTO_UPGRADE_INFLIGHT_MS = 60 * 60 * 1e3;
|
|
33760
|
-
}
|
|
33761
|
-
});
|
|
33762
|
-
|
|
33763
34176
|
// src/lib/data-structures-migration.ts
|
|
33764
|
-
import { existsSync as
|
|
33765
|
-
import { join as
|
|
34177
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync14 } from "fs";
|
|
34178
|
+
import { join as join29, basename as basename8 } from "path";
|
|
33766
34179
|
function enrichDataStructuresFrontmatter(data, product) {
|
|
33767
34180
|
const existingTags = Array.isArray(data.tags) ? data.tags.map(String) : [];
|
|
33768
34181
|
const tags = [...existingTags];
|
|
@@ -33784,16 +34197,16 @@ function ensureSqlFence(body) {
|
|
|
33784
34197
|
}
|
|
33785
34198
|
function migrateDataStructures(contextRoot) {
|
|
33786
34199
|
const result = { migrated: [], skipped: [] };
|
|
33787
|
-
const oldDir =
|
|
33788
|
-
if (!
|
|
34200
|
+
const oldDir = join29(contextRoot, OLD_DATA_STRUCTURES_DIR);
|
|
34201
|
+
if (!existsSync29(oldDir)) return result;
|
|
33789
34202
|
const files = import_fast_glob6.default.sync("*.md", { cwd: oldDir, absolute: true });
|
|
33790
34203
|
if (files.length === 0) return result;
|
|
33791
|
-
const newDir =
|
|
33792
|
-
|
|
34204
|
+
const newDir = join29(contextRoot, NEW_DATA_STRUCTURES_DIR);
|
|
34205
|
+
mkdirSync14(newDir, { recursive: true });
|
|
33793
34206
|
for (const oldFile of files) {
|
|
33794
34207
|
const product = basename8(oldFile, ".md");
|
|
33795
|
-
const newFile =
|
|
33796
|
-
if (
|
|
34208
|
+
const newFile = join29(newDir, `${product}.md`);
|
|
34209
|
+
if (existsSync29(newFile)) {
|
|
33797
34210
|
result.skipped.push(product);
|
|
33798
34211
|
continue;
|
|
33799
34212
|
}
|
|
@@ -33804,8 +34217,8 @@ function migrateDataStructures(contextRoot) {
|
|
|
33804
34217
|
return result;
|
|
33805
34218
|
}
|
|
33806
34219
|
function listUnfencedDataStructures(contextRoot) {
|
|
33807
|
-
const dir =
|
|
33808
|
-
if (!
|
|
34220
|
+
const dir = join29(contextRoot, NEW_DATA_STRUCTURES_DIR);
|
|
34221
|
+
if (!existsSync29(dir)) return [];
|
|
33809
34222
|
const out = [];
|
|
33810
34223
|
for (const file of import_fast_glob6.default.sync("*.md", { cwd: dir, absolute: true })) {
|
|
33811
34224
|
try {
|
|
@@ -33817,8 +34230,8 @@ function listUnfencedDataStructures(contextRoot) {
|
|
|
33817
34230
|
return out.sort();
|
|
33818
34231
|
}
|
|
33819
34232
|
function fenceExistingDataStructures(contextRoot) {
|
|
33820
|
-
const dir =
|
|
33821
|
-
if (!
|
|
34233
|
+
const dir = join29(contextRoot, NEW_DATA_STRUCTURES_DIR);
|
|
34234
|
+
if (!existsSync29(dir)) return [];
|
|
33822
34235
|
const fenced = [];
|
|
33823
34236
|
for (const file of import_fast_glob6.default.sync("*.md", { cwd: dir, absolute: true })) {
|
|
33824
34237
|
try {
|
|
@@ -33839,8 +34252,8 @@ var init_data_structures_migration = __esm({
|
|
|
33839
34252
|
"use strict";
|
|
33840
34253
|
import_fast_glob6 = __toESM(require_out4(), 1);
|
|
33841
34254
|
init_frontmatter();
|
|
33842
|
-
OLD_DATA_STRUCTURES_DIR =
|
|
33843
|
-
NEW_DATA_STRUCTURES_DIR =
|
|
34255
|
+
OLD_DATA_STRUCTURES_DIR = join29("core", "data-structures");
|
|
34256
|
+
NEW_DATA_STRUCTURES_DIR = join29("knowledge", "data-structures");
|
|
33844
34257
|
DATA_STRUCTURES_TAGS = ["data-structures", "database", "schema"];
|
|
33845
34258
|
}
|
|
33846
34259
|
});
|
|
@@ -33892,13 +34305,13 @@ var init__ = __esm({
|
|
|
33892
34305
|
|
|
33893
34306
|
// src/lib/wikilink-rewrite.ts
|
|
33894
34307
|
import {
|
|
33895
|
-
existsSync as
|
|
33896
|
-
readFileSync as
|
|
33897
|
-
writeFileSync as
|
|
33898
|
-
renameSync,
|
|
33899
|
-
mkdirSync as
|
|
34308
|
+
existsSync as existsSync30,
|
|
34309
|
+
readFileSync as readFileSync26,
|
|
34310
|
+
writeFileSync as writeFileSync23,
|
|
34311
|
+
renameSync as renameSync2,
|
|
34312
|
+
mkdirSync as mkdirSync15
|
|
33900
34313
|
} from "fs";
|
|
33901
|
-
import { dirname as
|
|
34314
|
+
import { dirname as dirname14 } from "path";
|
|
33902
34315
|
function rewriteWikilinks(contextRoot, remaps) {
|
|
33903
34316
|
if (remaps.length === 0) return [];
|
|
33904
34317
|
const remapMap = new Map(remaps.map((r) => [r.from, r.to]));
|
|
@@ -33911,7 +34324,7 @@ function rewriteWikilinks(contextRoot, remaps) {
|
|
|
33911
34324
|
for (const file of files) {
|
|
33912
34325
|
let content;
|
|
33913
34326
|
try {
|
|
33914
|
-
content =
|
|
34327
|
+
content = readFileSync26(file, "utf-8");
|
|
33915
34328
|
} catch {
|
|
33916
34329
|
continue;
|
|
33917
34330
|
}
|
|
@@ -33919,14 +34332,14 @@ function rewriteWikilinks(contextRoot, remaps) {
|
|
|
33919
34332
|
if (rewritten === content) continue;
|
|
33920
34333
|
const tmp = file + ".wl-tmp";
|
|
33921
34334
|
try {
|
|
33922
|
-
|
|
33923
|
-
|
|
33924
|
-
|
|
34335
|
+
mkdirSync15(dirname14(tmp), { recursive: true });
|
|
34336
|
+
writeFileSync23(tmp, rewritten, "utf-8");
|
|
34337
|
+
renameSync2(tmp, file);
|
|
33925
34338
|
changed.push(file);
|
|
33926
34339
|
} catch {
|
|
33927
34340
|
try {
|
|
33928
|
-
if (
|
|
33929
|
-
|
|
34341
|
+
if (existsSync30(tmp)) {
|
|
34342
|
+
writeFileSync23(tmp, "");
|
|
33930
34343
|
}
|
|
33931
34344
|
} catch {
|
|
33932
34345
|
}
|
|
@@ -34002,13 +34415,13 @@ var init_wikilink_rewrite = __esm({
|
|
|
34002
34415
|
|
|
34003
34416
|
// src/lib/diagrams-migration.ts
|
|
34004
34417
|
import {
|
|
34005
|
-
existsSync as
|
|
34006
|
-
mkdirSync as
|
|
34007
|
-
renameSync as
|
|
34008
|
-
readdirSync as
|
|
34418
|
+
existsSync as existsSync31,
|
|
34419
|
+
mkdirSync as mkdirSync16,
|
|
34420
|
+
renameSync as renameSync3,
|
|
34421
|
+
readdirSync as readdirSync8,
|
|
34009
34422
|
statSync as statSync4
|
|
34010
34423
|
} from "fs";
|
|
34011
|
-
import { join as
|
|
34424
|
+
import { join as join31, resolve as resolve5, sep as sep3 } from "path";
|
|
34012
34425
|
function isSameBasenameSibling(filename, boardBase) {
|
|
34013
34426
|
for (const ext of GENERATOR_EXTS) {
|
|
34014
34427
|
if (filename === `${boardBase}${ext}`) return true;
|
|
@@ -34016,9 +34429,9 @@ function isSameBasenameSibling(filename, boardBase) {
|
|
|
34016
34429
|
return false;
|
|
34017
34430
|
}
|
|
34018
34431
|
function migrateDiagramsToFolders(contextRoot) {
|
|
34019
|
-
const diagramsDir =
|
|
34432
|
+
const diagramsDir = join31(contextRoot, "knowledge", "diagrams");
|
|
34020
34433
|
const result = { moved: [], skipped: [], ambiguous: [] };
|
|
34021
|
-
if (!
|
|
34434
|
+
if (!existsSync31(diagramsDir)) return result;
|
|
34022
34435
|
const flatFiles = import_fast_glob8.default.sync("*.excalidraw.md", {
|
|
34023
34436
|
cwd: diagramsDir,
|
|
34024
34437
|
absolute: false
|
|
@@ -34030,13 +34443,13 @@ function migrateDiagramsToFolders(contextRoot) {
|
|
|
34030
34443
|
for (const nested of nestedFiles) {
|
|
34031
34444
|
result.skipped.push(nested.replace(EXCALIDRAW_SUFFIX, ""));
|
|
34032
34445
|
}
|
|
34033
|
-
const diagramsDirResolved =
|
|
34446
|
+
const diagramsDirResolved = resolve5(diagramsDir);
|
|
34034
34447
|
for (const filename of flatFiles) {
|
|
34035
34448
|
const boardBase = filename.slice(0, -EXCALIDRAW_SUFFIX.length);
|
|
34036
|
-
const srcBoard =
|
|
34037
|
-
const destDir =
|
|
34038
|
-
const destBoard =
|
|
34039
|
-
if (boardBase === "" || boardBase === "." || boardBase === ".." || boardBase.includes("/") || boardBase.includes("\\") ||
|
|
34449
|
+
const srcBoard = join31(diagramsDir, filename);
|
|
34450
|
+
const destDir = join31(diagramsDir, boardBase);
|
|
34451
|
+
const destBoard = join31(destDir, filename);
|
|
34452
|
+
if (boardBase === "" || boardBase === "." || boardBase === ".." || boardBase.includes("/") || boardBase.includes("\\") || resolve5(destDir) !== join31(diagramsDirResolved, boardBase) || !resolve5(destDir).startsWith(diagramsDirResolved + sep3)) {
|
|
34040
34453
|
result.ambiguous.push(boardBase);
|
|
34041
34454
|
continue;
|
|
34042
34455
|
}
|
|
@@ -34044,8 +34457,8 @@ function migrateDiagramsToFolders(contextRoot) {
|
|
|
34044
34457
|
const newSlug = `diagrams/${boardBase}/${boardBase}.excalidraw`;
|
|
34045
34458
|
let siblings = [];
|
|
34046
34459
|
try {
|
|
34047
|
-
const allInDir =
|
|
34048
|
-
(f) => statSync4(
|
|
34460
|
+
const allInDir = readdirSync8(diagramsDir).filter(
|
|
34461
|
+
(f) => statSync4(join31(diagramsDir, f)).isFile()
|
|
34049
34462
|
);
|
|
34050
34463
|
siblings = allInDir.filter(
|
|
34051
34464
|
(f) => f !== filename && isSameBasenameSibling(f, boardBase)
|
|
@@ -34055,7 +34468,7 @@ function migrateDiagramsToFolders(contextRoot) {
|
|
|
34055
34468
|
continue;
|
|
34056
34469
|
}
|
|
34057
34470
|
try {
|
|
34058
|
-
|
|
34471
|
+
mkdirSync16(destDir, { recursive: true });
|
|
34059
34472
|
} catch {
|
|
34060
34473
|
result.ambiguous.push(boardBase);
|
|
34061
34474
|
continue;
|
|
@@ -34063,14 +34476,14 @@ function migrateDiagramsToFolders(contextRoot) {
|
|
|
34063
34476
|
const remaps = [{ from: oldSlug, to: newSlug }];
|
|
34064
34477
|
rewriteWikilinks(contextRoot, remaps);
|
|
34065
34478
|
try {
|
|
34066
|
-
|
|
34479
|
+
renameSync3(srcBoard, destBoard);
|
|
34067
34480
|
} catch {
|
|
34068
34481
|
result.ambiguous.push(boardBase);
|
|
34069
34482
|
continue;
|
|
34070
34483
|
}
|
|
34071
34484
|
for (const sib of siblings) {
|
|
34072
34485
|
try {
|
|
34073
|
-
|
|
34486
|
+
renameSync3(join31(diagramsDir, sib), join31(destDir, sib));
|
|
34074
34487
|
} catch {
|
|
34075
34488
|
result.ambiguous.push(`${boardBase} (sibling: ${sib})`);
|
|
34076
34489
|
}
|
|
@@ -34080,8 +34493,8 @@ function migrateDiagramsToFolders(contextRoot) {
|
|
|
34080
34493
|
return result;
|
|
34081
34494
|
}
|
|
34082
34495
|
function detectFlatDiagramBoards(contextRoot) {
|
|
34083
|
-
const diagramsDir =
|
|
34084
|
-
if (!
|
|
34496
|
+
const diagramsDir = join31(contextRoot, "knowledge", "diagrams");
|
|
34497
|
+
if (!existsSync31(diagramsDir)) return [];
|
|
34085
34498
|
const flatFiles = import_fast_glob8.default.sync("*.excalidraw.md", {
|
|
34086
34499
|
cwd: diagramsDir,
|
|
34087
34500
|
absolute: false
|
|
@@ -34131,17 +34544,17 @@ var init__2 = __esm({
|
|
|
34131
34544
|
});
|
|
34132
34545
|
|
|
34133
34546
|
// src/lib/vaults.ts
|
|
34134
|
-
import { existsSync as
|
|
34135
|
-
import { dirname as
|
|
34136
|
-
import { homedir } from "os";
|
|
34137
|
-
function vaultsFilePath(home =
|
|
34138
|
-
return
|
|
34547
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync17, readFileSync as readFileSync27, writeFileSync as writeFileSync24 } from "fs";
|
|
34548
|
+
import { dirname as dirname15, join as join32, resolve as resolve6 } from "path";
|
|
34549
|
+
import { homedir as homedir2 } from "os";
|
|
34550
|
+
function vaultsFilePath(home = homedir2()) {
|
|
34551
|
+
return join32(home, ".dreamcontext", "vaults.json");
|
|
34139
34552
|
}
|
|
34140
34553
|
function listVaults(home) {
|
|
34141
34554
|
const filePath = vaultsFilePath(home);
|
|
34142
|
-
if (!
|
|
34555
|
+
if (!existsSync32(filePath)) return [];
|
|
34143
34556
|
try {
|
|
34144
|
-
const raw =
|
|
34557
|
+
const raw = readFileSync27(filePath, "utf-8");
|
|
34145
34558
|
const parsed = JSON.parse(raw);
|
|
34146
34559
|
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.vaults)) {
|
|
34147
34560
|
return [];
|
|
@@ -34155,15 +34568,15 @@ function listVaults(home) {
|
|
|
34155
34568
|
}
|
|
34156
34569
|
}
|
|
34157
34570
|
function writeRegistry(filePath, registry) {
|
|
34158
|
-
|
|
34159
|
-
|
|
34571
|
+
mkdirSync17(dirname15(filePath), { recursive: true });
|
|
34572
|
+
writeFileSync24(filePath, JSON.stringify(registry, null, 2) + "\n", "utf-8");
|
|
34160
34573
|
}
|
|
34161
34574
|
function addVault(name, dirPath, home) {
|
|
34162
|
-
const resolved =
|
|
34163
|
-
if (!
|
|
34575
|
+
const resolved = resolve6(dirPath);
|
|
34576
|
+
if (!existsSync32(resolved)) {
|
|
34164
34577
|
throw new VaultError(`Path does not exist: ${resolved}`);
|
|
34165
34578
|
}
|
|
34166
|
-
if (!
|
|
34579
|
+
if (!existsSync32(join32(resolved, "_dream_context"))) {
|
|
34167
34580
|
throw new VaultError(
|
|
34168
34581
|
`Path is not a dreamcontext project (no _dream_context/ directory): ${resolved}`
|
|
34169
34582
|
);
|
|
@@ -34173,7 +34586,7 @@ function addVault(name, dirPath, home) {
|
|
|
34173
34586
|
if (existing.some((v) => v.name === name)) {
|
|
34174
34587
|
throw new VaultError(`A vault named "${name}" is already registered.`);
|
|
34175
34588
|
}
|
|
34176
|
-
if (existing.some((v) =>
|
|
34589
|
+
if (existing.some((v) => resolve6(v.path) === resolved)) {
|
|
34177
34590
|
throw new VaultError(`Path is already registered: ${resolved}`);
|
|
34178
34591
|
}
|
|
34179
34592
|
const vault = { name, path: resolved };
|
|
@@ -34181,19 +34594,19 @@ function addVault(name, dirPath, home) {
|
|
|
34181
34594
|
writeRegistry(filePath, registry);
|
|
34182
34595
|
return vault;
|
|
34183
34596
|
}
|
|
34184
|
-
function resolveVaultContextRoot(arg, home =
|
|
34597
|
+
function resolveVaultContextRoot(arg, home = homedir2()) {
|
|
34185
34598
|
const vaults = listVaults(home);
|
|
34186
34599
|
const named = vaults.find((v) => v.name === arg);
|
|
34187
|
-
const resolved = named ? named.path :
|
|
34188
|
-
if (!
|
|
34600
|
+
const resolved = named ? named.path : resolve6(arg);
|
|
34601
|
+
if (!existsSync32(resolved)) {
|
|
34189
34602
|
throw new VaultError(`Vault path does not exist: ${resolved}`);
|
|
34190
34603
|
}
|
|
34191
|
-
if (!
|
|
34604
|
+
if (!existsSync32(join32(resolved, "_dream_context"))) {
|
|
34192
34605
|
throw new VaultError(
|
|
34193
34606
|
`Path is not a dreamcontext project (no _dream_context/ directory): ${resolved}`
|
|
34194
34607
|
);
|
|
34195
34608
|
}
|
|
34196
|
-
return
|
|
34609
|
+
return join32(resolved, "_dream_context");
|
|
34197
34610
|
}
|
|
34198
34611
|
function removeVault(name, home) {
|
|
34199
34612
|
const existing = listVaults(home);
|
|
@@ -34218,11 +34631,11 @@ var init_vaults = __esm({
|
|
|
34218
34631
|
});
|
|
34219
34632
|
|
|
34220
34633
|
// src/lib/connections.ts
|
|
34221
|
-
import { existsSync as
|
|
34634
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync18, readFileSync as readFileSync28, renameSync as renameSync4, writeFileSync as writeFileSync25 } from "fs";
|
|
34222
34635
|
import { randomBytes } from "crypto";
|
|
34223
|
-
import { dirname as
|
|
34636
|
+
import { dirname as dirname16, join as join33, resolve as resolve7 } from "path";
|
|
34224
34637
|
function connectionsPath(contextRoot) {
|
|
34225
|
-
return
|
|
34638
|
+
return join33(contextRoot, CONNECTIONS_REL_PATH);
|
|
34226
34639
|
}
|
|
34227
34640
|
function emptyFile() {
|
|
34228
34641
|
return { version: 1, connections: [] };
|
|
@@ -34242,9 +34655,9 @@ function sanitizeConnection(raw) {
|
|
|
34242
34655
|
}
|
|
34243
34656
|
function readConnections(contextRoot) {
|
|
34244
34657
|
const path2 = connectionsPath(contextRoot);
|
|
34245
|
-
if (!
|
|
34658
|
+
if (!existsSync33(path2)) return emptyFile();
|
|
34246
34659
|
try {
|
|
34247
|
-
const parsed = JSON.parse(
|
|
34660
|
+
const parsed = JSON.parse(readFileSync28(path2, "utf-8"));
|
|
34248
34661
|
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.connections)) {
|
|
34249
34662
|
return emptyFile();
|
|
34250
34663
|
}
|
|
@@ -34257,10 +34670,10 @@ function readConnections(contextRoot) {
|
|
|
34257
34670
|
}
|
|
34258
34671
|
function writeConnections(contextRoot, file) {
|
|
34259
34672
|
const path2 = connectionsPath(contextRoot);
|
|
34260
|
-
|
|
34673
|
+
mkdirSync18(dirname16(path2), { recursive: true });
|
|
34261
34674
|
const tmp = `${path2}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
34262
|
-
|
|
34263
|
-
|
|
34675
|
+
writeFileSync25(tmp, JSON.stringify(file, null, 2) + "\n", "utf-8");
|
|
34676
|
+
renameSync4(tmp, path2);
|
|
34264
34677
|
}
|
|
34265
34678
|
function listConnections(contextRoot) {
|
|
34266
34679
|
return readConnections(contextRoot).connections;
|
|
@@ -34280,7 +34693,7 @@ function addConnection(contextRoot, currentVaultName3, peer, direction, topics,
|
|
|
34280
34693
|
throw new VaultError(`Unknown vault "${peer}" \u2014 register it first with \`dreamcontext vaults add\`.`);
|
|
34281
34694
|
}
|
|
34282
34695
|
const peerRoot = resolveVaultContextRoot(peer, home);
|
|
34283
|
-
if (
|
|
34696
|
+
if (resolve7(peerRoot) === resolve7(contextRoot)) {
|
|
34284
34697
|
throw new VaultError("A vault cannot connect to itself.");
|
|
34285
34698
|
}
|
|
34286
34699
|
const file = readConnections(contextRoot);
|
|
@@ -34320,11 +34733,11 @@ var init_connections = __esm({
|
|
|
34320
34733
|
});
|
|
34321
34734
|
|
|
34322
34735
|
// src/server/safe-path.ts
|
|
34323
|
-
import { resolve as
|
|
34736
|
+
import { resolve as resolve8, sep as sep4 } from "path";
|
|
34324
34737
|
function safeChildPath2(baseDir, child) {
|
|
34325
34738
|
if (!child || child.includes("\0")) return null;
|
|
34326
|
-
const base =
|
|
34327
|
-
const target =
|
|
34739
|
+
const base = resolve8(baseDir);
|
|
34740
|
+
const target = resolve8(base, child);
|
|
34328
34741
|
if (target !== base && !target.startsWith(base + sep4)) return null;
|
|
34329
34742
|
return target;
|
|
34330
34743
|
}
|
|
@@ -34336,22 +34749,22 @@ var init_safe_path = __esm({
|
|
|
34336
34749
|
|
|
34337
34750
|
// src/lib/federation-inbox.ts
|
|
34338
34751
|
import {
|
|
34339
|
-
existsSync as
|
|
34340
|
-
mkdirSync as
|
|
34341
|
-
readFileSync as
|
|
34342
|
-
readdirSync as
|
|
34343
|
-
renameSync as
|
|
34344
|
-
writeFileSync as
|
|
34752
|
+
existsSync as existsSync34,
|
|
34753
|
+
mkdirSync as mkdirSync19,
|
|
34754
|
+
readFileSync as readFileSync29,
|
|
34755
|
+
readdirSync as readdirSync9,
|
|
34756
|
+
renameSync as renameSync5,
|
|
34757
|
+
writeFileSync as writeFileSync26
|
|
34345
34758
|
} from "fs";
|
|
34346
|
-
import { join as
|
|
34759
|
+
import { join as join34 } from "path";
|
|
34347
34760
|
function inboxDir(contextRoot) {
|
|
34348
|
-
return
|
|
34761
|
+
return join34(contextRoot, INBOX_REL);
|
|
34349
34762
|
}
|
|
34350
34763
|
function consumedDir(contextRoot) {
|
|
34351
|
-
return
|
|
34764
|
+
return join34(inboxDir(contextRoot), CONSUMED_DIRNAME);
|
|
34352
34765
|
}
|
|
34353
34766
|
function ensureInbox(contextRoot) {
|
|
34354
|
-
|
|
34767
|
+
mkdirSync19(consumedDir(contextRoot), { recursive: true });
|
|
34355
34768
|
}
|
|
34356
34769
|
function majorOf(version) {
|
|
34357
34770
|
return Math.floor(Number.isFinite(version) ? version : 0);
|
|
@@ -34364,19 +34777,19 @@ function isDigestEntry(raw) {
|
|
|
34364
34777
|
function drainInbox(contextRoot) {
|
|
34365
34778
|
const dir = inboxDir(contextRoot);
|
|
34366
34779
|
const result = { entries: [], quarantined: [] };
|
|
34367
|
-
if (!
|
|
34780
|
+
if (!existsSync34(dir)) return result;
|
|
34368
34781
|
let files;
|
|
34369
34782
|
try {
|
|
34370
|
-
files =
|
|
34783
|
+
files = readdirSync9(dir).filter((f) => f.endsWith(".json"));
|
|
34371
34784
|
} catch (err) {
|
|
34372
34785
|
console.error(`[dreamcontext] federation: cannot read inbox at ${dir}: ${String(err)}`);
|
|
34373
34786
|
return result;
|
|
34374
34787
|
}
|
|
34375
34788
|
for (const file of files) {
|
|
34376
|
-
const path2 =
|
|
34789
|
+
const path2 = join34(dir, file);
|
|
34377
34790
|
let entry;
|
|
34378
34791
|
try {
|
|
34379
|
-
const parsed = JSON.parse(
|
|
34792
|
+
const parsed = JSON.parse(readFileSync29(path2, "utf-8"));
|
|
34380
34793
|
if (!isDigestEntry(parsed)) {
|
|
34381
34794
|
console.error(`[dreamcontext] federation: skipping malformed inbox entry "${file}".`);
|
|
34382
34795
|
continue;
|
|
@@ -34401,9 +34814,9 @@ function drainInbox(contextRoot) {
|
|
|
34401
34814
|
}
|
|
34402
34815
|
function pendingInboxCount(contextRoot) {
|
|
34403
34816
|
const dir = inboxDir(contextRoot);
|
|
34404
|
-
if (!
|
|
34817
|
+
if (!existsSync34(dir)) return 0;
|
|
34405
34818
|
try {
|
|
34406
|
-
return
|
|
34819
|
+
return readdirSync9(dir, { withFileTypes: true }).filter(
|
|
34407
34820
|
(d) => d.isFile() && d.name.endsWith(".json")
|
|
34408
34821
|
).length;
|
|
34409
34822
|
} catch {
|
|
@@ -34412,17 +34825,17 @@ function pendingInboxCount(contextRoot) {
|
|
|
34412
34825
|
}
|
|
34413
34826
|
function listConsumedEntries(contextRoot) {
|
|
34414
34827
|
const dir = consumedDir(contextRoot);
|
|
34415
|
-
if (!
|
|
34828
|
+
if (!existsSync34(dir)) return [];
|
|
34416
34829
|
let files;
|
|
34417
34830
|
try {
|
|
34418
|
-
files =
|
|
34831
|
+
files = readdirSync9(dir).filter((f) => f.endsWith(".json"));
|
|
34419
34832
|
} catch {
|
|
34420
34833
|
return [];
|
|
34421
34834
|
}
|
|
34422
34835
|
const out = [];
|
|
34423
34836
|
for (const file of files) {
|
|
34424
34837
|
try {
|
|
34425
|
-
const parsed = JSON.parse(
|
|
34838
|
+
const parsed = JSON.parse(readFileSync29(join34(dir, file), "utf-8"));
|
|
34426
34839
|
if (isDigestEntry(parsed)) out.push(parsed);
|
|
34427
34840
|
} catch {
|
|
34428
34841
|
}
|
|
@@ -34435,14 +34848,14 @@ var init_federation_inbox = __esm({
|
|
|
34435
34848
|
"use strict";
|
|
34436
34849
|
init_safe_path();
|
|
34437
34850
|
DIGEST_SCHEMA_VERSION = 1;
|
|
34438
|
-
INBOX_REL =
|
|
34851
|
+
INBOX_REL = join34("state", ".federation-inbox");
|
|
34439
34852
|
CONSUMED_DIRNAME = "consumed";
|
|
34440
34853
|
}
|
|
34441
34854
|
});
|
|
34442
34855
|
|
|
34443
34856
|
// src/migrations/0.8.0.ts
|
|
34444
|
-
import { existsSync as
|
|
34445
|
-
import { dirname as
|
|
34857
|
+
import { existsSync as existsSync35 } from "fs";
|
|
34858
|
+
import { dirname as dirname17, join as join35 } from "path";
|
|
34446
34859
|
var migration080;
|
|
34447
34860
|
var init__3 = __esm({
|
|
34448
34861
|
"src/migrations/0.8.0.ts"() {
|
|
@@ -34454,16 +34867,16 @@ var init__3 = __esm({
|
|
|
34454
34867
|
version: "0.8.0",
|
|
34455
34868
|
steps: [
|
|
34456
34869
|
(root) => {
|
|
34457
|
-
const projectRoot =
|
|
34870
|
+
const projectRoot = dirname17(root);
|
|
34458
34871
|
const filesTouched = [];
|
|
34459
34872
|
const connPath = connectionsPath(root);
|
|
34460
|
-
if (!
|
|
34873
|
+
if (!existsSync35(connPath)) {
|
|
34461
34874
|
writeConnections(root, { version: 1, connections: [] });
|
|
34462
34875
|
filesTouched.push("state/.connections.json");
|
|
34463
34876
|
} else {
|
|
34464
34877
|
readConnections(root);
|
|
34465
34878
|
}
|
|
34466
|
-
const inboxExisted =
|
|
34879
|
+
const inboxExisted = existsSync35(consumedDir(root));
|
|
34467
34880
|
ensureInbox(root);
|
|
34468
34881
|
if (!inboxExisted) {
|
|
34469
34882
|
filesTouched.push("state/.federation-inbox/", "state/.federation-inbox/consumed/");
|
|
@@ -34479,7 +34892,7 @@ var init__3 = __esm({
|
|
|
34479
34892
|
const summary = detected ? "Federation already scaffolded (.connections.json + .federation-inbox/ present, shareable set) \u2014 nothing to do." : `Scaffolded federation: ${filesTouched.join(", ")}` + (shareableTouched ? "" : cfg ? " (shareable already set \u2014 preserved)" : "");
|
|
34480
34893
|
return {
|
|
34481
34894
|
step: "scaffold-federation",
|
|
34482
|
-
filesTouched: filesTouched.map((f) =>
|
|
34895
|
+
filesTouched: filesTouched.map((f) => join35(root, f.split(" ")[0])),
|
|
34483
34896
|
summary,
|
|
34484
34897
|
detected
|
|
34485
34898
|
};
|
|
@@ -34509,21 +34922,21 @@ var init_migrations = __esm({
|
|
|
34509
34922
|
|
|
34510
34923
|
// src/lib/migration-ledger.ts
|
|
34511
34924
|
import {
|
|
34512
|
-
existsSync as
|
|
34513
|
-
mkdirSync as
|
|
34514
|
-
readFileSync as
|
|
34515
|
-
writeFileSync as
|
|
34516
|
-
renameSync as
|
|
34925
|
+
existsSync as existsSync36,
|
|
34926
|
+
mkdirSync as mkdirSync20,
|
|
34927
|
+
readFileSync as readFileSync30,
|
|
34928
|
+
writeFileSync as writeFileSync27,
|
|
34929
|
+
renameSync as renameSync6
|
|
34517
34930
|
} from "fs";
|
|
34518
|
-
import { dirname as
|
|
34931
|
+
import { dirname as dirname18, join as join36 } from "path";
|
|
34519
34932
|
function ledgerPath(contextRoot) {
|
|
34520
|
-
return
|
|
34933
|
+
return join36(contextRoot, LEDGER_REL_PATH);
|
|
34521
34934
|
}
|
|
34522
34935
|
function readLedger(contextRoot) {
|
|
34523
34936
|
const path2 = ledgerPath(contextRoot);
|
|
34524
|
-
if (!
|
|
34937
|
+
if (!existsSync36(path2)) return [];
|
|
34525
34938
|
try {
|
|
34526
|
-
const raw =
|
|
34939
|
+
const raw = readFileSync30(path2, "utf-8");
|
|
34527
34940
|
const parsed = JSON.parse(raw);
|
|
34528
34941
|
if (!Array.isArray(parsed)) return [];
|
|
34529
34942
|
return parsed;
|
|
@@ -34534,9 +34947,9 @@ function readLedger(contextRoot) {
|
|
|
34534
34947
|
function writeLedger(contextRoot, entries) {
|
|
34535
34948
|
const path2 = ledgerPath(contextRoot);
|
|
34536
34949
|
const tmp = path2 + ".tmp";
|
|
34537
|
-
|
|
34538
|
-
|
|
34539
|
-
|
|
34950
|
+
mkdirSync20(dirname18(path2), { recursive: true });
|
|
34951
|
+
writeFileSync27(tmp, JSON.stringify(entries, null, 2) + "\n", "utf-8");
|
|
34952
|
+
renameSync6(tmp, path2);
|
|
34540
34953
|
}
|
|
34541
34954
|
function appendLedger(contextRoot, entry) {
|
|
34542
34955
|
const entries = readLedger(contextRoot);
|
|
@@ -34556,8 +34969,8 @@ var init_migration_ledger = __esm({
|
|
|
34556
34969
|
});
|
|
34557
34970
|
|
|
34558
34971
|
// src/lib/migration-runner.ts
|
|
34559
|
-
import { existsSync as
|
|
34560
|
-
import { join as
|
|
34972
|
+
import { existsSync as existsSync37 } from "fs";
|
|
34973
|
+
import { join as join37 } from "path";
|
|
34561
34974
|
function runMigrations(contextRoot, fromVersion, toVersion) {
|
|
34562
34975
|
if (compareVersions(toVersion, fromVersion) < 0) {
|
|
34563
34976
|
return { applied: [], pendingAgentTasks: [] };
|
|
@@ -34588,8 +35001,8 @@ function runMigrations(contextRoot, fromVersion, toVersion) {
|
|
|
34588
35001
|
applied.push(entry);
|
|
34589
35002
|
}
|
|
34590
35003
|
}
|
|
34591
|
-
const changelogPath =
|
|
34592
|
-
if (
|
|
35004
|
+
const changelogPath = join37(contextRoot, "core", "CHANGELOG.json");
|
|
35005
|
+
if (existsSync37(changelogPath)) {
|
|
34593
35006
|
const codeByVersion = /* @__PURE__ */ new Map();
|
|
34594
35007
|
for (const entry of applied) {
|
|
34595
35008
|
if (entry.executor === "code") {
|
|
@@ -34808,13 +35221,13 @@ var init_sleep_consolidation = __esm({
|
|
|
34808
35221
|
});
|
|
34809
35222
|
|
|
34810
35223
|
// src/cli/commands/sleep.ts
|
|
34811
|
-
import { existsSync as
|
|
34812
|
-
import { join as
|
|
35224
|
+
import { existsSync as existsSync38 } from "fs";
|
|
35225
|
+
import { join as join38, dirname as dirname19 } from "path";
|
|
34813
35226
|
function getSleepPath(root) {
|
|
34814
|
-
return
|
|
35227
|
+
return join38(root, "state", ".sleep.json");
|
|
34815
35228
|
}
|
|
34816
35229
|
function getSleepHistoryPath(root) {
|
|
34817
|
-
return
|
|
35230
|
+
return join38(root, "state", ".sleep-history.json");
|
|
34818
35231
|
}
|
|
34819
35232
|
function freshDefaults() {
|
|
34820
35233
|
return {
|
|
@@ -34836,7 +35249,7 @@ function freshDefaults() {
|
|
|
34836
35249
|
}
|
|
34837
35250
|
function readSleepState(root) {
|
|
34838
35251
|
const filePath = getSleepPath(root);
|
|
34839
|
-
if (!
|
|
35252
|
+
if (!existsSync38(filePath)) {
|
|
34840
35253
|
return freshDefaults();
|
|
34841
35254
|
}
|
|
34842
35255
|
try {
|
|
@@ -34845,7 +35258,7 @@ function readSleepState(root) {
|
|
|
34845
35258
|
const historyPath = getSleepHistoryPath(root);
|
|
34846
35259
|
let existing = [];
|
|
34847
35260
|
try {
|
|
34848
|
-
if (
|
|
35261
|
+
if (existsSync38(historyPath)) {
|
|
34849
35262
|
existing = readJsonArray(historyPath);
|
|
34850
35263
|
}
|
|
34851
35264
|
} catch {
|
|
@@ -34872,7 +35285,7 @@ function readSleepState(root) {
|
|
|
34872
35285
|
}
|
|
34873
35286
|
function readSleepHistory(root) {
|
|
34874
35287
|
const filePath = getSleepHistoryPath(root);
|
|
34875
|
-
if (!
|
|
35288
|
+
if (!existsSync38(filePath)) return [];
|
|
34876
35289
|
try {
|
|
34877
35290
|
return readJsonArray(filePath);
|
|
34878
35291
|
} catch {
|
|
@@ -34965,7 +35378,7 @@ function registerSleepCommand(program2) {
|
|
|
34965
35378
|
const decision = consolidationDepth(state.debt, { userRequestedDeep: !!opts.deep });
|
|
34966
35379
|
state.consolidation_depth = decision.depth;
|
|
34967
35380
|
state.pendingMigrationNotices = [];
|
|
34968
|
-
const projectRoot =
|
|
35381
|
+
const projectRoot = dirname19(root);
|
|
34969
35382
|
const config = readSetupConfig(projectRoot);
|
|
34970
35383
|
const fromVersion = config?.setupVersion ?? "0.0.0";
|
|
34971
35384
|
const migResult = runMigrations(root, fromVersion, dreamcontextVersion());
|
|
@@ -35119,19 +35532,19 @@ var init_sleep = __esm({
|
|
|
35119
35532
|
});
|
|
35120
35533
|
|
|
35121
35534
|
// src/cli/commands/knowledge.ts
|
|
35122
|
-
import { existsSync as
|
|
35123
|
-
import { join as
|
|
35535
|
+
import { existsSync as existsSync39 } from "fs";
|
|
35536
|
+
import { join as join39 } from "path";
|
|
35124
35537
|
function getKnowledgeDir() {
|
|
35125
35538
|
const root = ensureContextRoot();
|
|
35126
|
-
return
|
|
35539
|
+
return join39(root, "knowledge");
|
|
35127
35540
|
}
|
|
35128
35541
|
function registerKnowledgeCommand(program2) {
|
|
35129
35542
|
const knowledge = program2.command("knowledge").description("Create and index knowledge files");
|
|
35130
35543
|
knowledge.command("create").argument("<name>").option("-d, --description <desc>", "Description").option("-t, --tags <tags>", "Tags (comma-separated)").option("-c, --content <content>", "Content body").description("Create a new knowledge file").action(async (name, opts) => {
|
|
35131
35544
|
const dir = getKnowledgeDir();
|
|
35132
35545
|
const slug = slugify(name);
|
|
35133
|
-
const filePath =
|
|
35134
|
-
if (
|
|
35546
|
+
const filePath = join39(dir, `${slug}.md`);
|
|
35547
|
+
if (existsSync39(filePath)) {
|
|
35135
35548
|
error(`Knowledge file already exists: ${slug}.md`);
|
|
35136
35549
|
return;
|
|
35137
35550
|
}
|
|
@@ -35206,8 +35619,8 @@ ${content || "(Content to be added)"}
|
|
|
35206
35619
|
});
|
|
35207
35620
|
knowledge.command("touch").argument("<slug>", "Knowledge file slug").description("Record access to a knowledge file (for decay tracking)").action((slug) => {
|
|
35208
35621
|
const root = ensureContextRoot();
|
|
35209
|
-
const knowledgePath2 =
|
|
35210
|
-
if (!
|
|
35622
|
+
const knowledgePath2 = join39(root, "knowledge", `${slug}.md`);
|
|
35623
|
+
if (!existsSync39(knowledgePath2)) {
|
|
35211
35624
|
error(`Knowledge file not found: ${slug}.md`);
|
|
35212
35625
|
return;
|
|
35213
35626
|
}
|
|
@@ -35232,10 +35645,10 @@ var init_knowledge = __esm({
|
|
|
35232
35645
|
});
|
|
35233
35646
|
|
|
35234
35647
|
// src/cli/commands/tasks.ts
|
|
35235
|
-
import { join as
|
|
35648
|
+
import { join as join40, basename as basename10, dirname as dirname20 } from "path";
|
|
35236
35649
|
function getStateDir() {
|
|
35237
35650
|
const root = ensureContextRoot();
|
|
35238
|
-
return
|
|
35651
|
+
return join40(root, "state");
|
|
35239
35652
|
}
|
|
35240
35653
|
function collectOption(value, previous) {
|
|
35241
35654
|
return previous.concat(value);
|
|
@@ -35374,7 +35787,7 @@ function registerTasksCommand(program2) {
|
|
|
35374
35787
|
const description = opts.description || name;
|
|
35375
35788
|
const tags = opts.tags ? opts.tags.split(",").map((t) => t.trim()).filter(Boolean) : [];
|
|
35376
35789
|
if (opts.person && opts.person.trim()) {
|
|
35377
|
-
const projectRoot =
|
|
35790
|
+
const projectRoot = dirname20(ensureContextRoot());
|
|
35378
35791
|
if (isMultiPerson(readSetupConfig(projectRoot))) {
|
|
35379
35792
|
const personTag = `person:${slugify(opts.person)}`;
|
|
35380
35793
|
if (!tags.includes(personTag)) tags.push(personTag);
|
|
@@ -35726,7 +36139,7 @@ function registerTasksCommand(program2) {
|
|
|
35726
36139
|
}
|
|
35727
36140
|
});
|
|
35728
36141
|
tasks.command("sync-hooks").argument("<action>", "install | uninstall").description("Install/uninstall best-effort git sync triggers (post-commit, pre-push)").action((action) => {
|
|
35729
|
-
const projectRoot =
|
|
36142
|
+
const projectRoot = dirname20(ensureContextRoot());
|
|
35730
36143
|
if (action === "install") {
|
|
35731
36144
|
const res = installTaskSyncHooks(projectRoot);
|
|
35732
36145
|
if (res.noGit) {
|
|
@@ -35754,7 +36167,7 @@ function registerTasksCommand(program2) {
|
|
|
35754
36167
|
const backend = getTaskBackend();
|
|
35755
36168
|
const slug = await resolveTaskSlug(backend, name);
|
|
35756
36169
|
if (!slug) return;
|
|
35757
|
-
files = [
|
|
36170
|
+
files = [join40(dir, `${slug}.md`)];
|
|
35758
36171
|
} else {
|
|
35759
36172
|
files = import_fast_glob9.default.sync("*.md", { cwd: dir, absolute: true });
|
|
35760
36173
|
}
|
|
@@ -35842,8 +36255,8 @@ var init_tasks = __esm({
|
|
|
35842
36255
|
});
|
|
35843
36256
|
|
|
35844
36257
|
// src/cli/commands/update.ts
|
|
35845
|
-
import { existsSync as
|
|
35846
|
-
import { join as
|
|
36258
|
+
import { existsSync as existsSync40, readdirSync as readdirSync10, rmSync as rmSync6 } from "fs";
|
|
36259
|
+
import { join as join41 } from "path";
|
|
35847
36260
|
function buildUpdateSummary(input2) {
|
|
35848
36261
|
const { platforms, installedCount, packs, removed, setupVersion } = input2;
|
|
35849
36262
|
const lines = ["## Update Summary\n"];
|
|
@@ -35866,7 +36279,7 @@ function buildUpdateSummary(input2) {
|
|
|
35866
36279
|
}
|
|
35867
36280
|
function detectInstalledPlatforms(projectRoot) {
|
|
35868
36281
|
return SUPPORTED_PLATFORMS.filter(
|
|
35869
|
-
(p) =>
|
|
36282
|
+
(p) => existsSync40(join41(platformSkillRoot(projectRoot, p), "dreamcontext", "SKILL.md"))
|
|
35870
36283
|
);
|
|
35871
36284
|
}
|
|
35872
36285
|
function detectInstalledPacks(projectRoot, platforms) {
|
|
@@ -35879,11 +36292,11 @@ function detectInstalledPacks(projectRoot, platforms) {
|
|
|
35879
36292
|
const found = /* @__PURE__ */ new Set();
|
|
35880
36293
|
for (const platform2 of platforms) {
|
|
35881
36294
|
const root = platformSkillRoot(projectRoot, platform2);
|
|
35882
|
-
if (!
|
|
35883
|
-
for (const name of
|
|
36295
|
+
if (!existsSync40(root)) continue;
|
|
36296
|
+
for (const name of readdirSync10(root)) {
|
|
35884
36297
|
if (name === "dreamcontext") continue;
|
|
35885
36298
|
if (!knownNames.has(name)) continue;
|
|
35886
|
-
if (
|
|
36299
|
+
if (existsSync40(join41(root, name, "SKILL.md"))) found.add(name);
|
|
35887
36300
|
}
|
|
35888
36301
|
}
|
|
35889
36302
|
return [...found].sort();
|
|
@@ -35933,9 +36346,9 @@ async function pruneStaleFiles(projectRoot, oldManifest, newManifest, isFirstRun
|
|
|
35933
36346
|
}
|
|
35934
36347
|
const removed = [];
|
|
35935
36348
|
for (const rel of owned) {
|
|
35936
|
-
const abs =
|
|
36349
|
+
const abs = join41(projectRoot, rel);
|
|
35937
36350
|
try {
|
|
35938
|
-
|
|
36351
|
+
rmSync6(abs, { force: true });
|
|
35939
36352
|
removed.push(rel);
|
|
35940
36353
|
} catch (e) {
|
|
35941
36354
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -36026,7 +36439,7 @@ function registerUpdateCommand(program2) {
|
|
|
36026
36439
|
const ver = dreamcontextVersion();
|
|
36027
36440
|
updateSetupConfig(projectRoot, { setupVersion: ver });
|
|
36028
36441
|
newSetupVersion = ver;
|
|
36029
|
-
const ctxRoot =
|
|
36442
|
+
const ctxRoot = join41(projectRoot, "_dream_context");
|
|
36030
36443
|
const migResult = runMigrations(ctxRoot, fromVersion, ver);
|
|
36031
36444
|
if (migResult.applied.length > 0) {
|
|
36032
36445
|
const codeApplied = migResult.applied.filter(
|
|
@@ -36085,11 +36498,11 @@ var init_update = __esm({
|
|
|
36085
36498
|
});
|
|
36086
36499
|
|
|
36087
36500
|
// src/lib/core-index.ts
|
|
36088
|
-
import { existsSync as
|
|
36089
|
-
import { join as
|
|
36501
|
+
import { existsSync as existsSync41 } from "fs";
|
|
36502
|
+
import { join as join42, basename as basename11 } from "path";
|
|
36090
36503
|
function buildCoreIndex(contextRoot) {
|
|
36091
|
-
const coreDir =
|
|
36092
|
-
if (!
|
|
36504
|
+
const coreDir = join42(contextRoot, "core");
|
|
36505
|
+
if (!existsSync41(coreDir)) return [];
|
|
36093
36506
|
const files = import_fast_glob10.default.sync("[3-9]*", { cwd: coreDir, absolute: true });
|
|
36094
36507
|
const entries = [];
|
|
36095
36508
|
for (const file of files) {
|
|
@@ -36137,19 +36550,19 @@ var init_core_index = __esm({
|
|
|
36137
36550
|
});
|
|
36138
36551
|
|
|
36139
36552
|
// src/lib/marketing/paths.ts
|
|
36140
|
-
import { join as
|
|
36553
|
+
import { join as join43 } from "path";
|
|
36141
36554
|
function marketingRoot(from) {
|
|
36142
|
-
return
|
|
36555
|
+
return join43(ensureContextRoot(from), MARKETING_DIR);
|
|
36143
36556
|
}
|
|
36144
36557
|
function marketingRootIfExists(from) {
|
|
36145
36558
|
const ctx = resolveContextRoot(from);
|
|
36146
|
-
return ctx ?
|
|
36559
|
+
return ctx ? join43(ctx, MARKETING_DIR) : null;
|
|
36147
36560
|
}
|
|
36148
36561
|
function marketingPath(...segments) {
|
|
36149
|
-
return
|
|
36562
|
+
return join43(marketingRoot(), ...segments);
|
|
36150
36563
|
}
|
|
36151
36564
|
function knowledgePath(...segments) {
|
|
36152
|
-
return
|
|
36565
|
+
return join43(ensureContextRoot(), KNOWLEDGE_DIR, ...segments);
|
|
36153
36566
|
}
|
|
36154
36567
|
var MARKETING_DIR, KNOWLEDGE_DIR, LEARNINGS_SUBDIR, MARKETING_PATHS;
|
|
36155
36568
|
var init_paths2 = __esm({
|
|
@@ -36231,33 +36644,33 @@ var init_secrets2 = __esm({
|
|
|
36231
36644
|
|
|
36232
36645
|
// src/lib/marketing/store.ts
|
|
36233
36646
|
import {
|
|
36234
|
-
existsSync as
|
|
36235
|
-
mkdirSync as
|
|
36647
|
+
existsSync as existsSync42,
|
|
36648
|
+
mkdirSync as mkdirSync21,
|
|
36236
36649
|
openSync,
|
|
36237
36650
|
closeSync,
|
|
36238
|
-
readFileSync as
|
|
36239
|
-
writeFileSync as
|
|
36240
|
-
renameSync as
|
|
36651
|
+
readFileSync as readFileSync31,
|
|
36652
|
+
writeFileSync as writeFileSync28,
|
|
36653
|
+
renameSync as renameSync7,
|
|
36241
36654
|
unlinkSync as unlinkSync2,
|
|
36242
|
-
readdirSync as
|
|
36655
|
+
readdirSync as readdirSync11
|
|
36243
36656
|
} from "fs";
|
|
36244
|
-
import { dirname as
|
|
36657
|
+
import { dirname as dirname21, join as join44 } from "path";
|
|
36245
36658
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
36246
36659
|
function atomicWriteFile(path2, data) {
|
|
36247
|
-
|
|
36660
|
+
mkdirSync21(dirname21(path2), { recursive: true });
|
|
36248
36661
|
const tmp = `${path2}.tmp.${process.pid}.${randomBytes2(4).toString("hex")}`;
|
|
36249
|
-
|
|
36250
|
-
|
|
36662
|
+
writeFileSync28(tmp, data, "utf8");
|
|
36663
|
+
renameSync7(tmp, path2);
|
|
36251
36664
|
}
|
|
36252
36665
|
function writeJsonWithBridge(jsonPath, bridgePath, jsonValue, bridgeMarkdown) {
|
|
36253
|
-
|
|
36254
|
-
|
|
36666
|
+
mkdirSync21(dirname21(jsonPath), { recursive: true });
|
|
36667
|
+
mkdirSync21(dirname21(bridgePath), { recursive: true });
|
|
36255
36668
|
const jsonStr = JSON.stringify(jsonValue, null, 2) + "\n";
|
|
36256
36669
|
const jsonTmp = `${jsonPath}.tmp.${process.pid}.${randomBytes2(4).toString("hex")}`;
|
|
36257
36670
|
const bridgeTmp = `${bridgePath}.tmp.${process.pid}.${randomBytes2(4).toString("hex")}`;
|
|
36258
|
-
|
|
36671
|
+
writeFileSync28(jsonTmp, jsonStr, "utf8");
|
|
36259
36672
|
try {
|
|
36260
|
-
|
|
36673
|
+
writeFileSync28(bridgeTmp, bridgeMarkdown, "utf8");
|
|
36261
36674
|
} catch (e) {
|
|
36262
36675
|
try {
|
|
36263
36676
|
unlinkSync2(jsonTmp);
|
|
@@ -36265,9 +36678,9 @@ function writeJsonWithBridge(jsonPath, bridgePath, jsonValue, bridgeMarkdown) {
|
|
|
36265
36678
|
}
|
|
36266
36679
|
throw e;
|
|
36267
36680
|
}
|
|
36268
|
-
|
|
36681
|
+
renameSync7(jsonTmp, jsonPath);
|
|
36269
36682
|
try {
|
|
36270
|
-
|
|
36683
|
+
renameSync7(bridgeTmp, bridgePath);
|
|
36271
36684
|
} catch (e) {
|
|
36272
36685
|
try {
|
|
36273
36686
|
unlinkSync2(bridgeTmp);
|
|
@@ -36288,9 +36701,9 @@ function pidAlive(pid) {
|
|
|
36288
36701
|
}
|
|
36289
36702
|
function acquireLock() {
|
|
36290
36703
|
const lockPath = MARKETING_PATHS.lockFile();
|
|
36291
|
-
|
|
36292
|
-
if (
|
|
36293
|
-
const heldRaw =
|
|
36704
|
+
mkdirSync21(marketingRoot(), { recursive: true });
|
|
36705
|
+
if (existsSync42(lockPath)) {
|
|
36706
|
+
const heldRaw = readFileSync31(lockPath, "utf8").trim();
|
|
36294
36707
|
const heldPid = Number.parseInt(heldRaw, 10);
|
|
36295
36708
|
if (pidAlive(heldPid)) {
|
|
36296
36709
|
throw new LockBusyError(heldPid);
|
|
@@ -36306,19 +36719,19 @@ function acquireLock() {
|
|
|
36306
36719
|
} catch (e) {
|
|
36307
36720
|
const code = e.code;
|
|
36308
36721
|
if (code === "EEXIST") {
|
|
36309
|
-
const heldRaw =
|
|
36722
|
+
const heldRaw = existsSync42(lockPath) ? readFileSync31(lockPath, "utf8").trim() : "?";
|
|
36310
36723
|
throw new LockBusyError(Number.parseInt(heldRaw, 10) || -1);
|
|
36311
36724
|
}
|
|
36312
36725
|
throw e;
|
|
36313
36726
|
}
|
|
36314
36727
|
try {
|
|
36315
|
-
|
|
36728
|
+
writeFileSync28(fd, String(process.pid), "utf8");
|
|
36316
36729
|
} finally {
|
|
36317
36730
|
closeSync(fd);
|
|
36318
36731
|
}
|
|
36319
36732
|
return function release2() {
|
|
36320
36733
|
try {
|
|
36321
|
-
const heldRaw =
|
|
36734
|
+
const heldRaw = readFileSync31(lockPath, "utf8").trim();
|
|
36322
36735
|
if (Number.parseInt(heldRaw, 10) === process.pid) {
|
|
36323
36736
|
unlinkSync2(lockPath);
|
|
36324
36737
|
}
|
|
@@ -36337,7 +36750,7 @@ function newRunId(verb) {
|
|
|
36337
36750
|
return `${isoTs()}__${verb}`;
|
|
36338
36751
|
}
|
|
36339
36752
|
function runPath(runId) {
|
|
36340
|
-
return
|
|
36753
|
+
return join44(MARKETING_PATHS.runsDir(), `${runId}.json`);
|
|
36341
36754
|
}
|
|
36342
36755
|
function beginRun(verb, inputs) {
|
|
36343
36756
|
const id = newRunId(verb);
|
|
@@ -36380,24 +36793,24 @@ function beginRun(verb, inputs) {
|
|
|
36380
36793
|
}
|
|
36381
36794
|
function appendIndex(runId, verb, status) {
|
|
36382
36795
|
const path2 = MARKETING_PATHS.runsIndex();
|
|
36383
|
-
|
|
36796
|
+
mkdirSync21(dirname21(path2), { recursive: true });
|
|
36384
36797
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
36385
36798
|
const line = `- \`${ts}\` **${verb}** (${status}) \u2014 [\`${runId}\`](./${runId}.json)
|
|
36386
36799
|
`;
|
|
36387
36800
|
let header2 = "";
|
|
36388
36801
|
let body = "";
|
|
36389
|
-
if (
|
|
36390
|
-
body =
|
|
36802
|
+
if (existsSync42(path2)) {
|
|
36803
|
+
body = readFileSync31(path2, "utf8");
|
|
36391
36804
|
} else {
|
|
36392
36805
|
header2 = "# Marketing runs (LIFO)\n\n";
|
|
36393
36806
|
}
|
|
36394
36807
|
if (header2) {
|
|
36395
|
-
|
|
36808
|
+
writeFileSync28(path2, header2 + line + body, "utf8");
|
|
36396
36809
|
} else if (body.startsWith("# Marketing runs (LIFO)\n\n")) {
|
|
36397
36810
|
const HDR = "# Marketing runs (LIFO)\n\n";
|
|
36398
|
-
|
|
36811
|
+
writeFileSync28(path2, HDR + line + body.slice(HDR.length), "utf8");
|
|
36399
36812
|
} else {
|
|
36400
|
-
|
|
36813
|
+
writeFileSync28(path2, "# Marketing runs (LIFO)\n\n" + line + body, "utf8");
|
|
36401
36814
|
}
|
|
36402
36815
|
}
|
|
36403
36816
|
var LockBusyError;
|
|
@@ -36417,35 +36830,35 @@ var init_store = __esm({
|
|
|
36417
36830
|
});
|
|
36418
36831
|
|
|
36419
36832
|
// src/lib/marketing/cohort.ts
|
|
36420
|
-
import { existsSync as
|
|
36421
|
-
import { join as
|
|
36833
|
+
import { existsSync as existsSync43, readFileSync as readFileSync32, readdirSync as readdirSync12 } from "fs";
|
|
36834
|
+
import { join as join45 } from "path";
|
|
36422
36835
|
function newCohortId() {
|
|
36423
36836
|
return `coh_${idgen()}`;
|
|
36424
36837
|
}
|
|
36425
36838
|
function cohortPaths(id) {
|
|
36426
36839
|
const dir = MARKETING_PATHS.cohortsDir();
|
|
36427
36840
|
return {
|
|
36428
|
-
json:
|
|
36429
|
-
md:
|
|
36841
|
+
json: join45(dir, `${id}.json`),
|
|
36842
|
+
md: join45(dir, `${id}.md`)
|
|
36430
36843
|
};
|
|
36431
36844
|
}
|
|
36432
36845
|
function loadCohort(id) {
|
|
36433
36846
|
const { json } = cohortPaths(id);
|
|
36434
|
-
if (!
|
|
36847
|
+
if (!existsSync43(json)) return null;
|
|
36435
36848
|
try {
|
|
36436
|
-
return JSON.parse(
|
|
36849
|
+
return JSON.parse(readFileSync32(json, "utf8"));
|
|
36437
36850
|
} catch {
|
|
36438
36851
|
return null;
|
|
36439
36852
|
}
|
|
36440
36853
|
}
|
|
36441
36854
|
function listCohorts() {
|
|
36442
36855
|
const dir = MARKETING_PATHS.cohortsDir();
|
|
36443
|
-
if (!
|
|
36444
|
-
const files =
|
|
36856
|
+
if (!existsSync43(dir)) return [];
|
|
36857
|
+
const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
|
|
36445
36858
|
const cohorts = [];
|
|
36446
36859
|
for (const f of files) {
|
|
36447
36860
|
try {
|
|
36448
|
-
const c = JSON.parse(
|
|
36861
|
+
const c = JSON.parse(readFileSync32(join45(dir, f), "utf8"));
|
|
36449
36862
|
cohorts.push(c);
|
|
36450
36863
|
} catch {
|
|
36451
36864
|
}
|
|
@@ -36498,19 +36911,19 @@ var init_cohort = __esm({
|
|
|
36498
36911
|
|
|
36499
36912
|
// src/lib/marketing/learnings.ts
|
|
36500
36913
|
import {
|
|
36501
|
-
existsSync as
|
|
36502
|
-
mkdirSync as
|
|
36503
|
-
readFileSync as
|
|
36504
|
-
writeFileSync as
|
|
36505
|
-
renameSync as
|
|
36914
|
+
existsSync as existsSync44,
|
|
36915
|
+
mkdirSync as mkdirSync22,
|
|
36916
|
+
readFileSync as readFileSync33,
|
|
36917
|
+
writeFileSync as writeFileSync29,
|
|
36918
|
+
renameSync as renameSync8
|
|
36506
36919
|
} from "fs";
|
|
36507
|
-
import { dirname as
|
|
36920
|
+
import { dirname as dirname22 } from "path";
|
|
36508
36921
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
36509
36922
|
function atomicWriteFile2(path2, data) {
|
|
36510
|
-
|
|
36923
|
+
mkdirSync22(dirname22(path2), { recursive: true });
|
|
36511
36924
|
const tmp = `${path2}.tmp.${process.pid}.${randomBytes3(4).toString("hex")}`;
|
|
36512
|
-
|
|
36513
|
-
|
|
36925
|
+
writeFileSync29(tmp, data, "utf8");
|
|
36926
|
+
renameSync8(tmp, path2);
|
|
36514
36927
|
}
|
|
36515
36928
|
function newLearningId(type) {
|
|
36516
36929
|
return type === "ledger" ? `led_${idgen2()}` : `rec_${idgen2()}`;
|
|
@@ -36520,11 +36933,11 @@ function todayDateString(now = /* @__PURE__ */ new Date()) {
|
|
|
36520
36933
|
}
|
|
36521
36934
|
function loadIndex() {
|
|
36522
36935
|
const path2 = MARKETING_PATHS.learningsIndex();
|
|
36523
|
-
if (!
|
|
36936
|
+
if (!existsSync44(path2)) {
|
|
36524
36937
|
return { version: INDEX_VERSION, entries: [] };
|
|
36525
36938
|
}
|
|
36526
36939
|
try {
|
|
36527
|
-
const parsed = JSON.parse(
|
|
36940
|
+
const parsed = JSON.parse(readFileSync33(path2, "utf8"));
|
|
36528
36941
|
if (parsed.version !== INDEX_VERSION || !Array.isArray(parsed.entries)) {
|
|
36529
36942
|
return { version: INDEX_VERSION, entries: [] };
|
|
36530
36943
|
}
|
|
@@ -36538,8 +36951,8 @@ function saveIndex(index) {
|
|
|
36538
36951
|
}
|
|
36539
36952
|
function loadByDate(date) {
|
|
36540
36953
|
const path2 = MARKETING_PATHS.learningsFile(date);
|
|
36541
|
-
if (!
|
|
36542
|
-
return
|
|
36954
|
+
if (!existsSync44(path2)) return null;
|
|
36955
|
+
return readFileSync33(path2, "utf8");
|
|
36543
36956
|
}
|
|
36544
36957
|
function renderEntryBlock(entry, body) {
|
|
36545
36958
|
const time = entry.created_at.slice(11, 16);
|
|
@@ -36574,7 +36987,7 @@ function ensureDailyHeader(date, existing) {
|
|
|
36574
36987
|
}
|
|
36575
36988
|
function appendToDayFile(entry, body) {
|
|
36576
36989
|
const path2 = MARKETING_PATHS.learningsFile(entry.date_file);
|
|
36577
|
-
const existing =
|
|
36990
|
+
const existing = existsSync44(path2) ? readFileSync33(path2, "utf8") : null;
|
|
36578
36991
|
const base = ensureDailyHeader(entry.date_file, existing);
|
|
36579
36992
|
const block = renderEntryBlock(entry, body);
|
|
36580
36993
|
const next = existing && existing.startsWith("# Marketing learnings") ? existing.endsWith("\n") ? existing + block : existing + "\n" + block : base + block;
|
|
@@ -36582,8 +36995,8 @@ function appendToDayFile(entry, body) {
|
|
|
36582
36995
|
}
|
|
36583
36996
|
function rewriteDayFileForStatusUpdate(oldEntry, newEntry) {
|
|
36584
36997
|
const path2 = MARKETING_PATHS.learningsFile(oldEntry.date_file);
|
|
36585
|
-
if (!
|
|
36586
|
-
const text =
|
|
36998
|
+
if (!existsSync44(path2)) return;
|
|
36999
|
+
const text = readFileSync33(path2, "utf8");
|
|
36587
37000
|
const re = new RegExp(
|
|
36588
37001
|
`<!-- entry ([^>]*?id=${escapeRegExp(oldEntry.id)}[^>]*) -->`
|
|
36589
37002
|
);
|
|
@@ -36691,10 +37104,10 @@ var init_learnings = __esm({
|
|
|
36691
37104
|
});
|
|
36692
37105
|
|
|
36693
37106
|
// src/lib/marketing/snapshot.ts
|
|
36694
|
-
import { existsSync as
|
|
37107
|
+
import { existsSync as existsSync45, readFileSync as readFileSync34 } from "fs";
|
|
36695
37108
|
function buildMarketingSnapshot(opts = {}) {
|
|
36696
37109
|
const root = marketingRootIfExists();
|
|
36697
|
-
if (!root || !
|
|
37110
|
+
if (!root || !existsSync45(root)) return null;
|
|
36698
37111
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
36699
37112
|
const lines = ["## Marketing\n"];
|
|
36700
37113
|
const cohorts = listCohorts();
|
|
@@ -36751,9 +37164,9 @@ function cohortHypothesisLine(c) {
|
|
|
36751
37164
|
}
|
|
36752
37165
|
function readLastInsightsPull() {
|
|
36753
37166
|
const idxPath = MARKETING_PATHS.insightsDir() + "/_index.json";
|
|
36754
|
-
if (!
|
|
37167
|
+
if (!existsSync45(idxPath)) return null;
|
|
36755
37168
|
try {
|
|
36756
|
-
const raw = JSON.parse(
|
|
37169
|
+
const raw = JSON.parse(readFileSync34(idxPath, "utf8"));
|
|
36757
37170
|
return raw.updated_at && raw.updated_at !== "1970-01-01T00:00:00Z" ? raw.updated_at : null;
|
|
36758
37171
|
} catch {
|
|
36759
37172
|
return null;
|
|
@@ -36851,16 +37264,16 @@ var init_setup_drift = __esm({
|
|
|
36851
37264
|
});
|
|
36852
37265
|
|
|
36853
37266
|
// src/lib/asset-drift-cache.ts
|
|
36854
|
-
import { existsSync as
|
|
36855
|
-
import { join as
|
|
37267
|
+
import { existsSync as existsSync46, readFileSync as readFileSync35, writeFileSync as writeFileSync30, mkdirSync as mkdirSync23 } from "fs";
|
|
37268
|
+
import { join as join46, dirname as dirname23 } from "path";
|
|
36856
37269
|
function assetDriftCachePath(contextRoot) {
|
|
36857
|
-
return
|
|
37270
|
+
return join46(contextRoot, "state", ".asset-drift.json");
|
|
36858
37271
|
}
|
|
36859
37272
|
function readAssetDriftCache(contextRoot) {
|
|
36860
37273
|
try {
|
|
36861
37274
|
const p = assetDriftCachePath(contextRoot);
|
|
36862
|
-
if (!
|
|
36863
|
-
const parsed = JSON.parse(
|
|
37275
|
+
if (!existsSync46(p)) return null;
|
|
37276
|
+
const parsed = JSON.parse(readFileSync35(p, "utf-8"));
|
|
36864
37277
|
if (!parsed || typeof parsed.cliVersion !== "string" || typeof parsed.setupVersion !== "string" || typeof parsed.usedAssetsChanged !== "boolean") {
|
|
36865
37278
|
return null;
|
|
36866
37279
|
}
|
|
@@ -36876,8 +37289,8 @@ function readAssetDriftCache(contextRoot) {
|
|
|
36876
37289
|
}
|
|
36877
37290
|
function writeAssetDriftCache(contextRoot, cache) {
|
|
36878
37291
|
const p = assetDriftCachePath(contextRoot);
|
|
36879
|
-
|
|
36880
|
-
|
|
37292
|
+
mkdirSync23(dirname23(p), { recursive: true });
|
|
37293
|
+
writeFileSync30(p, JSON.stringify(cache, null, 2) + "\n", "utf-8");
|
|
36881
37294
|
}
|
|
36882
37295
|
function cacheConfidentlyClean(cache, cliVersion, setupVersion) {
|
|
36883
37296
|
return cache !== null && cache.cliVersion === cliVersion && cache.setupVersion === setupVersion && cache.usedAssetsChanged === false;
|
|
@@ -37022,8 +37435,8 @@ var init_recall_synonyms = __esm({
|
|
|
37022
37435
|
});
|
|
37023
37436
|
|
|
37024
37437
|
// src/lib/session-digest.ts
|
|
37025
|
-
import { existsSync as
|
|
37026
|
-
import { join as
|
|
37438
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync24, writeFileSync as writeFileSync31 } from "fs";
|
|
37439
|
+
import { join as join47 } from "path";
|
|
37027
37440
|
function coerceCreatedAt(value) {
|
|
37028
37441
|
if (typeof value === "string" && value.trim()) return value.trim();
|
|
37029
37442
|
if (value instanceof Date && !Number.isNaN(value.getTime())) return value.toISOString();
|
|
@@ -37081,18 +37494,18 @@ function enforceByteCap(lines, maxBytes) {
|
|
|
37081
37494
|
return out.trimEnd() + "\n";
|
|
37082
37495
|
}
|
|
37083
37496
|
function digestsDir(root) {
|
|
37084
|
-
return
|
|
37497
|
+
return join47(root, "state", DIGESTS_DIRNAME);
|
|
37085
37498
|
}
|
|
37086
37499
|
function digestPath(root, sessionId) {
|
|
37087
37500
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
37088
|
-
return
|
|
37501
|
+
return join47(digestsDir(root), `${safe}.md`);
|
|
37089
37502
|
}
|
|
37090
37503
|
function digestExists(root, sessionId) {
|
|
37091
|
-
return
|
|
37504
|
+
return existsSync47(digestPath(root, sessionId));
|
|
37092
37505
|
}
|
|
37093
37506
|
function digestIsPartial(root, sessionId) {
|
|
37094
37507
|
const file = digestPath(root, sessionId);
|
|
37095
|
-
if (!
|
|
37508
|
+
if (!existsSync47(file)) return false;
|
|
37096
37509
|
try {
|
|
37097
37510
|
const { data } = readFrontmatter(file);
|
|
37098
37511
|
return data.partial === true;
|
|
@@ -37102,7 +37515,7 @@ function digestIsPartial(root, sessionId) {
|
|
|
37102
37515
|
}
|
|
37103
37516
|
function writeDigest(root, sessionId, md, opts = {}) {
|
|
37104
37517
|
const dir = digestsDir(root);
|
|
37105
|
-
|
|
37518
|
+
mkdirSync24(dir, { recursive: true });
|
|
37106
37519
|
const file = digestPath(root, sessionId);
|
|
37107
37520
|
const safeId = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
37108
37521
|
const frontmatter = [
|
|
@@ -37114,12 +37527,12 @@ function writeDigest(root, sessionId, md, opts = {}) {
|
|
|
37114
37527
|
"---",
|
|
37115
37528
|
""
|
|
37116
37529
|
].join("\n");
|
|
37117
|
-
|
|
37530
|
+
writeFileSync31(file, frontmatter + md, "utf-8");
|
|
37118
37531
|
return file;
|
|
37119
37532
|
}
|
|
37120
37533
|
function loadDigestDocs(root) {
|
|
37121
37534
|
const dir = digestsDir(root);
|
|
37122
|
-
if (!
|
|
37535
|
+
if (!existsSync47(dir)) return [];
|
|
37123
37536
|
const files = import_fast_glob11.default.sync("*.md", { cwd: dir, absolute: true });
|
|
37124
37537
|
const parsed = [];
|
|
37125
37538
|
for (const file of files) {
|
|
@@ -37130,7 +37543,7 @@ function loadDigestDocs(root) {
|
|
|
37130
37543
|
const title = `Session digest ${sessionId}`;
|
|
37131
37544
|
const body = content.trim();
|
|
37132
37545
|
if (!body) continue;
|
|
37133
|
-
const relPath =
|
|
37546
|
+
const relPath = join47("state", DIGESTS_DIRNAME, `${sessionId}.md`);
|
|
37134
37547
|
const createdAt = coerceCreatedAt(data.created_at);
|
|
37135
37548
|
const fields = buildFields({ slug, title, description: "", tags: [], body });
|
|
37136
37549
|
const ms = createdAt ? Date.parse(createdAt) : NaN;
|
|
@@ -37182,8 +37595,8 @@ var init_session_digest = __esm({
|
|
|
37182
37595
|
});
|
|
37183
37596
|
|
|
37184
37597
|
// src/lib/recall.ts
|
|
37185
|
-
import { existsSync as
|
|
37186
|
-
import { join as
|
|
37598
|
+
import { existsSync as existsSync48, readFileSync as readFileSync37 } from "fs";
|
|
37599
|
+
import { join as join48, basename as basename12, dirname as dirname24, relative as relative3 } from "path";
|
|
37187
37600
|
function isFederated(doc) {
|
|
37188
37601
|
return doc.federated === true;
|
|
37189
37602
|
}
|
|
@@ -37272,7 +37685,7 @@ function productFromRelPath(relPath) {
|
|
|
37272
37685
|
return m ? m[1] : void 0;
|
|
37273
37686
|
}
|
|
37274
37687
|
function loadMarkdownDocs(dir, type, contextRoot) {
|
|
37275
|
-
if (!
|
|
37688
|
+
if (!existsSync48(dir)) return [];
|
|
37276
37689
|
const files = import_fast_glob12.default.sync("**/*.md", { cwd: dir, absolute: true });
|
|
37277
37690
|
const boardDirs = diagramFolderDirs(files);
|
|
37278
37691
|
const out = [];
|
|
@@ -37316,11 +37729,11 @@ function loadMarkdownDocs(dir, type, contextRoot) {
|
|
|
37316
37729
|
return out;
|
|
37317
37730
|
}
|
|
37318
37731
|
function loadChangelogEntries(contextRoot) {
|
|
37319
|
-
const path2 =
|
|
37320
|
-
if (!
|
|
37732
|
+
const path2 = join48(contextRoot, "core", "CHANGELOG.json");
|
|
37733
|
+
if (!existsSync48(path2)) return [];
|
|
37321
37734
|
let entries = [];
|
|
37322
37735
|
try {
|
|
37323
|
-
const raw =
|
|
37736
|
+
const raw = readFileSync37(path2, "utf-8");
|
|
37324
37737
|
const parsed = JSON.parse(raw);
|
|
37325
37738
|
if (Array.isArray(parsed)) entries = parsed;
|
|
37326
37739
|
} catch {
|
|
@@ -37368,9 +37781,9 @@ function loadChangelogEntries(contextRoot) {
|
|
|
37368
37781
|
return out;
|
|
37369
37782
|
}
|
|
37370
37783
|
function loadMemoryFile(contextRoot) {
|
|
37371
|
-
const path2 =
|
|
37372
|
-
if (!
|
|
37373
|
-
const raw =
|
|
37784
|
+
const path2 = join48(contextRoot, "core", "2.memory.md");
|
|
37785
|
+
if (!existsSync48(path2)) return [];
|
|
37786
|
+
const raw = readFileSync37(path2, "utf-8");
|
|
37374
37787
|
const sections = raw.split(/^##\s+/m).slice(1);
|
|
37375
37788
|
const out = [];
|
|
37376
37789
|
for (let i = 0; i < sections.length; i++) {
|
|
@@ -37402,11 +37815,11 @@ function loadMemoryFile(contextRoot) {
|
|
|
37402
37815
|
return out;
|
|
37403
37816
|
}
|
|
37404
37817
|
function loadBookmarkDocs(contextRoot) {
|
|
37405
|
-
const path2 =
|
|
37406
|
-
if (!
|
|
37818
|
+
const path2 = join48(contextRoot, "state", ".sleep.json");
|
|
37819
|
+
if (!existsSync48(path2)) return [];
|
|
37407
37820
|
let bookmarks = [];
|
|
37408
37821
|
try {
|
|
37409
|
-
const parsed = JSON.parse(
|
|
37822
|
+
const parsed = JSON.parse(readFileSync37(path2, "utf-8"));
|
|
37410
37823
|
if (parsed && typeof parsed === "object" && Array.isArray(parsed.bookmarks)) {
|
|
37411
37824
|
bookmarks = parsed.bookmarks;
|
|
37412
37825
|
}
|
|
@@ -37448,14 +37861,14 @@ function loadBookmarkDocs(contextRoot) {
|
|
|
37448
37861
|
return out;
|
|
37449
37862
|
}
|
|
37450
37863
|
function loadSkillDocs(skillsRoot) {
|
|
37451
|
-
if (!
|
|
37864
|
+
if (!existsSync48(skillsRoot)) return [];
|
|
37452
37865
|
const files = import_fast_glob12.default.sync("*/SKILL.md", { cwd: skillsRoot, absolute: true });
|
|
37453
37866
|
const out = [];
|
|
37454
37867
|
for (const file of files) {
|
|
37455
37868
|
try {
|
|
37456
37869
|
const { data, content } = readFrontmatter(file);
|
|
37457
37870
|
if (data.alwaysApply === true) continue;
|
|
37458
|
-
const slug = typeof data.name === "string" && data.name ? data.name : basename12(
|
|
37871
|
+
const slug = typeof data.name === "string" && data.name ? data.name : basename12(dirname24(file));
|
|
37459
37872
|
const title = slug;
|
|
37460
37873
|
const description = typeof data.description === "string" ? data.description : "";
|
|
37461
37874
|
const tags = Array.isArray(data.tags) ? data.tags.map(String) : [];
|
|
@@ -37487,13 +37900,13 @@ function buildCorpus(contextRoot, opts = {}) {
|
|
|
37487
37900
|
const types = new Set(opts.types ?? ["knowledge", "feature", "task", "memory", "changelog"]);
|
|
37488
37901
|
const docs = [];
|
|
37489
37902
|
if (types.has("knowledge")) {
|
|
37490
|
-
docs.push(...loadMarkdownDocs(
|
|
37903
|
+
docs.push(...loadMarkdownDocs(join48(contextRoot, "knowledge"), "knowledge", contextRoot));
|
|
37491
37904
|
}
|
|
37492
37905
|
if (types.has("feature")) {
|
|
37493
|
-
docs.push(...loadMarkdownDocs(
|
|
37906
|
+
docs.push(...loadMarkdownDocs(join48(contextRoot, "core", "features"), "feature", contextRoot));
|
|
37494
37907
|
}
|
|
37495
37908
|
if (types.has("task")) {
|
|
37496
|
-
docs.push(...loadMarkdownDocs(
|
|
37909
|
+
docs.push(...loadMarkdownDocs(join48(contextRoot, "state"), "task", contextRoot));
|
|
37497
37910
|
docs.push(...loadDigestDocs(contextRoot));
|
|
37498
37911
|
}
|
|
37499
37912
|
if (types.has("memory")) {
|
|
@@ -37855,7 +38268,7 @@ var init_federation_config = __esm({
|
|
|
37855
38268
|
});
|
|
37856
38269
|
|
|
37857
38270
|
// src/lib/federation-recall.ts
|
|
37858
|
-
import { basename as basename13, dirname as
|
|
38271
|
+
import { basename as basename13, dirname as dirname25 } from "path";
|
|
37859
38272
|
function namespacedKey(vault, type, slug) {
|
|
37860
38273
|
return `${vault}::${type}/${slug}`;
|
|
37861
38274
|
}
|
|
@@ -37880,7 +38293,7 @@ function crossVaultRecall(query, opts) {
|
|
|
37880
38293
|
}
|
|
37881
38294
|
const isCurrent = target.current === true;
|
|
37882
38295
|
if (!isCurrent) {
|
|
37883
|
-
const projectRoot =
|
|
38296
|
+
const projectRoot = dirname25(contextRoot);
|
|
37884
38297
|
if (!isShareable(projectRoot)) continue;
|
|
37885
38298
|
}
|
|
37886
38299
|
const corpus = buildCorpus(contextRoot, opts.types ? { types: opts.types } : {}).filter((doc) => !isFederated(doc));
|
|
@@ -37953,16 +38366,16 @@ var init_federation_recall = __esm({
|
|
|
37953
38366
|
});
|
|
37954
38367
|
|
|
37955
38368
|
// src/lib/federation-peer-summary.ts
|
|
37956
|
-
import { existsSync as
|
|
37957
|
-
import { dirname as
|
|
38369
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync25, readFileSync as readFileSync38, writeFileSync as writeFileSync32 } from "fs";
|
|
38370
|
+
import { dirname as dirname26, join as join49 } from "path";
|
|
37958
38371
|
function peerSummaryCachePath(contextRoot) {
|
|
37959
|
-
return
|
|
38372
|
+
return join49(contextRoot, CACHE_REL_PATH2);
|
|
37960
38373
|
}
|
|
37961
38374
|
function readPeerSummaryCache(contextRoot) {
|
|
37962
38375
|
const path2 = peerSummaryCachePath(contextRoot);
|
|
37963
|
-
if (!
|
|
38376
|
+
if (!existsSync49(path2)) return null;
|
|
37964
38377
|
try {
|
|
37965
|
-
const parsed = JSON.parse(
|
|
38378
|
+
const parsed = JSON.parse(readFileSync38(path2, "utf-8"));
|
|
37966
38379
|
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.peers)) return null;
|
|
37967
38380
|
const peers = parsed.peers.filter((p) => p !== null && typeof p === "object").map(sanitizePeer);
|
|
37968
38381
|
return {
|
|
@@ -37993,8 +38406,8 @@ function buildPeerSummary(peerRoot, peerName) {
|
|
|
37993
38406
|
};
|
|
37994
38407
|
}
|
|
37995
38408
|
function readWhatItIs(peerRoot) {
|
|
37996
|
-
const soulPath =
|
|
37997
|
-
if (!
|
|
38409
|
+
const soulPath = join49(peerRoot, "core", "0.soul.md");
|
|
38410
|
+
if (!existsSync49(soulPath)) return "";
|
|
37998
38411
|
try {
|
|
37999
38412
|
const { data, content } = readFrontmatter(soulPath);
|
|
38000
38413
|
const name = typeof data.name === "string" ? data.name : "";
|
|
@@ -38011,8 +38424,8 @@ function readWhatItIs(peerRoot) {
|
|
|
38011
38424
|
}
|
|
38012
38425
|
}
|
|
38013
38426
|
function readLastActivity(peerRoot) {
|
|
38014
|
-
const path2 =
|
|
38015
|
-
if (!
|
|
38427
|
+
const path2 = join49(peerRoot, "core", "CHANGELOG.json");
|
|
38428
|
+
if (!existsSync49(path2)) return [];
|
|
38016
38429
|
try {
|
|
38017
38430
|
const entries = readJsonArray(path2);
|
|
38018
38431
|
const out = [];
|
|
@@ -38030,8 +38443,8 @@ function readLastActivity(peerRoot) {
|
|
|
38030
38443
|
}
|
|
38031
38444
|
}
|
|
38032
38445
|
function readActiveTask(peerRoot) {
|
|
38033
|
-
const stateDir =
|
|
38034
|
-
if (!
|
|
38446
|
+
const stateDir = join49(peerRoot, "state");
|
|
38447
|
+
if (!existsSync49(stateDir)) return "";
|
|
38035
38448
|
let files;
|
|
38036
38449
|
try {
|
|
38037
38450
|
files = import_fast_glob13.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
@@ -38059,9 +38472,9 @@ function readActiveTask(peerRoot) {
|
|
|
38059
38472
|
}
|
|
38060
38473
|
function readTopTags(peerRoot) {
|
|
38061
38474
|
const counts = /* @__PURE__ */ new Map();
|
|
38062
|
-
const dirs = [
|
|
38475
|
+
const dirs = [join49(peerRoot, "knowledge"), join49(peerRoot, "core", "features")];
|
|
38063
38476
|
for (const dir of dirs) {
|
|
38064
|
-
if (!
|
|
38477
|
+
if (!existsSync49(dir)) continue;
|
|
38065
38478
|
let files;
|
|
38066
38479
|
try {
|
|
38067
38480
|
files = import_fast_glob13.default.sync("*.md", { cwd: dir, absolute: true });
|
|
@@ -38083,7 +38496,7 @@ function readTopTags(peerRoot) {
|
|
|
38083
38496
|
return Array.from(counts.entries()).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_TAGS).map(([t]) => t);
|
|
38084
38497
|
}
|
|
38085
38498
|
function refreshPeerSummaries(contextRoot, home) {
|
|
38086
|
-
const { name, target } = currentVaultTarget(
|
|
38499
|
+
const { name, target } = currentVaultTarget(dirname26(contextRoot), home);
|
|
38087
38500
|
const targets = resolveConnectedVaults(target, contextRoot, home).filter(
|
|
38088
38501
|
(t) => t.current !== true && t.name !== name
|
|
38089
38502
|
);
|
|
@@ -38103,8 +38516,8 @@ function refreshPeerSummaries(contextRoot, home) {
|
|
|
38103
38516
|
}
|
|
38104
38517
|
function writePeerSummaryCache(contextRoot, cache) {
|
|
38105
38518
|
const path2 = peerSummaryCachePath(contextRoot);
|
|
38106
|
-
|
|
38107
|
-
|
|
38519
|
+
mkdirSync25(dirname26(path2), { recursive: true });
|
|
38520
|
+
writeFileSync32(path2, JSON.stringify(cache, null, 2) + "\n", "utf-8");
|
|
38108
38521
|
}
|
|
38109
38522
|
var import_fast_glob13, CACHE_REL_PATH2, MAX_ACTIVITY, MAX_TAGS, WHAT_IT_IS_CHARS;
|
|
38110
38523
|
var init_federation_peer_summary = __esm({
|
|
@@ -38227,8 +38640,8 @@ var init_snapshot_budget = __esm({
|
|
|
38227
38640
|
});
|
|
38228
38641
|
|
|
38229
38642
|
// src/cli/commands/snapshot.ts
|
|
38230
|
-
import { readFileSync as
|
|
38231
|
-
import { join as
|
|
38643
|
+
import { readFileSync as readFileSync39, existsSync as existsSync50, statSync as statSync5 } from "fs";
|
|
38644
|
+
import { join as join50, basename as basename14, dirname as dirname27 } from "path";
|
|
38232
38645
|
function extractFirstParagraph(content) {
|
|
38233
38646
|
const lines = content.split("\n");
|
|
38234
38647
|
const paragraphLines = [];
|
|
@@ -38262,8 +38675,8 @@ function sortTaskEntriesByActivity(entries) {
|
|
|
38262
38675
|
return [...entries].sort((a, b) => statusRank(a.status) - statusRank(b.status) || prioRank(a.priority) - prioRank(b.priority) || b.updated.localeCompare(a.updated));
|
|
38263
38676
|
}
|
|
38264
38677
|
function getActiveTaskEntries(root) {
|
|
38265
|
-
const stateDir =
|
|
38266
|
-
if (!
|
|
38678
|
+
const stateDir = join50(root, "state");
|
|
38679
|
+
if (!existsSync50(stateDir)) return [];
|
|
38267
38680
|
const taskFiles = import_fast_glob14.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
38268
38681
|
const entries = [];
|
|
38269
38682
|
for (const file of taskFiles) {
|
|
@@ -38295,15 +38708,15 @@ function getActiveTaskEntries(root) {
|
|
|
38295
38708
|
return entries;
|
|
38296
38709
|
}
|
|
38297
38710
|
function resolveActiveTaskPath(root) {
|
|
38298
|
-
const stateDir =
|
|
38299
|
-
if (!
|
|
38300
|
-
const overridePath =
|
|
38301
|
-
if (
|
|
38711
|
+
const stateDir = join50(root, "state");
|
|
38712
|
+
if (!existsSync50(stateDir)) return null;
|
|
38713
|
+
const overridePath = join50(stateDir, ".active-task");
|
|
38714
|
+
if (existsSync50(overridePath)) {
|
|
38302
38715
|
try {
|
|
38303
|
-
const slug =
|
|
38716
|
+
const slug = readFileSync39(overridePath, "utf-8").trim();
|
|
38304
38717
|
if (slug) {
|
|
38305
|
-
const taskPath =
|
|
38306
|
-
if (
|
|
38718
|
+
const taskPath = join50(stateDir, `${slug}.md`);
|
|
38719
|
+
if (existsSync50(taskPath)) return taskPath;
|
|
38307
38720
|
}
|
|
38308
38721
|
} catch {
|
|
38309
38722
|
}
|
|
@@ -38329,7 +38742,7 @@ function resolveActiveTaskPath(root) {
|
|
|
38329
38742
|
return candidates[0].path;
|
|
38330
38743
|
}
|
|
38331
38744
|
function getActiveProductKnowledge(root) {
|
|
38332
|
-
const config = readSetupConfig(
|
|
38745
|
+
const config = readSetupConfig(dirname27(root));
|
|
38333
38746
|
if (!config || !Array.isArray(config.multiProduct) || config.multiProduct.length === 0) {
|
|
38334
38747
|
return [];
|
|
38335
38748
|
}
|
|
@@ -38346,11 +38759,11 @@ function getActiveProductKnowledge(root) {
|
|
|
38346
38759
|
}
|
|
38347
38760
|
if (!product) return [];
|
|
38348
38761
|
if (!config.multiProduct.includes(product)) return [];
|
|
38349
|
-
const productKnowledgePath =
|
|
38350
|
-
if (!
|
|
38762
|
+
const productKnowledgePath = join50(root, "knowledge", "products", `${product}.md`);
|
|
38763
|
+
if (!existsSync50(productKnowledgePath)) return [];
|
|
38351
38764
|
let raw;
|
|
38352
38765
|
try {
|
|
38353
|
-
raw =
|
|
38766
|
+
raw = readFileSync39(productKnowledgePath, "utf-8");
|
|
38354
38767
|
} catch {
|
|
38355
38768
|
return [];
|
|
38356
38769
|
}
|
|
@@ -38385,7 +38798,7 @@ function getActiveProductKnowledge(root) {
|
|
|
38385
38798
|
}
|
|
38386
38799
|
function getVersionNudge(root) {
|
|
38387
38800
|
try {
|
|
38388
|
-
const projectRoot =
|
|
38801
|
+
const projectRoot = dirname27(root);
|
|
38389
38802
|
const cache = readVersionCache(projectRoot);
|
|
38390
38803
|
if (!cache || !isCacheFresh(cache)) return "";
|
|
38391
38804
|
const installedCli = dreamcontextVersion();
|
|
@@ -38401,9 +38814,9 @@ function getVersionNudge(root) {
|
|
|
38401
38814
|
}
|
|
38402
38815
|
function getMigrationNote(root) {
|
|
38403
38816
|
try {
|
|
38404
|
-
const sleepPath =
|
|
38405
|
-
if (!
|
|
38406
|
-
const raw =
|
|
38817
|
+
const sleepPath = join50(root, "state", ".sleep.json");
|
|
38818
|
+
if (!existsSync50(sleepPath)) return "";
|
|
38819
|
+
const raw = readFileSync39(sleepPath, "utf-8");
|
|
38407
38820
|
const parsed = JSON.parse(raw);
|
|
38408
38821
|
if (!parsed || !Array.isArray(parsed.pendingMigrationNotices) || parsed.pendingMigrationNotices.length === 0) {
|
|
38409
38822
|
return "";
|
|
@@ -38421,7 +38834,7 @@ Migrations applied since last session: ${notices.join("; ")}`;
|
|
|
38421
38834
|
}
|
|
38422
38835
|
function getDriftDirective(root) {
|
|
38423
38836
|
try {
|
|
38424
|
-
const projectRoot =
|
|
38837
|
+
const projectRoot = dirname27(root);
|
|
38425
38838
|
const config = readSetupConfig(projectRoot);
|
|
38426
38839
|
if (!config) return "";
|
|
38427
38840
|
const cliVersion = dreamcontextVersion();
|
|
@@ -38451,24 +38864,24 @@ function generateSnapshot(rootOverride) {
|
|
|
38451
38864
|
parts = [];
|
|
38452
38865
|
}
|
|
38453
38866
|
};
|
|
38454
|
-
const soulPath =
|
|
38455
|
-
if (
|
|
38456
|
-
const content =
|
|
38867
|
+
const soulPath = join50(root, "core", "0.soul.md");
|
|
38868
|
+
if (existsSync50(soulPath)) {
|
|
38869
|
+
const content = readFileSync39(soulPath, "utf-8").trim();
|
|
38457
38870
|
parts.push("## Soul (Agent Identity, Principles, Rules)\n");
|
|
38458
38871
|
parts.push(content);
|
|
38459
38872
|
parts.push("");
|
|
38460
38873
|
}
|
|
38461
|
-
const userPath =
|
|
38462
|
-
if (
|
|
38463
|
-
const content =
|
|
38874
|
+
const userPath = join50(root, "core", "1.user.md");
|
|
38875
|
+
if (existsSync50(userPath)) {
|
|
38876
|
+
const content = readFileSync39(userPath, "utf-8").trim();
|
|
38464
38877
|
parts.push("## User (Preferences, Project Details, Rules)\n");
|
|
38465
38878
|
parts.push(content);
|
|
38466
38879
|
parts.push("");
|
|
38467
38880
|
}
|
|
38468
38881
|
flush("identity", { neverEvict: true });
|
|
38469
|
-
const memoryPath =
|
|
38470
|
-
if (
|
|
38471
|
-
const content =
|
|
38882
|
+
const memoryPath = join50(root, "core", "2.memory.md");
|
|
38883
|
+
if (existsSync50(memoryPath)) {
|
|
38884
|
+
const content = readFileSync39(memoryPath, "utf-8").trim();
|
|
38472
38885
|
if (content) {
|
|
38473
38886
|
parts.push("## Memory (Technical Decisions, Known Issues, Session Log)\n");
|
|
38474
38887
|
parts.push(content);
|
|
@@ -38533,8 +38946,8 @@ function generateSnapshot(rootOverride) {
|
|
|
38533
38946
|
if (sleepState.triggers.length > 0) {
|
|
38534
38947
|
const taskNames = [];
|
|
38535
38948
|
const taskTags = [];
|
|
38536
|
-
const stateDir =
|
|
38537
|
-
if (
|
|
38949
|
+
const stateDir = join50(root, "state");
|
|
38950
|
+
if (existsSync50(stateDir)) {
|
|
38538
38951
|
const taskFiles = import_fast_glob14.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
38539
38952
|
for (const file of taskFiles) {
|
|
38540
38953
|
try {
|
|
@@ -38570,14 +38983,14 @@ function generateSnapshot(rootOverride) {
|
|
|
38570
38983
|
const CHANGELOG_TIER2 = 10;
|
|
38571
38984
|
const TIER1_BODY_CHARS = 300;
|
|
38572
38985
|
const TIER2_LINE_CHARS = 140;
|
|
38573
|
-
const multiPerson = isMultiPerson(readSetupConfig(
|
|
38986
|
+
const multiPerson = isMultiPerson(readSetupConfig(dirname27(root)));
|
|
38574
38987
|
const authorSuffix = (e) => {
|
|
38575
38988
|
if (!multiPerson) return "";
|
|
38576
38989
|
const authors = Array.isArray(e.authors) ? e.authors.filter((a) => typeof a === "string") : [];
|
|
38577
38990
|
return authors.length > 0 ? ` \u2014 by ${authors.join(", ")}` : "";
|
|
38578
38991
|
};
|
|
38579
|
-
const changelogPath =
|
|
38580
|
-
if (
|
|
38992
|
+
const changelogPath = join50(root, "core", "CHANGELOG.json");
|
|
38993
|
+
if (existsSync50(changelogPath)) {
|
|
38581
38994
|
try {
|
|
38582
38995
|
const entries = readJsonArray(changelogPath);
|
|
38583
38996
|
const tier1 = entries.slice(0, CHANGELOG_TIER1);
|
|
@@ -38633,8 +39046,8 @@ function generateSnapshot(rootOverride) {
|
|
|
38633
39046
|
} catch {
|
|
38634
39047
|
}
|
|
38635
39048
|
}
|
|
38636
|
-
const releasesPath =
|
|
38637
|
-
if (
|
|
39049
|
+
const releasesPath = join50(root, "core", "RELEASES.json");
|
|
39050
|
+
if (existsSync50(releasesPath)) {
|
|
38638
39051
|
try {
|
|
38639
39052
|
const releases = readJsonArray(releasesPath);
|
|
38640
39053
|
if (releases.length > 0) {
|
|
@@ -38670,8 +39083,8 @@ function generateSnapshot(rootOverride) {
|
|
|
38670
39083
|
}
|
|
38671
39084
|
}
|
|
38672
39085
|
flush("releases", { neverEvict: true });
|
|
38673
|
-
const featuresDir =
|
|
38674
|
-
if (
|
|
39086
|
+
const featuresDir = join50(root, "core", "features");
|
|
39087
|
+
if (existsSync50(featuresDir)) {
|
|
38675
39088
|
const featureFiles = import_fast_glob14.default.sync("*.md", { cwd: featuresDir, absolute: true });
|
|
38676
39089
|
const features = [];
|
|
38677
39090
|
const featureMeta = [];
|
|
@@ -38759,8 +39172,8 @@ function generateSnapshot(rootOverride) {
|
|
|
38759
39172
|
const pinnedEntries = [];
|
|
38760
39173
|
const warmEntries = [];
|
|
38761
39174
|
const activeTaskTags = [];
|
|
38762
|
-
const stDir =
|
|
38763
|
-
if (
|
|
39175
|
+
const stDir = join50(root, "state");
|
|
39176
|
+
if (existsSync50(stDir)) {
|
|
38764
39177
|
const tFiles = import_fast_glob14.default.sync("*.md", { cwd: stDir, absolute: true });
|
|
38765
39178
|
for (const file of tFiles) {
|
|
38766
39179
|
try {
|
|
@@ -38916,8 +39329,8 @@ function generateSubagentBriefing() {
|
|
|
38916
39329
|
parts.push('`dreamcontext memory recall "<keywords>"` (BM25 over knowledge/features/tasks/');
|
|
38917
39330
|
parts.push("memory/changelog, <100ms, zero token overhead) BEFORE Glob/Grep \u2014 it frequently");
|
|
38918
39331
|
parts.push("beats blind exploration outright.\n");
|
|
38919
|
-
const soulPath =
|
|
38920
|
-
if (
|
|
39332
|
+
const soulPath = join50(root, "core", "0.soul.md");
|
|
39333
|
+
if (existsSync50(soulPath)) {
|
|
38921
39334
|
const { data, content } = readFrontmatter(soulPath);
|
|
38922
39335
|
const projectName = typeof data.name === "string" ? data.name : "";
|
|
38923
39336
|
const lines = content.split("\n");
|
|
@@ -38936,8 +39349,8 @@ function generateSubagentBriefing() {
|
|
|
38936
39349
|
`);
|
|
38937
39350
|
}
|
|
38938
39351
|
}
|
|
38939
|
-
const featuresDir =
|
|
38940
|
-
if (
|
|
39352
|
+
const featuresDir = join50(root, "core", "features");
|
|
39353
|
+
if (existsSync50(featuresDir)) {
|
|
38941
39354
|
const featureFiles = import_fast_glob14.default.sync("*.md", { cwd: featuresDir, absolute: true });
|
|
38942
39355
|
const features = [];
|
|
38943
39356
|
for (const file of featureFiles) {
|
|
@@ -39004,8 +39417,8 @@ function generateSubagentBriefing() {
|
|
|
39004
39417
|
}
|
|
39005
39418
|
parts.push("");
|
|
39006
39419
|
}
|
|
39007
|
-
const coreDir =
|
|
39008
|
-
if (
|
|
39420
|
+
const coreDir = join50(root, "core");
|
|
39421
|
+
if (existsSync50(coreDir)) {
|
|
39009
39422
|
const allCoreFiles = import_fast_glob14.default.sync(["[0-9]*"], { cwd: coreDir, absolute: true });
|
|
39010
39423
|
allCoreFiles.sort((a, b) => basename14(a).localeCompare(basename14(b), void 0, { numeric: true }));
|
|
39011
39424
|
if (allCoreFiles.length > 0) {
|
|
@@ -39149,7 +39562,7 @@ var init_salience = __esm({
|
|
|
39149
39562
|
});
|
|
39150
39563
|
|
|
39151
39564
|
// src/cli/commands/transcript.ts
|
|
39152
|
-
import { readFileSync as
|
|
39565
|
+
import { readFileSync as readFileSync40, existsSync as existsSync51, statSync as statSync6 } from "fs";
|
|
39153
39566
|
function distillTranscript(transcriptPath, sinceTimestamp) {
|
|
39154
39567
|
const result = {
|
|
39155
39568
|
userMessages: [],
|
|
@@ -39158,11 +39571,11 @@ function distillTranscript(transcriptPath, sinceTimestamp) {
|
|
|
39158
39571
|
errors: [],
|
|
39159
39572
|
bookmarks: []
|
|
39160
39573
|
};
|
|
39161
|
-
if (!
|
|
39574
|
+
if (!existsSync51(transcriptPath)) return result;
|
|
39162
39575
|
try {
|
|
39163
39576
|
const stat = statSync6(transcriptPath);
|
|
39164
39577
|
if (stat.size === 0 || stat.size > MAX_TRANSCRIPT_BYTES) return result;
|
|
39165
|
-
const content =
|
|
39578
|
+
const content = readFileSync40(transcriptPath, "utf-8");
|
|
39166
39579
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
39167
39580
|
for (const line of lines) {
|
|
39168
39581
|
let entry;
|
|
@@ -39346,7 +39759,7 @@ function registerTranscriptCommand(program2) {
|
|
|
39346
39759
|
error(`No transcript path for session: ${sessionId}`);
|
|
39347
39760
|
return;
|
|
39348
39761
|
}
|
|
39349
|
-
if (!
|
|
39762
|
+
if (!existsSync51(session.transcript_path)) {
|
|
39350
39763
|
error(`Transcript file not found: ${session.transcript_path}`);
|
|
39351
39764
|
return;
|
|
39352
39765
|
}
|
|
@@ -39390,22 +39803,22 @@ var init_transcript = __esm({
|
|
|
39390
39803
|
});
|
|
39391
39804
|
|
|
39392
39805
|
// src/lib/marketing/path-guards.ts
|
|
39393
|
-
import { existsSync as
|
|
39394
|
-
import { basename as basename15, dirname as
|
|
39806
|
+
import { existsSync as existsSync52, realpathSync } from "fs";
|
|
39807
|
+
import { basename as basename15, dirname as dirname28, resolve as resolve9, sep as sep5 } from "path";
|
|
39395
39808
|
function isMarketingEnvPath(filePath, from) {
|
|
39396
39809
|
if (!filePath) return false;
|
|
39397
39810
|
const root = resolveContextRoot(from);
|
|
39398
39811
|
if (!root) return false;
|
|
39399
39812
|
const realRoot = realpathOrSelf(root);
|
|
39400
|
-
const target =
|
|
39401
|
-
const realCandidate = realpathOfNearestAncestor(
|
|
39813
|
+
const target = resolve9(realRoot, "marketing", ".env");
|
|
39814
|
+
const realCandidate = realpathOfNearestAncestor(resolve9(filePath));
|
|
39402
39815
|
if (realCandidate === target) return true;
|
|
39403
39816
|
if (!realCandidate.startsWith(realRoot + sep5)) return false;
|
|
39404
39817
|
return realCandidate.endsWith(`${sep5}marketing${sep5}.env`);
|
|
39405
39818
|
}
|
|
39406
39819
|
function realpathOrSelf(p) {
|
|
39407
39820
|
try {
|
|
39408
|
-
return
|
|
39821
|
+
return existsSync52(p) ? realpathSync(p) : p;
|
|
39409
39822
|
} catch {
|
|
39410
39823
|
return p;
|
|
39411
39824
|
}
|
|
@@ -39413,9 +39826,9 @@ function realpathOrSelf(p) {
|
|
|
39413
39826
|
function realpathOfNearestAncestor(p) {
|
|
39414
39827
|
let current = p;
|
|
39415
39828
|
const tail = [];
|
|
39416
|
-
while (current && current !== sep5 && !
|
|
39829
|
+
while (current && current !== sep5 && !existsSync52(current)) {
|
|
39417
39830
|
tail.unshift(basename15(current));
|
|
39418
|
-
current =
|
|
39831
|
+
current = dirname28(current);
|
|
39419
39832
|
}
|
|
39420
39833
|
if (!current || current === sep5) return p;
|
|
39421
39834
|
try {
|
|
@@ -39433,7 +39846,7 @@ var init_path_guards = __esm({
|
|
|
39433
39846
|
});
|
|
39434
39847
|
|
|
39435
39848
|
// src/lib/recall-query-extractor.ts
|
|
39436
|
-
import { execFileSync as
|
|
39849
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
39437
39850
|
function buildCorpusIndex(corpus) {
|
|
39438
39851
|
return corpus.map((d) => {
|
|
39439
39852
|
const desc = d.description ? ` \u2014 ${d.description}` : "";
|
|
@@ -39532,7 +39945,7 @@ If nothing is relevant: {"docs":[],"skip":false}
|
|
|
39532
39945
|
If pure greeting: {"skip":true}`;
|
|
39533
39946
|
DEFAULT_TIMEOUT_MS2 = 12e4;
|
|
39534
39947
|
defaultExecutor = (prompt, systemPrompt) => {
|
|
39535
|
-
return
|
|
39948
|
+
return execFileSync4("claude", [
|
|
39536
39949
|
"--model",
|
|
39537
39950
|
"haiku",
|
|
39538
39951
|
"-p",
|
|
@@ -39554,371 +39967,6 @@ If pure greeting: {"skip":true}`;
|
|
|
39554
39967
|
}
|
|
39555
39968
|
});
|
|
39556
39969
|
|
|
39557
|
-
// src/cli/commands/app.ts
|
|
39558
|
-
import { execFileSync as execFileSync3, spawn as spawnProcess } from "child_process";
|
|
39559
|
-
import {
|
|
39560
|
-
existsSync as existsSync52,
|
|
39561
|
-
mkdirSync as mkdirSync25,
|
|
39562
|
-
mkdtempSync,
|
|
39563
|
-
readFileSync as readFileSync40,
|
|
39564
|
-
writeFileSync as writeFileSync32,
|
|
39565
|
-
rmSync as rmSync6,
|
|
39566
|
-
renameSync as renameSync8,
|
|
39567
|
-
readdirSync as readdirSync12
|
|
39568
|
-
} from "fs";
|
|
39569
|
-
import { homedir as homedir2, tmpdir } from "os";
|
|
39570
|
-
import { join as join50, resolve as resolve9, dirname as dirname28 } from "path";
|
|
39571
|
-
import { createHash as createHash2 } from "crypto";
|
|
39572
|
-
function detectPlatform(platform2 = process.platform, arch2 = process.arch) {
|
|
39573
|
-
const os3 = platform2 === "darwin" ? "darwin" : platform2 === "win32" ? "win32" : platform2 === "linux" ? "linux" : "other";
|
|
39574
|
-
const a = arch2 === "arm64" ? "aarch64" : arch2 === "x64" ? "x86_64" : "other";
|
|
39575
|
-
return { os: os3, arch: a };
|
|
39576
|
-
}
|
|
39577
|
-
function pickAssetForArch(assetNames, arch2) {
|
|
39578
|
-
const appAssets = assetNames.filter((n) => n.endsWith(".app.tar.gz"));
|
|
39579
|
-
const exact = appAssets.find((n) => n.includes(`_${arch2}.`));
|
|
39580
|
-
return exact ?? null;
|
|
39581
|
-
}
|
|
39582
|
-
function defaultInstallDir(home = homedir2()) {
|
|
39583
|
-
return join50(home, "Applications");
|
|
39584
|
-
}
|
|
39585
|
-
function appManifestPath(home = homedir2()) {
|
|
39586
|
-
return join50(home, ".dreamcontext", "app.json");
|
|
39587
|
-
}
|
|
39588
|
-
function readAppManifest(home = homedir2()) {
|
|
39589
|
-
const p = appManifestPath(home);
|
|
39590
|
-
if (!existsSync52(p)) return null;
|
|
39591
|
-
try {
|
|
39592
|
-
const parsed = JSON.parse(readFileSync40(p, "utf-8"));
|
|
39593
|
-
if (!parsed || typeof parsed.version !== "string" || typeof parsed.path !== "string") return null;
|
|
39594
|
-
return {
|
|
39595
|
-
version: parsed.version,
|
|
39596
|
-
path: parsed.path,
|
|
39597
|
-
installedAt: typeof parsed.installedAt === "number" ? parsed.installedAt : 0,
|
|
39598
|
-
source: typeof parsed.source === "string" ? parsed.source : "unknown"
|
|
39599
|
-
};
|
|
39600
|
-
} catch {
|
|
39601
|
-
return null;
|
|
39602
|
-
}
|
|
39603
|
-
}
|
|
39604
|
-
function writeAppManifest(manifest, home = homedir2()) {
|
|
39605
|
-
const p = appManifestPath(home);
|
|
39606
|
-
mkdirSync25(dirname28(p), { recursive: true });
|
|
39607
|
-
writeFileSync32(p, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
39608
|
-
}
|
|
39609
|
-
function run(cmd, args) {
|
|
39610
|
-
execFileSync3(cmd, args, { stdio: ["ignore", "ignore", "pipe"] });
|
|
39611
|
-
}
|
|
39612
|
-
function runCapture(cmd, args) {
|
|
39613
|
-
return execFileSync3(cmd, args, { encoding: "utf-8" }).toString().trim();
|
|
39614
|
-
}
|
|
39615
|
-
function validateAppBundle(appDir) {
|
|
39616
|
-
if (!appDir.endsWith(".app") || !existsSync52(appDir)) {
|
|
39617
|
-
throw new Error(`Not a .app bundle: ${appDir}`);
|
|
39618
|
-
}
|
|
39619
|
-
const macos = join50(appDir, "Contents", "MacOS");
|
|
39620
|
-
const plist = join50(appDir, "Contents", "Info.plist");
|
|
39621
|
-
if (!existsSync52(macos) || !existsSync52(plist)) {
|
|
39622
|
-
throw new Error(`Malformed .app (missing Contents/MacOS or Info.plist): ${appDir}`);
|
|
39623
|
-
}
|
|
39624
|
-
}
|
|
39625
|
-
function readBundleVersion(appDir) {
|
|
39626
|
-
const plist = join50(appDir, "Contents", "Info.plist");
|
|
39627
|
-
try {
|
|
39628
|
-
return runCapture("plutil", ["-extract", "CFBundleShortVersionString", "raw", "-o", "-", plist]) || null;
|
|
39629
|
-
} catch {
|
|
39630
|
-
return null;
|
|
39631
|
-
}
|
|
39632
|
-
}
|
|
39633
|
-
function findAppInDir(dir) {
|
|
39634
|
-
const entries = readdirSync12(dir).filter((e) => e.endsWith(".app"));
|
|
39635
|
-
return entries.length > 0 ? join50(dir, entries[0]) : null;
|
|
39636
|
-
}
|
|
39637
|
-
function materializeAppBundle(source, workDir) {
|
|
39638
|
-
const src = resolve9(source);
|
|
39639
|
-
if (!existsSync52(src)) throw new Error(`Source not found: ${src}`);
|
|
39640
|
-
if (src.endsWith(".app")) {
|
|
39641
|
-
return src;
|
|
39642
|
-
}
|
|
39643
|
-
if (src.endsWith(".tar.gz") || src.endsWith(".tgz")) {
|
|
39644
|
-
run("tar", ["-xzf", src, "-C", workDir]);
|
|
39645
|
-
} else if (src.endsWith(".zip")) {
|
|
39646
|
-
run("ditto", ["-x", "-k", src, workDir]);
|
|
39647
|
-
} else {
|
|
39648
|
-
throw new Error(`Unsupported source (expect .app, .tar.gz, or .zip): ${src}`);
|
|
39649
|
-
}
|
|
39650
|
-
const app = findAppInDir(workDir);
|
|
39651
|
-
if (!app) throw new Error(`No .app found inside archive: ${src}`);
|
|
39652
|
-
return app;
|
|
39653
|
-
}
|
|
39654
|
-
function verifyCodesign(appDir) {
|
|
39655
|
-
try {
|
|
39656
|
-
execFileSync3("codesign", ["--verify", "--deep", appDir], { stdio: ["ignore", "ignore", "ignore"] });
|
|
39657
|
-
return true;
|
|
39658
|
-
} catch {
|
|
39659
|
-
return false;
|
|
39660
|
-
}
|
|
39661
|
-
}
|
|
39662
|
-
function isAppRunning() {
|
|
39663
|
-
try {
|
|
39664
|
-
const out = execFileSync3("pgrep", ["-f", `${APP_BUNDLE_NAME}/Contents/MacOS/`], { encoding: "utf-8" }).toString().trim();
|
|
39665
|
-
return out.length > 0;
|
|
39666
|
-
} catch {
|
|
39667
|
-
return false;
|
|
39668
|
-
}
|
|
39669
|
-
}
|
|
39670
|
-
function installAppBundle(source, opts = {}) {
|
|
39671
|
-
if (detectPlatform().os !== "darwin") {
|
|
39672
|
-
throw new Error("Desktop app install is currently macOS-only.");
|
|
39673
|
-
}
|
|
39674
|
-
const home = opts.home ?? homedir2();
|
|
39675
|
-
const installDir = opts.installDir ?? defaultInstallDir(home);
|
|
39676
|
-
mkdirSync25(installDir, { recursive: true });
|
|
39677
|
-
const workDir = mkdtempSync(join50(tmpdir(), "dc-app-"));
|
|
39678
|
-
try {
|
|
39679
|
-
const appDir = materializeAppBundle(source, workDir);
|
|
39680
|
-
validateAppBundle(appDir);
|
|
39681
|
-
const target = join50(installDir, APP_BUNDLE_NAME);
|
|
39682
|
-
const staging = join50(installDir, `.${APP_BUNDLE_NAME}.new-${process.pid}`);
|
|
39683
|
-
const backup = join50(installDir, `.${APP_BUNDLE_NAME}.old-${process.pid}`);
|
|
39684
|
-
rmSync6(staging, { recursive: true, force: true });
|
|
39685
|
-
rmSync6(backup, { recursive: true, force: true });
|
|
39686
|
-
let wasRunning;
|
|
39687
|
-
let replaced;
|
|
39688
|
-
try {
|
|
39689
|
-
run("ditto", [appDir, staging]);
|
|
39690
|
-
try {
|
|
39691
|
-
run("xattr", ["-dr", "com.apple.quarantine", staging]);
|
|
39692
|
-
} catch {
|
|
39693
|
-
}
|
|
39694
|
-
wasRunning = isAppRunning();
|
|
39695
|
-
replaced = existsSync52(target);
|
|
39696
|
-
if (replaced) renameSync8(target, backup);
|
|
39697
|
-
renameSync8(staging, target);
|
|
39698
|
-
} catch (e) {
|
|
39699
|
-
if (existsSync52(target) === false && existsSync52(backup)) {
|
|
39700
|
-
try {
|
|
39701
|
-
renameSync8(backup, target);
|
|
39702
|
-
} catch {
|
|
39703
|
-
}
|
|
39704
|
-
}
|
|
39705
|
-
rmSync6(staging, { recursive: true, force: true });
|
|
39706
|
-
throw e;
|
|
39707
|
-
}
|
|
39708
|
-
rmSync6(backup, { recursive: true, force: true });
|
|
39709
|
-
const version = readBundleVersion(target);
|
|
39710
|
-
writeAppManifest(
|
|
39711
|
-
{
|
|
39712
|
-
version: version ?? "unknown",
|
|
39713
|
-
path: target,
|
|
39714
|
-
installedAt: Date.now(),
|
|
39715
|
-
source: opts.sourceLabel ?? "local"
|
|
39716
|
-
},
|
|
39717
|
-
home
|
|
39718
|
-
);
|
|
39719
|
-
const signatureValid = verifyCodesign(target);
|
|
39720
|
-
return { version, path: target, replaced, wasRunning, signatureValid };
|
|
39721
|
-
} finally {
|
|
39722
|
-
rmSync6(workDir, { recursive: true, force: true });
|
|
39723
|
-
}
|
|
39724
|
-
}
|
|
39725
|
-
function versionFromTag(tag) {
|
|
39726
|
-
return tag.replace(/^v/, "");
|
|
39727
|
-
}
|
|
39728
|
-
async function fetchLatestRelease(repo = APP_RELEASE_REPO, fetchImpl = fetch) {
|
|
39729
|
-
try {
|
|
39730
|
-
const res = await fetchImpl(`https://api.github.com/repos/${repo}/releases/latest`, {
|
|
39731
|
-
headers: { Accept: "application/vnd.github+json", "User-Agent": "dreamcontext-cli" }
|
|
39732
|
-
});
|
|
39733
|
-
if (!res.ok) return null;
|
|
39734
|
-
const json = await res.json();
|
|
39735
|
-
if (!json || typeof json.tag_name !== "string" || !Array.isArray(json.assets)) return null;
|
|
39736
|
-
return json;
|
|
39737
|
-
} catch {
|
|
39738
|
-
return null;
|
|
39739
|
-
}
|
|
39740
|
-
}
|
|
39741
|
-
async function downloadTo(url, destFile, fetchImpl = fetch) {
|
|
39742
|
-
const res = await fetchImpl(url, { headers: { "User-Agent": "dreamcontext-cli" } });
|
|
39743
|
-
if (!res.ok) throw new Error(`Download failed (${res.status}): ${url}`);
|
|
39744
|
-
const buf = Buffer.from(await res.arrayBuffer());
|
|
39745
|
-
writeFileSync32(destFile, buf);
|
|
39746
|
-
}
|
|
39747
|
-
function sha256File(file) {
|
|
39748
|
-
return createHash2("sha256").update(readFileSync40(file)).digest("hex");
|
|
39749
|
-
}
|
|
39750
|
-
async function downloadLatestArtifact(repo = APP_RELEASE_REPO, fetchImpl = fetch) {
|
|
39751
|
-
const plat = detectPlatform();
|
|
39752
|
-
if (plat.os !== "darwin") return null;
|
|
39753
|
-
const release2 = await fetchLatestRelease(repo, fetchImpl);
|
|
39754
|
-
if (!release2) return null;
|
|
39755
|
-
const assetName = pickAssetForArch(release2.assets.map((a) => a.name), plat.arch);
|
|
39756
|
-
if (!assetName) return null;
|
|
39757
|
-
const asset = release2.assets.find((a) => a.name === assetName);
|
|
39758
|
-
const sumAsset = release2.assets.find((a) => a.name === `${assetName}.sha256`);
|
|
39759
|
-
if (!sumAsset) {
|
|
39760
|
-
throw new Error(
|
|
39761
|
-
`Release ${release2.tag_name} is missing ${assetName}.sha256 \u2014 refusing to install an unverified binary.`
|
|
39762
|
-
);
|
|
39763
|
-
}
|
|
39764
|
-
const workDir = mkdtempSync(join50(tmpdir(), "dc-app-dl-"));
|
|
39765
|
-
try {
|
|
39766
|
-
const archivePath = join50(workDir, assetName);
|
|
39767
|
-
await downloadTo(asset.browser_download_url, archivePath, fetchImpl);
|
|
39768
|
-
const sumFile = join50(workDir, `${assetName}.sha256`);
|
|
39769
|
-
await downloadTo(sumAsset.browser_download_url, sumFile, fetchImpl);
|
|
39770
|
-
const expected = readFileSync40(sumFile, "utf-8").trim().split(/\s+/)[0].toLowerCase();
|
|
39771
|
-
const actual = sha256File(archivePath).toLowerCase();
|
|
39772
|
-
if (!expected || expected !== actual) {
|
|
39773
|
-
throw new Error(`Checksum mismatch for ${assetName}: expected ${expected || "(empty)"}, got ${actual}`);
|
|
39774
|
-
}
|
|
39775
|
-
return { archivePath, version: versionFromTag(release2.tag_name) };
|
|
39776
|
-
} catch (e) {
|
|
39777
|
-
rmSync6(workDir, { recursive: true, force: true });
|
|
39778
|
-
throw e;
|
|
39779
|
-
}
|
|
39780
|
-
}
|
|
39781
|
-
function appAutoUpdateEnabled(env2 = process.env) {
|
|
39782
|
-
if (env2.DREAMCONTEXT_VERSION_CHECK === "0") return false;
|
|
39783
|
-
return env2.DREAMCONTEXT_APP_AUTO_UPDATE !== "0";
|
|
39784
|
-
}
|
|
39785
|
-
function defaultAppUpdateSpawner() {
|
|
39786
|
-
const child = spawnProcess(process.execPath, [process.argv[1], "app", "update"], {
|
|
39787
|
-
detached: true,
|
|
39788
|
-
stdio: "ignore"
|
|
39789
|
-
});
|
|
39790
|
-
child.unref();
|
|
39791
|
-
}
|
|
39792
|
-
function maybeTriggerAppUpdate(env2 = process.env, deps = {}) {
|
|
39793
|
-
try {
|
|
39794
|
-
if (detectPlatform().os !== "darwin") return false;
|
|
39795
|
-
if (!appAutoUpdateEnabled(env2)) return false;
|
|
39796
|
-
const installed = deps.manifest !== void 0 ? deps.manifest : readAppManifest();
|
|
39797
|
-
if (!installed) return false;
|
|
39798
|
-
(deps.spawner ?? defaultAppUpdateSpawner)();
|
|
39799
|
-
return true;
|
|
39800
|
-
} catch {
|
|
39801
|
-
return false;
|
|
39802
|
-
}
|
|
39803
|
-
}
|
|
39804
|
-
async function doInstall(from, dir) {
|
|
39805
|
-
const plat = detectPlatform();
|
|
39806
|
-
if (plat.os !== "darwin") {
|
|
39807
|
-
console.log(source_default.yellow("The desktop app is currently macOS-only. Windows/Linux support is planned."));
|
|
39808
|
-
return;
|
|
39809
|
-
}
|
|
39810
|
-
let tempToClean = null;
|
|
39811
|
-
let source = from;
|
|
39812
|
-
let sourceLabel = "local";
|
|
39813
|
-
if (!source) {
|
|
39814
|
-
console.log(source_default.cyan("Fetching the latest desktop app from GitHub Releases\u2026"));
|
|
39815
|
-
let dl = null;
|
|
39816
|
-
try {
|
|
39817
|
-
dl = await downloadLatestArtifact();
|
|
39818
|
-
} catch (e) {
|
|
39819
|
-
console.log(source_default.red(`Install aborted: ${e.message}`));
|
|
39820
|
-
return;
|
|
39821
|
-
}
|
|
39822
|
-
if (!dl) {
|
|
39823
|
-
console.log(
|
|
39824
|
-
source_default.yellow(
|
|
39825
|
-
"No published desktop release found yet.\nBuild one locally and install it with: dreamcontext app install --from <path-to.app|.tar.gz>"
|
|
39826
|
-
)
|
|
39827
|
-
);
|
|
39828
|
-
return;
|
|
39829
|
-
}
|
|
39830
|
-
source = dl.archivePath;
|
|
39831
|
-
sourceLabel = "github";
|
|
39832
|
-
tempToClean = dirname28(dl.archivePath);
|
|
39833
|
-
}
|
|
39834
|
-
try {
|
|
39835
|
-
const res = installAppBundle(source, { installDir: dir, sourceLabel });
|
|
39836
|
-
console.log(source_default.green(`\u2713 Installed dreamcontext-beta ${res.version ?? ""}`.trim()) + source_default.dim(` \u2192 ${res.path}`));
|
|
39837
|
-
if (res.signatureValid === false) {
|
|
39838
|
-
console.log(
|
|
39839
|
-
source_default.yellow(
|
|
39840
|
-
"Warning: the installed app failed code-signature verification. It may still launch (ad-hoc),\nbut the published artifact should be properly ad-hoc deep-signed at build time."
|
|
39841
|
-
)
|
|
39842
|
-
);
|
|
39843
|
-
}
|
|
39844
|
-
if (res.wasRunning) {
|
|
39845
|
-
console.log(source_default.yellow("The app is currently running \u2014 restart it to apply the update."));
|
|
39846
|
-
} else {
|
|
39847
|
-
console.log(source_default.dim(`Launch it: open "${res.path}"`));
|
|
39848
|
-
}
|
|
39849
|
-
} finally {
|
|
39850
|
-
if (tempToClean) rmSync6(tempToClean, { recursive: true, force: true });
|
|
39851
|
-
}
|
|
39852
|
-
}
|
|
39853
|
-
async function doUpdate(from, dir) {
|
|
39854
|
-
const installed = readAppManifest();
|
|
39855
|
-
if (!installed) {
|
|
39856
|
-
console.log(source_default.dim("No installed app recorded \u2014 running a fresh install."));
|
|
39857
|
-
await doInstall(from, dir);
|
|
39858
|
-
return;
|
|
39859
|
-
}
|
|
39860
|
-
if (from) {
|
|
39861
|
-
await doInstall(from, dir);
|
|
39862
|
-
return;
|
|
39863
|
-
}
|
|
39864
|
-
let dl = null;
|
|
39865
|
-
try {
|
|
39866
|
-
dl = await downloadLatestArtifact();
|
|
39867
|
-
} catch (e) {
|
|
39868
|
-
console.log(source_default.red(`Update aborted: ${e.message}`));
|
|
39869
|
-
return;
|
|
39870
|
-
}
|
|
39871
|
-
if (!dl) {
|
|
39872
|
-
console.log(source_default.yellow("No published desktop release available to update to."));
|
|
39873
|
-
return;
|
|
39874
|
-
}
|
|
39875
|
-
try {
|
|
39876
|
-
if (compareVersions(installed.version, dl.version) >= 0) {
|
|
39877
|
-
console.log(source_default.green(`Desktop app is up to date (${installed.version}).`));
|
|
39878
|
-
return;
|
|
39879
|
-
}
|
|
39880
|
-
const res = installAppBundle(dl.archivePath, { installDir: dir, sourceLabel: "github" });
|
|
39881
|
-
console.log(source_default.green(`\u2713 Updated dreamcontext-beta ${installed.version} \u2192 ${res.version ?? dl.version}`));
|
|
39882
|
-
if (res.wasRunning) console.log(source_default.yellow("Restart the app to apply the update."));
|
|
39883
|
-
} finally {
|
|
39884
|
-
rmSync6(dirname28(dl.archivePath), { recursive: true, force: true });
|
|
39885
|
-
}
|
|
39886
|
-
}
|
|
39887
|
-
function doStatus() {
|
|
39888
|
-
const installed = readAppManifest();
|
|
39889
|
-
if (!installed) {
|
|
39890
|
-
console.log("Desktop app: not installed (run `dreamcontext app install`).");
|
|
39891
|
-
return;
|
|
39892
|
-
}
|
|
39893
|
-
const onDisk = existsSync52(installed.path);
|
|
39894
|
-
console.log(`Desktop app: ${installed.version}`);
|
|
39895
|
-
console.log(` path: ${installed.path}${onDisk ? "" : source_default.red(" (missing!)")}`);
|
|
39896
|
-
console.log(` source: ${installed.source}`);
|
|
39897
|
-
console.log(` running: ${isAppRunning() ? "yes" : "no"}`);
|
|
39898
|
-
}
|
|
39899
|
-
function registerAppCommand(program2) {
|
|
39900
|
-
const app = program2.command("app").description("Manage the dreamcontext desktop app (install / update / status)");
|
|
39901
|
-
app.command("install").description("Install the desktop app to ~/Applications (no quarantine, no admin)").option("--from <path>", "Install from a local .app, .tar.gz, or .zip instead of GitHub Releases").option("--dir <dir>", "Install directory (default: ~/Applications)").action(async (opts) => {
|
|
39902
|
-
await doInstall(opts.from, opts.dir);
|
|
39903
|
-
});
|
|
39904
|
-
app.command("update").description("Update the installed desktop app to the latest version").option("--from <path>", "Update from a local artifact instead of GitHub Releases").option("--dir <dir>", "Install directory (default: ~/Applications)").action(async (opts) => {
|
|
39905
|
-
await doUpdate(opts.from, opts.dir);
|
|
39906
|
-
});
|
|
39907
|
-
app.command("status").description("Show the installed desktop app version and state").action(() => {
|
|
39908
|
-
doStatus();
|
|
39909
|
-
});
|
|
39910
|
-
}
|
|
39911
|
-
var APP_BUNDLE_NAME, APP_RELEASE_REPO;
|
|
39912
|
-
var init_app = __esm({
|
|
39913
|
-
"src/cli/commands/app.ts"() {
|
|
39914
|
-
"use strict";
|
|
39915
|
-
init_source();
|
|
39916
|
-
init_version_check();
|
|
39917
|
-
APP_BUNDLE_NAME = "dreamcontext-beta.app";
|
|
39918
|
-
APP_RELEASE_REPO = "meanllbrl/dreamcontext";
|
|
39919
|
-
}
|
|
39920
|
-
});
|
|
39921
|
-
|
|
39922
39970
|
// src/cli/commands/asset-drift.ts
|
|
39923
39971
|
import { mkdtempSync as mkdtempSync2, rmSync as rmSync7, existsSync as existsSync53, readFileSync as readFileSync41, readdirSync as readdirSync13 } from "fs";
|
|
39924
39972
|
import { tmpdir as tmpdir2 } from "os";
|
|
@@ -39988,7 +40036,7 @@ var init_asset_drift = __esm({
|
|
|
39988
40036
|
|
|
39989
40037
|
// src/cli/commands/hook.ts
|
|
39990
40038
|
import { readFileSync as readFileSync42, existsSync as existsSync54, statSync as statSync7 } from "fs";
|
|
39991
|
-
import { execFileSync as
|
|
40039
|
+
import { execFileSync as execFileSync5, spawn as spawn3 } from "child_process";
|
|
39992
40040
|
import { get as httpGet } from "http";
|
|
39993
40041
|
import { dirname as dirname30, resolve as resolve10, join as join52, extname as extname2, basename as basename16, relative as relative4 } from "path";
|
|
39994
40042
|
function readStdin() {
|
|
@@ -40143,13 +40191,13 @@ function runFormatter(detection, filePath) {
|
|
|
40143
40191
|
if (detection.type === "biome") {
|
|
40144
40192
|
const localBin = resolveLocalBin("biome", detection.projectRoot);
|
|
40145
40193
|
if (localBin) {
|
|
40146
|
-
|
|
40194
|
+
execFileSync5(localBin, ["format", "--write", filePath], {
|
|
40147
40195
|
cwd: detection.projectRoot,
|
|
40148
40196
|
timeout: 15e3,
|
|
40149
40197
|
stdio: ["pipe", "pipe", "pipe"]
|
|
40150
40198
|
});
|
|
40151
40199
|
} else {
|
|
40152
|
-
|
|
40200
|
+
execFileSync5("npx", ["@biomejs/biome", "format", "--write", filePath], {
|
|
40153
40201
|
cwd: detection.projectRoot,
|
|
40154
40202
|
timeout: 15e3,
|
|
40155
40203
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40158,13 +40206,13 @@ function runFormatter(detection, filePath) {
|
|
|
40158
40206
|
} else {
|
|
40159
40207
|
const localBin = resolveLocalBin("prettier", detection.projectRoot);
|
|
40160
40208
|
if (localBin) {
|
|
40161
|
-
|
|
40209
|
+
execFileSync5(localBin, ["--write", filePath], {
|
|
40162
40210
|
cwd: detection.projectRoot,
|
|
40163
40211
|
timeout: 15e3,
|
|
40164
40212
|
stdio: ["pipe", "pipe", "pipe"]
|
|
40165
40213
|
});
|
|
40166
40214
|
} else {
|
|
40167
|
-
|
|
40215
|
+
execFileSync5("npx", ["prettier", "--write", filePath], {
|
|
40168
40216
|
cwd: detection.projectRoot,
|
|
40169
40217
|
timeout: 15e3,
|
|
40170
40218
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -40184,14 +40232,14 @@ function runTscCheckWithConfig(filePath, tsconfigPath) {
|
|
|
40184
40232
|
const localBin = resolveLocalBin("tsc", projectRoot);
|
|
40185
40233
|
const args = ["--noEmit", "--pretty", "false", "--incremental"];
|
|
40186
40234
|
if (localBin) {
|
|
40187
|
-
|
|
40235
|
+
execFileSync5(localBin, args, {
|
|
40188
40236
|
cwd: projectRoot,
|
|
40189
40237
|
timeout: 3e4,
|
|
40190
40238
|
encoding: "utf-8",
|
|
40191
40239
|
stdio: ["pipe", "pipe", "pipe"]
|
|
40192
40240
|
});
|
|
40193
40241
|
} else {
|
|
40194
|
-
|
|
40242
|
+
execFileSync5("npx", ["tsc", ...args], {
|
|
40195
40243
|
cwd: projectRoot,
|
|
40196
40244
|
timeout: 3e4,
|
|
40197
40245
|
encoding: "utf-8",
|
|
@@ -57139,7 +57187,7 @@ var init_rem_sleep2 = __esm({
|
|
|
57139
57187
|
});
|
|
57140
57188
|
|
|
57141
57189
|
// src/lib/marketing/git-guard.ts
|
|
57142
|
-
import { execFileSync as
|
|
57190
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
57143
57191
|
function isBlockedMarketingPath(repoRelPath) {
|
|
57144
57192
|
if (typeof repoRelPath !== "string" || repoRelPath.length === 0) return false;
|
|
57145
57193
|
const norm2 = repoRelPath.replace(/\\/g, "/");
|
|
@@ -57153,7 +57201,7 @@ function isBlockedMarketingPath(repoRelPath) {
|
|
|
57153
57201
|
function getStagedFiles(cwd) {
|
|
57154
57202
|
let raw;
|
|
57155
57203
|
try {
|
|
57156
|
-
raw =
|
|
57204
|
+
raw = execFileSync6("git", ["diff", "--cached", "--name-only", "-z"], {
|
|
57157
57205
|
cwd,
|
|
57158
57206
|
encoding: "utf-8",
|
|
57159
57207
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -57178,11 +57226,11 @@ var init_git_guard = __esm({
|
|
|
57178
57226
|
|
|
57179
57227
|
// src/cli/commands/marketing/hooks.ts
|
|
57180
57228
|
import { existsSync as existsSync87, readFileSync as readFileSync66, writeFileSync as writeFileSync44, chmodSync as chmodSync3, mkdirSync as mkdirSync39, statSync as statSync18 } from "fs";
|
|
57181
|
-
import { execFileSync as
|
|
57229
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
57182
57230
|
import { join as join78 } from "path";
|
|
57183
57231
|
function findGitDir(cwd = process.cwd()) {
|
|
57184
57232
|
try {
|
|
57185
|
-
const out =
|
|
57233
|
+
const out = execFileSync7("git", ["rev-parse", "--git-dir"], {
|
|
57186
57234
|
cwd,
|
|
57187
57235
|
encoding: "utf-8",
|
|
57188
57236
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -57869,10 +57917,39 @@ var init_memory = __esm({
|
|
|
57869
57917
|
});
|
|
57870
57918
|
|
|
57871
57919
|
// src/cli/commands/upgrade.ts
|
|
57872
|
-
import { execFileSync as
|
|
57920
|
+
import { execFileSync as execFileSync9 } from "child_process";
|
|
57873
57921
|
import { dirname as dirname52 } from "path";
|
|
57922
|
+
import { existsSync as existsSync91 } from "fs";
|
|
57874
57923
|
function defaultInstaller(args) {
|
|
57875
|
-
|
|
57924
|
+
execFileSync9("npm", args, { stdio: "inherit" });
|
|
57925
|
+
}
|
|
57926
|
+
function defaultProjectUpdater(vault) {
|
|
57927
|
+
if (!existsSync91(vault.path)) {
|
|
57928
|
+
return { vault, ok: false, error: "project folder no longer exists" };
|
|
57929
|
+
}
|
|
57930
|
+
try {
|
|
57931
|
+
execFileSync9("npx", ["dreamcontext", "update", "--yes"], {
|
|
57932
|
+
cwd: vault.path,
|
|
57933
|
+
stdio: "inherit"
|
|
57934
|
+
});
|
|
57935
|
+
return { vault, ok: true };
|
|
57936
|
+
} catch (e) {
|
|
57937
|
+
return { vault, ok: false, error: e.message };
|
|
57938
|
+
}
|
|
57939
|
+
}
|
|
57940
|
+
async function defaultConfirmAll(count) {
|
|
57941
|
+
return esm_default4({
|
|
57942
|
+
message: `Also refresh ${count} registered dreamcontext project(s) to the new version?`,
|
|
57943
|
+
default: true
|
|
57944
|
+
});
|
|
57945
|
+
}
|
|
57946
|
+
function defaultAppUpdater() {
|
|
57947
|
+
try {
|
|
57948
|
+
execFileSync9("npx", ["dreamcontext", "app", "update"], { stdio: "inherit" });
|
|
57949
|
+
return { ok: true };
|
|
57950
|
+
} catch (e) {
|
|
57951
|
+
return { ok: false, error: e.message };
|
|
57952
|
+
}
|
|
57876
57953
|
}
|
|
57877
57954
|
function projectRootForCache() {
|
|
57878
57955
|
const contextDir = resolveContextRoot();
|
|
@@ -57881,7 +57958,7 @@ function projectRootForCache() {
|
|
|
57881
57958
|
function defaultLiveLatest() {
|
|
57882
57959
|
let latest = null;
|
|
57883
57960
|
try {
|
|
57884
|
-
const raw =
|
|
57961
|
+
const raw = execFileSync9("npm", ["view", "dreamcontext", "version"], {
|
|
57885
57962
|
timeout: 5e3,
|
|
57886
57963
|
encoding: "utf-8"
|
|
57887
57964
|
});
|
|
@@ -57905,7 +57982,62 @@ function defaultLiveLatest() {
|
|
|
57905
57982
|
}
|
|
57906
57983
|
return latest;
|
|
57907
57984
|
}
|
|
57908
|
-
function
|
|
57985
|
+
async function maybeUpdateApp(opts) {
|
|
57986
|
+
const installed = (opts?.appInstalledCheck ?? (() => readAppManifest() !== null))();
|
|
57987
|
+
if (!installed) return;
|
|
57988
|
+
const auto = opts?.yes === true;
|
|
57989
|
+
const interactive = process.stdin.isTTY === true;
|
|
57990
|
+
if (!auto && !interactive) {
|
|
57991
|
+
console.log(
|
|
57992
|
+
source_default.dim(
|
|
57993
|
+
"Tip: the desktop app is installed \u2014 run `dreamcontext upgrade --yes` (or `dreamcontext app update`) to update it too."
|
|
57994
|
+
)
|
|
57995
|
+
);
|
|
57996
|
+
return;
|
|
57997
|
+
}
|
|
57998
|
+
console.log(source_default.cyan("\n\u21BB Updating the desktop app\u2026"));
|
|
57999
|
+
const result = (opts?.appUpdater ?? defaultAppUpdater)();
|
|
58000
|
+
if (result.ok) console.log(source_default.green("\u2713 Desktop app updated."));
|
|
58001
|
+
else console.log(source_default.yellow(` \u26A0 Desktop app update skipped: ${result.error ?? "failed"}`));
|
|
58002
|
+
}
|
|
58003
|
+
async function maybeUpdateAllProjects(opts) {
|
|
58004
|
+
const vaults = (opts?.vaultLister ?? (() => listVaults()))();
|
|
58005
|
+
if (vaults.length === 0) return;
|
|
58006
|
+
const auto = opts?.yes === true;
|
|
58007
|
+
const canPrompt = process.stdin.isTTY === true || opts?.confirmAll !== void 0;
|
|
58008
|
+
if (!auto && !canPrompt) {
|
|
58009
|
+
console.log(
|
|
58010
|
+
source_default.dim(
|
|
58011
|
+
`Tip: ${vaults.length} registered project(s) were not refreshed. Run \`dreamcontext upgrade --yes\` to refresh them all, or \`dreamcontext update\` in each.`
|
|
58012
|
+
)
|
|
58013
|
+
);
|
|
58014
|
+
return;
|
|
58015
|
+
}
|
|
58016
|
+
let proceed = auto;
|
|
58017
|
+
if (!proceed) {
|
|
58018
|
+
const confirmFn = opts?.confirmAll ?? defaultConfirmAll;
|
|
58019
|
+
proceed = await confirmFn(vaults.length);
|
|
58020
|
+
}
|
|
58021
|
+
if (!proceed) {
|
|
58022
|
+
console.log(source_default.dim("Skipped refreshing other projects. Run `dreamcontext update` in any project later."));
|
|
58023
|
+
return;
|
|
58024
|
+
}
|
|
58025
|
+
const updater = opts?.projectUpdater ?? defaultProjectUpdater;
|
|
58026
|
+
const results = [];
|
|
58027
|
+
for (const vault of vaults) {
|
|
58028
|
+
console.log(source_default.cyan(`
|
|
58029
|
+
\u21BB Refreshing ${source_default.bold(vault.name)} (${vault.path})...`));
|
|
58030
|
+
results.push(updater(vault));
|
|
58031
|
+
}
|
|
58032
|
+
const ok = results.filter((r) => r.ok);
|
|
58033
|
+
const failed = results.filter((r) => !r.ok);
|
|
58034
|
+
console.log("");
|
|
58035
|
+
console.log(source_default.green(`\u2713 Refreshed ${ok.length}/${results.length} project(s).`));
|
|
58036
|
+
for (const f of failed) {
|
|
58037
|
+
console.log(source_default.yellow(` \u26A0 ${f.vault.name}: ${f.error ?? "update failed"}`));
|
|
58038
|
+
}
|
|
58039
|
+
}
|
|
58040
|
+
async function runUpgrade(check2, opts) {
|
|
57909
58041
|
const installer = opts?.installer ?? defaultInstaller;
|
|
57910
58042
|
if (check2) {
|
|
57911
58043
|
const current = dreamcontextVersion();
|
|
@@ -57921,20 +58053,26 @@ function runUpgrade(check2, opts) {
|
|
|
57921
58053
|
console.log(source_default.cyan("Installing dreamcontext@latest via npm..."));
|
|
57922
58054
|
installer(["install", "-g", "dreamcontext@latest"]);
|
|
57923
58055
|
console.log("");
|
|
57924
|
-
console.log(source_default.green("CLI upgraded.
|
|
58056
|
+
console.log(source_default.green("CLI upgraded."));
|
|
58057
|
+
await maybeUpdateApp(opts);
|
|
58058
|
+
await maybeUpdateAllProjects(opts);
|
|
58059
|
+
console.log(source_default.dim("\nIn each project, the new files take effect next session (hooks re-read them)."));
|
|
57925
58060
|
}
|
|
57926
58061
|
function registerUpgradeCommand(program2) {
|
|
57927
|
-
program2.command("upgrade").description("Upgrade the dreamcontext CLI
|
|
57928
|
-
runUpgrade(Boolean(options2.check), opts);
|
|
58062
|
+
program2.command("upgrade").description("Upgrade the dreamcontext CLI, then offer to refresh every registered project to match").option("--check", "Print current vs latest version and exit without installing").option("-y, --yes", "Refresh every registered project without prompting (non-interactive)").action(async (options2, _cmd, opts) => {
|
|
58063
|
+
await runUpgrade(Boolean(options2.check), { ...opts, yes: options2.yes });
|
|
57929
58064
|
});
|
|
57930
58065
|
}
|
|
57931
58066
|
var init_upgrade = __esm({
|
|
57932
58067
|
"src/cli/commands/upgrade.ts"() {
|
|
57933
58068
|
"use strict";
|
|
57934
58069
|
init_source();
|
|
58070
|
+
init_esm16();
|
|
57935
58071
|
init_manifest();
|
|
57936
58072
|
init_version_check();
|
|
57937
58073
|
init_context_path();
|
|
58074
|
+
init_vaults();
|
|
58075
|
+
init_app();
|
|
57938
58076
|
}
|
|
57939
58077
|
});
|
|
57940
58078
|
|
|
@@ -58502,7 +58640,7 @@ var init_people = __esm({
|
|
|
58502
58640
|
|
|
58503
58641
|
// src/cli/commands/config.ts
|
|
58504
58642
|
import { dirname as dirname54 } from "path";
|
|
58505
|
-
import { existsSync as
|
|
58643
|
+
import { existsSync as existsSync92, readFileSync as readFileSync69, writeFileSync as writeFileSync46 } from "fs";
|
|
58506
58644
|
import { join as join82 } from "path";
|
|
58507
58645
|
function resolveProjectRoot() {
|
|
58508
58646
|
const contextRoot = resolveContextRoot();
|
|
@@ -58764,7 +58902,7 @@ function registerConfigCommand(program2) {
|
|
|
58764
58902
|
let userMdSynced = false;
|
|
58765
58903
|
if (contextRoot) {
|
|
58766
58904
|
const userMdPath = join82(contextRoot, "core", "1.user.md");
|
|
58767
|
-
if (
|
|
58905
|
+
if (existsSync92(userMdPath)) {
|
|
58768
58906
|
try {
|
|
58769
58907
|
const before = readFileSync69(userMdPath, "utf-8");
|
|
58770
58908
|
const after = ensurePeopleSection(before, roster);
|
|
@@ -58911,7 +59049,7 @@ var init_config4 = __esm({
|
|
|
58911
59049
|
});
|
|
58912
59050
|
|
|
58913
59051
|
// src/lib/feedback.ts
|
|
58914
|
-
import { execFileSync as
|
|
59052
|
+
import { execFileSync as execFileSync10 } from "child_process";
|
|
58915
59053
|
import { platform, release, arch } from "os";
|
|
58916
59054
|
function isFeedbackCategory(value) {
|
|
58917
59055
|
return Object.prototype.hasOwnProperty.call(CATEGORY_META, value);
|
|
@@ -59068,7 +59206,7 @@ var init_feedback = __esm({
|
|
|
59068
59206
|
FEEDBACK_CATEGORIES = Object.keys(CATEGORY_META);
|
|
59069
59207
|
defaultRunner = (cmd, args) => {
|
|
59070
59208
|
try {
|
|
59071
|
-
const stdout =
|
|
59209
|
+
const stdout = execFileSync10(cmd, args, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
59072
59210
|
return { ok: true, stdout, stderr: "" };
|
|
59073
59211
|
} catch (err) {
|
|
59074
59212
|
const e = err;
|