@titan-design/active-work 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aw.js +1 -1
- package/dist/{chunk-RLSQSE7I.js → chunk-KAR6NOS2.js} +306 -50
- package/dist/chunk-KAR6NOS2.js.map +1 -0
- package/dist/cli.js +155 -281
- package/dist/cli.js.map +1 -1
- package/docs/cli-reference.md +4 -0
- package/package.json +1 -1
- package/dist/chunk-RLSQSE7I.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
NotFoundError,
|
|
14
14
|
NoteFrontmatterSchema,
|
|
15
15
|
NoteKindSchema,
|
|
16
|
+
SCHEMA_VERSION,
|
|
16
17
|
SessionFrontmatterSchema,
|
|
17
18
|
SessionIdSchema,
|
|
18
19
|
SessionResolveSchema,
|
|
@@ -21,11 +22,13 @@ import {
|
|
|
21
22
|
TaskSeqSchema,
|
|
22
23
|
UsageError,
|
|
23
24
|
ValidationError,
|
|
25
|
+
WORKSPACE_SPAN_SOURCE_BASE,
|
|
24
26
|
WorktreeEntrySchema,
|
|
25
27
|
assembleBootstrap,
|
|
26
28
|
atomicWrite,
|
|
27
29
|
coerceDates,
|
|
28
30
|
color,
|
|
31
|
+
defaultGraphPath,
|
|
29
32
|
defineCommand,
|
|
30
33
|
deriveOpenLoops,
|
|
31
34
|
deriveOpenLoopsFrom,
|
|
@@ -48,6 +51,8 @@ import {
|
|
|
48
51
|
loadNotesFromDir,
|
|
49
52
|
loadSessionsFromDir,
|
|
50
53
|
nowIso,
|
|
54
|
+
openGraph,
|
|
55
|
+
openGraphReadOnly,
|
|
51
56
|
open_default,
|
|
52
57
|
probeHealth,
|
|
53
58
|
readArtifactHashes,
|
|
@@ -76,7 +81,7 @@ import {
|
|
|
76
81
|
writeFrontmatter,
|
|
77
82
|
writeNoteFile,
|
|
78
83
|
writeYaml
|
|
79
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-KAR6NOS2.js";
|
|
80
85
|
|
|
81
86
|
// src/cli.ts
|
|
82
87
|
import { Command, CommanderError } from "commander";
|
|
@@ -1517,8 +1522,8 @@ var NO_UPSTREAM = { ahead: null, behind: null };
|
|
|
1517
1522
|
function shortBranch(ref) {
|
|
1518
1523
|
return ref.replace(/^refs\/heads\//, "");
|
|
1519
1524
|
}
|
|
1520
|
-
function emptyWorktree(
|
|
1521
|
-
return { path:
|
|
1525
|
+
function emptyWorktree(path67) {
|
|
1526
|
+
return { path: path67, head: null, branch: null, detached: false, bare: false };
|
|
1522
1527
|
}
|
|
1523
1528
|
function parseWorktreePorcelain(stdout) {
|
|
1524
1529
|
const out = [];
|
|
@@ -3855,144 +3860,6 @@ import { z as z33 } from "zod";
|
|
|
3855
3860
|
// src/search/index.ts
|
|
3856
3861
|
import { createRetrievalEngine, ftsRetriever } from "@titan-design/retrieval";
|
|
3857
3862
|
|
|
3858
|
-
// src/session-index/graph.ts
|
|
3859
|
-
import Database from "better-sqlite3";
|
|
3860
|
-
import { openSessionGraph } from "@titan-design/session-graph";
|
|
3861
|
-
import { runMigrations, WatermarkTable } from "@titan-design/store-sqlite";
|
|
3862
|
-
import path34 from "path";
|
|
3863
|
-
|
|
3864
|
-
// src/workspace-index/schema.ts
|
|
3865
|
-
import { kitDdl } from "@titan-design/store-sqlite";
|
|
3866
|
-
import { MIGRATIONS as SESSION_GRAPH_MIGRATIONS } from "@titan-design/session-graph";
|
|
3867
|
-
var WORKSPACE_KIT = {
|
|
3868
|
-
watermark: "workspace_file",
|
|
3869
|
-
edge: "edge",
|
|
3870
|
-
spanFts: "search"
|
|
3871
|
-
};
|
|
3872
|
-
var WORKSPACE_SPAN_SOURCE_BASE = 1e9;
|
|
3873
|
-
var DOMAIN_DDL = `
|
|
3874
|
-
CREATE TABLE IF NOT EXISTS initiative (
|
|
3875
|
-
path TEXT PRIMARY KEY,
|
|
3876
|
-
initiative_ref TEXT NOT NULL UNIQUE,
|
|
3877
|
-
slug TEXT NOT NULL,
|
|
3878
|
-
title TEXT,
|
|
3879
|
-
state TEXT,
|
|
3880
|
-
rank INTEGER,
|
|
3881
|
-
ship_target TEXT,
|
|
3882
|
-
owner TEXT,
|
|
3883
|
-
task_prefix TEXT,
|
|
3884
|
-
updated TEXT
|
|
3885
|
-
);
|
|
3886
|
-
|
|
3887
|
-
CREATE TABLE IF NOT EXISTS note (
|
|
3888
|
-
path TEXT PRIMARY KEY,
|
|
3889
|
-
note_ref TEXT NOT NULL UNIQUE,
|
|
3890
|
-
initiative TEXT NOT NULL,
|
|
3891
|
-
filename TEXT NOT NULL,
|
|
3892
|
-
kind TEXT NOT NULL,
|
|
3893
|
-
title TEXT NOT NULL,
|
|
3894
|
-
created TEXT,
|
|
3895
|
-
tags TEXT,
|
|
3896
|
-
hits INTEGER NOT NULL DEFAULT 0,
|
|
3897
|
-
promoted_at TEXT
|
|
3898
|
-
);
|
|
3899
|
-
CREATE INDEX IF NOT EXISTS idx_note_initiative ON note(initiative);
|
|
3900
|
-
|
|
3901
|
-
CREATE TABLE IF NOT EXISTS workspace_task (
|
|
3902
|
-
path TEXT PRIMARY KEY,
|
|
3903
|
-
task_ref TEXT NOT NULL,
|
|
3904
|
-
initiative TEXT NOT NULL,
|
|
3905
|
-
task_id TEXT NOT NULL,
|
|
3906
|
-
title TEXT NOT NULL,
|
|
3907
|
-
status TEXT NOT NULL,
|
|
3908
|
-
priority INTEGER,
|
|
3909
|
-
severity TEXT,
|
|
3910
|
-
estimate REAL,
|
|
3911
|
-
tags TEXT,
|
|
3912
|
-
created TEXT,
|
|
3913
|
-
updated TEXT,
|
|
3914
|
-
done_at TEXT
|
|
3915
|
-
);
|
|
3916
|
-
CREATE INDEX IF NOT EXISTS idx_workspace_task_ref ON workspace_task(task_ref);
|
|
3917
|
-
|
|
3918
|
-
CREATE TABLE IF NOT EXISTS session_record (
|
|
3919
|
-
path TEXT PRIMARY KEY,
|
|
3920
|
-
session_ref TEXT NOT NULL,
|
|
3921
|
-
initiative TEXT NOT NULL,
|
|
3922
|
-
session_id TEXT NOT NULL,
|
|
3923
|
-
started TEXT,
|
|
3924
|
-
ended TEXT,
|
|
3925
|
-
track TEXT,
|
|
3926
|
-
parent_session_id TEXT
|
|
3927
|
-
);
|
|
3928
|
-
CREATE INDEX IF NOT EXISTS idx_session_record_ref ON session_record(session_ref);
|
|
3929
|
-
|
|
3930
|
-
CREATE TABLE IF NOT EXISTS source (
|
|
3931
|
-
path TEXT PRIMARY KEY,
|
|
3932
|
-
source_ref TEXT NOT NULL UNIQUE,
|
|
3933
|
-
initiative TEXT NOT NULL,
|
|
3934
|
-
title TEXT,
|
|
3935
|
-
kind TEXT,
|
|
3936
|
-
added TEXT
|
|
3937
|
-
);
|
|
3938
|
-
`;
|
|
3939
|
-
function nextVersion(chain) {
|
|
3940
|
-
return (chain[chain.length - 1]?.version ?? 0) + 1;
|
|
3941
|
-
}
|
|
3942
|
-
var SPAN_SOURCE_INDEX = `
|
|
3943
|
-
CREATE INDEX IF NOT EXISTS idx_search_span_source ON search_span(source_id);
|
|
3944
|
-
`;
|
|
3945
|
-
var WORKSPACE_MIGRATIONS = [
|
|
3946
|
-
{
|
|
3947
|
-
version: nextVersion(SESSION_GRAPH_MIGRATIONS),
|
|
3948
|
-
name: "workspace index tables",
|
|
3949
|
-
up: (db) => {
|
|
3950
|
-
db.exec(kitDdl({ watermark: WORKSPACE_KIT.watermark }));
|
|
3951
|
-
db.exec(DOMAIN_DDL);
|
|
3952
|
-
db.exec(SPAN_SOURCE_INDEX);
|
|
3953
|
-
}
|
|
3954
|
-
}
|
|
3955
|
-
];
|
|
3956
|
-
var PRESERVE_DDL = `
|
|
3957
|
-
CREATE TABLE IF NOT EXISTS preserved_row (
|
|
3958
|
-
table_name TEXT NOT NULL,
|
|
3959
|
-
identity TEXT NOT NULL,
|
|
3960
|
-
row_key TEXT NOT NULL,
|
|
3961
|
-
payload TEXT NOT NULL,
|
|
3962
|
-
origin TEXT NOT NULL,
|
|
3963
|
-
mode TEXT NOT NULL DEFAULT 'insert',
|
|
3964
|
-
preserved_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
|
|
3965
|
-
PRIMARY KEY (table_name, row_key)
|
|
3966
|
-
);
|
|
3967
|
-
`;
|
|
3968
|
-
var PRESERVE_MIGRATION = {
|
|
3969
|
-
version: nextVersion([...SESSION_GRAPH_MIGRATIONS, ...WORKSPACE_MIGRATIONS]),
|
|
3970
|
-
name: "preserved rows",
|
|
3971
|
-
up: (db) => db.exec(PRESERVE_DDL)
|
|
3972
|
-
};
|
|
3973
|
-
var MIGRATIONS = [
|
|
3974
|
-
...SESSION_GRAPH_MIGRATIONS,
|
|
3975
|
-
...WORKSPACE_MIGRATIONS,
|
|
3976
|
-
PRESERVE_MIGRATION
|
|
3977
|
-
];
|
|
3978
|
-
|
|
3979
|
-
// src/session-index/graph.ts
|
|
3980
|
-
var SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
|
|
3981
|
-
function defaultGraphPath() {
|
|
3982
|
-
return path34.join(getMinerRoot(), "graph.sqlite3");
|
|
3983
|
-
}
|
|
3984
|
-
function openGraph(dbPath = defaultGraphPath()) {
|
|
3985
|
-
const graph = openSessionGraph(dbPath);
|
|
3986
|
-
runMigrations(graph.db, MIGRATIONS);
|
|
3987
|
-
return {
|
|
3988
|
-
...graph,
|
|
3989
|
-
workspaceFiles: new WatermarkTable(graph.db, { name: WORKSPACE_KIT.watermark })
|
|
3990
|
-
};
|
|
3991
|
-
}
|
|
3992
|
-
function openGraphReadOnly(dbPath = defaultGraphPath()) {
|
|
3993
|
-
return new Database(dbPath, { readonly: true });
|
|
3994
|
-
}
|
|
3995
|
-
|
|
3996
3863
|
// src/search/classes.ts
|
|
3997
3864
|
var TRANSCRIPT_FIELDS = ["prompt", "assistant_response", "tool_input", "tool_result"];
|
|
3998
3865
|
var SEARCH_CLASSES = [
|
|
@@ -4028,11 +3895,11 @@ function classOf(ref, field) {
|
|
|
4028
3895
|
}
|
|
4029
3896
|
|
|
4030
3897
|
// src/search/resolve.ts
|
|
4031
|
-
import
|
|
3898
|
+
import path35 from "path";
|
|
4032
3899
|
import { readLocatorText } from "@titan-design/locator";
|
|
4033
3900
|
|
|
4034
3901
|
// src/workspace-index/refs.ts
|
|
4035
|
-
import
|
|
3902
|
+
import path34 from "path";
|
|
4036
3903
|
import { refKind } from "@titan-design/store-sqlite";
|
|
4037
3904
|
var initiativeRef = refKind("initiative");
|
|
4038
3905
|
var noteRef = refKind("note");
|
|
@@ -4040,10 +3907,10 @@ var taskRef = refKind("task");
|
|
|
4040
3907
|
var sessionRef = refKind("session");
|
|
4041
3908
|
var sourceRef = refKind("source");
|
|
4042
3909
|
function toRelative(activeRoot, absolutePath) {
|
|
4043
|
-
return
|
|
3910
|
+
return path34.relative(activeRoot, absolutePath).split(path34.sep).join("/");
|
|
4044
3911
|
}
|
|
4045
3912
|
function toAbsolute(activeRoot, relativePath) {
|
|
4046
|
-
return
|
|
3913
|
+
return path34.join(activeRoot, ...relativePath.split("/"));
|
|
4047
3914
|
}
|
|
4048
3915
|
|
|
4049
3916
|
// src/search/resolve.ts
|
|
@@ -4071,7 +3938,7 @@ function fileForSource(graph, sourceId, activeRoot) {
|
|
|
4071
3938
|
}
|
|
4072
3939
|
const row = graph.db.prepare("SELECT source_key FROM transcript WHERE source_id = ?").get(sourceId);
|
|
4073
3940
|
if (!row) return null;
|
|
4074
|
-
return row.source_key.startsWith("~") ?
|
|
3941
|
+
return row.source_key.startsWith("~") ? path35.join(process.env.HOME ?? "", row.source_key.slice(1)) : row.source_key;
|
|
4075
3942
|
}
|
|
4076
3943
|
function oneLine(text, width) {
|
|
4077
3944
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
@@ -4304,7 +4171,7 @@ var list_default = defineCommand({
|
|
|
4304
4171
|
});
|
|
4305
4172
|
|
|
4306
4173
|
// src/commands/worktree-set.ts
|
|
4307
|
-
import
|
|
4174
|
+
import path36 from "path";
|
|
4308
4175
|
import { z as z35 } from "zod";
|
|
4309
4176
|
var argsSchema3 = z35.object({
|
|
4310
4177
|
slug: z35.string().min(1),
|
|
@@ -4321,7 +4188,7 @@ var resultSchema3 = z35.object({
|
|
|
4321
4188
|
promoted: z35.boolean()
|
|
4322
4189
|
});
|
|
4323
4190
|
var DEFAULT_LABEL = "main";
|
|
4324
|
-
var samePath = (a, b) =>
|
|
4191
|
+
var samePath = (a, b) => path36.resolve(expandTilde(a)) === path36.resolve(expandTilde(b));
|
|
4325
4192
|
var worktree_set_default = defineCommand({
|
|
4326
4193
|
name: "worktree.set",
|
|
4327
4194
|
description: "Add or update a registered worktree on an existing initiative. A lone worktree is made default automatically; use --default to promote an added one. Registered worktrees live in artifacts.yml alongside the ones wrap sweeps, and are what `aw` resolves a cwd against.",
|
|
@@ -4343,8 +4210,8 @@ var worktree_set_default = defineCommand({
|
|
|
4343
4210
|
},
|
|
4344
4211
|
async run(args) {
|
|
4345
4212
|
const label = args.label ?? DEFAULT_LABEL;
|
|
4346
|
-
const initiativeDir =
|
|
4347
|
-
const briefPath =
|
|
4213
|
+
const initiativeDir = path36.join(getActiveRoot(), args.slug);
|
|
4214
|
+
const briefPath = path36.join(initiativeDir, "brief.md");
|
|
4348
4215
|
return withFileLock(getLockPath(args.slug), async () => {
|
|
4349
4216
|
let frontmatter2;
|
|
4350
4217
|
let body;
|
|
@@ -4398,7 +4265,7 @@ var worktree_set_default = defineCommand({
|
|
|
4398
4265
|
});
|
|
4399
4266
|
|
|
4400
4267
|
// src/commands/worktree-set-default.ts
|
|
4401
|
-
import
|
|
4268
|
+
import path37 from "path";
|
|
4402
4269
|
import { z as z36 } from "zod";
|
|
4403
4270
|
var argsSchema4 = z36.object({
|
|
4404
4271
|
slug: z36.string().min(1),
|
|
@@ -4417,8 +4284,8 @@ var worktree_set_default_default = defineCommand({
|
|
|
4417
4284
|
positional: ["slug", "label"]
|
|
4418
4285
|
},
|
|
4419
4286
|
async run({ slug, label }) {
|
|
4420
|
-
const initiativeDir =
|
|
4421
|
-
const briefPath =
|
|
4287
|
+
const initiativeDir = path37.join(getActiveRoot(), slug);
|
|
4288
|
+
const briefPath = path37.join(initiativeDir, "brief.md");
|
|
4422
4289
|
return withFileLock(getLockPath(slug), async () => {
|
|
4423
4290
|
let frontmatter2;
|
|
4424
4291
|
let body;
|
|
@@ -4453,7 +4320,7 @@ import { z as z37 } from "zod";
|
|
|
4453
4320
|
|
|
4454
4321
|
// src/discover/index.ts
|
|
4455
4322
|
import { promises as fs29 } from "fs";
|
|
4456
|
-
import
|
|
4323
|
+
import path41 from "path";
|
|
4457
4324
|
|
|
4458
4325
|
// src/discover/run-command.ts
|
|
4459
4326
|
import { spawn } from "child_process";
|
|
@@ -4550,13 +4417,13 @@ async function discoverGitHub(repos, run = runCommand) {
|
|
|
4550
4417
|
}
|
|
4551
4418
|
|
|
4552
4419
|
// src/discover/git.ts
|
|
4553
|
-
import
|
|
4420
|
+
import path38 from "path";
|
|
4554
4421
|
var BRANCH_LIMIT = 20;
|
|
4555
4422
|
async function discoverGit(repoPaths, run = runCommand) {
|
|
4556
4423
|
const hits = [];
|
|
4557
4424
|
const errors = [];
|
|
4558
4425
|
for (const repoPath of repoPaths) {
|
|
4559
|
-
const repoName =
|
|
4426
|
+
const repoName = path38.basename(repoPath);
|
|
4560
4427
|
await collectBranches(repoPath, repoName, hits, errors, run);
|
|
4561
4428
|
await collectWorktrees(repoPath, repoName, hits, errors, run);
|
|
4562
4429
|
await collectStashes(repoPath, repoName, hits, errors, run);
|
|
@@ -4671,14 +4538,14 @@ function errStr(err) {
|
|
|
4671
4538
|
|
|
4672
4539
|
// src/discover/projects.ts
|
|
4673
4540
|
import { promises as fs27 } from "fs";
|
|
4674
|
-
import
|
|
4541
|
+
import path39 from "path";
|
|
4675
4542
|
var MS_PER_DAY = 24 * 60 * 60 * 1e3;
|
|
4676
4543
|
var RECENT_THRESHOLD_DAYS = 30;
|
|
4677
4544
|
async function discoverProjects(projectsRoot) {
|
|
4678
4545
|
const hits = [];
|
|
4679
4546
|
const errors = [];
|
|
4680
4547
|
if (!projectsRoot) return { hits, errors };
|
|
4681
|
-
const resolved =
|
|
4548
|
+
const resolved = path39.resolve(expandTilde(projectsRoot));
|
|
4682
4549
|
let entries;
|
|
4683
4550
|
try {
|
|
4684
4551
|
entries = await fs27.readdir(resolved, { withFileTypes: true });
|
|
@@ -4694,7 +4561,7 @@ async function discoverProjects(projectsRoot) {
|
|
|
4694
4561
|
if (!entry.isDirectory()) continue;
|
|
4695
4562
|
if (entry.name.startsWith(".")) continue;
|
|
4696
4563
|
if (entry.name === "active") continue;
|
|
4697
|
-
const fullPath =
|
|
4564
|
+
const fullPath = path39.join(resolved, entry.name);
|
|
4698
4565
|
let mtimeMs = 0;
|
|
4699
4566
|
try {
|
|
4700
4567
|
const stat = await fs27.stat(fullPath);
|
|
@@ -4727,11 +4594,11 @@ async function discoverProjects(projectsRoot) {
|
|
|
4727
4594
|
// src/discover/claude.ts
|
|
4728
4595
|
import { promises as fs28 } from "fs";
|
|
4729
4596
|
import os2 from "os";
|
|
4730
|
-
import
|
|
4597
|
+
import path40 from "path";
|
|
4731
4598
|
var MAX_SCAN_LINES = 200;
|
|
4732
4599
|
var COMPACTION_SUBJECT_PREFIX = "[compaction] ";
|
|
4733
4600
|
async function discoverClaudeSessions() {
|
|
4734
|
-
const root = process.env.CLAUDE_PROJECTS_ROOT ??
|
|
4601
|
+
const root = process.env.CLAUDE_PROJECTS_ROOT ?? path40.join(os2.homedir(), ".claude", "projects");
|
|
4735
4602
|
const hits = [];
|
|
4736
4603
|
const errors = [];
|
|
4737
4604
|
let projectDirs;
|
|
@@ -4746,7 +4613,7 @@ async function discoverClaudeSessions() {
|
|
|
4746
4613
|
const byCwd = /* @__PURE__ */ new Map();
|
|
4747
4614
|
for (const dir of projectDirs) {
|
|
4748
4615
|
if (!dir.isDirectory()) continue;
|
|
4749
|
-
const dirPath =
|
|
4616
|
+
const dirPath = path40.join(root, dir.name);
|
|
4750
4617
|
let files;
|
|
4751
4618
|
try {
|
|
4752
4619
|
files = await fs28.readdir(dirPath, { withFileTypes: true });
|
|
@@ -4759,7 +4626,7 @@ async function discoverClaudeSessions() {
|
|
|
4759
4626
|
}
|
|
4760
4627
|
for (const file of files) {
|
|
4761
4628
|
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
4762
|
-
const filePath =
|
|
4629
|
+
const filePath = path40.join(dirPath, file.name);
|
|
4763
4630
|
try {
|
|
4764
4631
|
await aggregateSession(filePath, byCwd);
|
|
4765
4632
|
} catch (err) {
|
|
@@ -4815,7 +4682,7 @@ async function aggregateSession(filePath, byCwd) {
|
|
|
4815
4682
|
}
|
|
4816
4683
|
if (!cwd) return;
|
|
4817
4684
|
const subject = lastCompactionSummary ? `${COMPACTION_SUBJECT_PREFIX}${truncate2(lastCompactionSummary, 120)}` : firstUserMessage ? truncate2(firstUserMessage, 120) : "";
|
|
4818
|
-
const sessionId =
|
|
4685
|
+
const sessionId = path40.basename(filePath, ".jsonl");
|
|
4819
4686
|
const existing = byCwd.get(cwd);
|
|
4820
4687
|
if (!existing) {
|
|
4821
4688
|
byCwd.set(cwd, {
|
|
@@ -4915,7 +4782,7 @@ async function loadSlugs(activeRoot) {
|
|
|
4915
4782
|
}
|
|
4916
4783
|
}
|
|
4917
4784
|
async function loadTriagedRefs(activeRoot) {
|
|
4918
|
-
const logPath =
|
|
4785
|
+
const logPath = path41.join(activeRoot, ".triaged.log");
|
|
4919
4786
|
const refs = /* @__PURE__ */ new Set();
|
|
4920
4787
|
try {
|
|
4921
4788
|
const raw = await fs29.readFile(logPath, "utf8");
|
|
@@ -4993,11 +4860,11 @@ import { z as z38 } from "zod";
|
|
|
4993
4860
|
|
|
4994
4861
|
// src/discover/triaged-log.ts
|
|
4995
4862
|
import { promises as fs30 } from "fs";
|
|
4996
|
-
import
|
|
4863
|
+
import path42 from "path";
|
|
4997
4864
|
async function appendTriagedLog(action, ref, extra) {
|
|
4998
4865
|
const root = getActiveRoot();
|
|
4999
4866
|
await fs30.mkdir(root, { recursive: true });
|
|
5000
|
-
const logPath =
|
|
4867
|
+
const logPath = path42.join(root, ".triaged.log");
|
|
5001
4868
|
let existing = "";
|
|
5002
4869
|
try {
|
|
5003
4870
|
existing = await fs30.readFile(logPath, "utf8");
|
|
@@ -5039,7 +4906,7 @@ var drop_default = defineCommand({
|
|
|
5039
4906
|
|
|
5040
4907
|
// src/commands/fold.ts
|
|
5041
4908
|
import { promises as fs31 } from "fs";
|
|
5042
|
-
import
|
|
4909
|
+
import path43 from "path";
|
|
5043
4910
|
import { z as z39 } from "zod";
|
|
5044
4911
|
var ArgsSchema35 = z39.object({
|
|
5045
4912
|
ref: z39.string().min(1),
|
|
@@ -5081,7 +4948,7 @@ var fold_default = defineCommand({
|
|
|
5081
4948
|
if (err instanceof NotFoundError) throw err;
|
|
5082
4949
|
throw new NotFoundError(`Initiative not found: ${args.into}`);
|
|
5083
4950
|
}
|
|
5084
|
-
const sessionsDir =
|
|
4951
|
+
const sessionsDir = path43.join(initiativeDir, "sessions");
|
|
5085
4952
|
await fs31.mkdir(sessionsDir, { recursive: true });
|
|
5086
4953
|
const startedIso = nowIso();
|
|
5087
4954
|
const stem = buildSessionStem(startedIso, `folded-${sanitizeRef(args.ref)}`);
|
|
@@ -5114,7 +4981,7 @@ function sanitizeRef(ref) {
|
|
|
5114
4981
|
|
|
5115
4982
|
// src/commands/track.ts
|
|
5116
4983
|
import { promises as fs32 } from "fs";
|
|
5117
|
-
import
|
|
4984
|
+
import path44 from "path";
|
|
5118
4985
|
import { z as z40 } from "zod";
|
|
5119
4986
|
import { stringify as yamlStringify } from "yaml";
|
|
5120
4987
|
var ArgsSchema36 = z40.object({
|
|
@@ -5161,13 +5028,13 @@ var track_default = defineCommand({
|
|
|
5161
5028
|
if (await dirExists5(dir)) {
|
|
5162
5029
|
throw new UsageError(`Initiative already exists: ${args.slug}`);
|
|
5163
5030
|
}
|
|
5164
|
-
await fs32.mkdir(
|
|
5165
|
-
await fs32.mkdir(
|
|
5166
|
-
await fs32.mkdir(
|
|
5031
|
+
await fs32.mkdir(path44.join(dir, "tasks"), { recursive: true });
|
|
5032
|
+
await fs32.mkdir(path44.join(dir, "sessions"), { recursive: true });
|
|
5033
|
+
await fs32.mkdir(path44.join(dir, "sources"), { recursive: true });
|
|
5167
5034
|
const title = args.title ?? deriveTitle(args.slug);
|
|
5168
5035
|
const briefBody = buildBriefBody(title, args.ref);
|
|
5169
5036
|
await writeFrontmatter(
|
|
5170
|
-
|
|
5037
|
+
path44.join(dir, "brief.md"),
|
|
5171
5038
|
{
|
|
5172
5039
|
schema_version: 1,
|
|
5173
5040
|
title,
|
|
@@ -5183,8 +5050,8 @@ var track_default = defineCommand({
|
|
|
5183
5050
|
const artifacts = ArtifactsSchema.parse({
|
|
5184
5051
|
worktrees: args.worktree ? [{ path: args.worktree, repo: args.worktree, name: "main", default: true }] : []
|
|
5185
5052
|
});
|
|
5186
|
-
await atomicWrite(
|
|
5187
|
-
await atomicWrite(
|
|
5053
|
+
await atomicWrite(path44.join(dir, "artifacts.yml"), yamlStringify(artifacts));
|
|
5054
|
+
await atomicWrite(path44.join(dir, "sources", ".gitkeep"), "");
|
|
5188
5055
|
await appendTriagedLog("track", args.ref, `slug:${args.slug}`);
|
|
5189
5056
|
return { slug: args.slug, dir, ref: args.ref };
|
|
5190
5057
|
}
|
|
@@ -5224,6 +5091,8 @@ var ArgsSchema37 = z41.object({
|
|
|
5224
5091
|
// Frame the prompt as ad-hoc work on the workstream rather than a
|
|
5225
5092
|
// continuation of its handoff / top task.
|
|
5226
5093
|
adhoc: z41.boolean().optional(),
|
|
5094
|
+
// Rank the notes against this instead of the top task and brief titles.
|
|
5095
|
+
about: z41.string().min(1).optional(),
|
|
5227
5096
|
// Skip the check for another session already live on this initiative.
|
|
5228
5097
|
no_sibling_check: z41.boolean().optional()
|
|
5229
5098
|
});
|
|
@@ -5247,12 +5116,16 @@ var promptCommand = defineCommand({
|
|
|
5247
5116
|
long: "--adhoc",
|
|
5248
5117
|
description: "Frame the prompt as ad-hoc work on the workstream, awaiting the user\u2019s task, not a continuation of the handoff / top task."
|
|
5249
5118
|
},
|
|
5119
|
+
about: {
|
|
5120
|
+
long: "--about",
|
|
5121
|
+
description: "What this session is about, ranking the notes against it instead of the top task and brief titles."
|
|
5122
|
+
},
|
|
5250
5123
|
no_sibling_check: {
|
|
5251
5124
|
long: "--no-sibling-check",
|
|
5252
5125
|
description: "Skip the check for another session already live on this initiative."
|
|
5253
5126
|
}
|
|
5254
5127
|
},
|
|
5255
|
-
usage: "active-work prompt [slug] [--offline] [--cwd <dir>] [--adhoc] [--no-sibling-check]"
|
|
5128
|
+
usage: "active-work prompt [slug] [--offline] [--cwd <dir>] [--adhoc] [--about <text>] [--no-sibling-check]"
|
|
5256
5129
|
},
|
|
5257
5130
|
async run(args, ctx) {
|
|
5258
5131
|
const activeRoot = ctx.activeRoot ?? getActiveRoot();
|
|
@@ -5274,6 +5147,7 @@ var promptCommand = defineCommand({
|
|
|
5274
5147
|
slug,
|
|
5275
5148
|
includeLiveStatus: !args.offline,
|
|
5276
5149
|
adhoc: args.adhoc,
|
|
5150
|
+
...args.about !== void 0 ? { about: args.about } : {},
|
|
5277
5151
|
detectSiblings: !args.no_sibling_check && !args.offline,
|
|
5278
5152
|
...process.env.AW_LEASE_ID ? { ownLeaseId: process.env.AW_LEASE_ID } : {}
|
|
5279
5153
|
});
|
|
@@ -5284,7 +5158,7 @@ var prompt_default = promptCommand;
|
|
|
5284
5158
|
|
|
5285
5159
|
// src/commands/edit.ts
|
|
5286
5160
|
import { promises as fs33 } from "fs";
|
|
5287
|
-
import
|
|
5161
|
+
import path45 from "path";
|
|
5288
5162
|
import { spawn as spawn2 } from "child_process";
|
|
5289
5163
|
import { z as z42 } from "zod";
|
|
5290
5164
|
var ArgsSchema38 = z42.object({
|
|
@@ -5335,7 +5209,7 @@ var defaultDeps = {
|
|
|
5335
5209
|
spawner: defaultSpawner
|
|
5336
5210
|
};
|
|
5337
5211
|
function targetFile(slug) {
|
|
5338
|
-
return
|
|
5212
|
+
return path45.join(getInitiativeDir(slug), "brief.md");
|
|
5339
5213
|
}
|
|
5340
5214
|
async function fileExists2(p) {
|
|
5341
5215
|
try {
|
|
@@ -5414,7 +5288,7 @@ import {
|
|
|
5414
5288
|
} from "@titan-design/registry";
|
|
5415
5289
|
|
|
5416
5290
|
// src/version.ts
|
|
5417
|
-
var BUILD_VERSION = "0.
|
|
5291
|
+
var BUILD_VERSION = "0.7.0";
|
|
5418
5292
|
|
|
5419
5293
|
// src/server/mcp.ts
|
|
5420
5294
|
var TOOL_NAME_PREFIX = "active__";
|
|
@@ -5437,7 +5311,7 @@ import { DaemonAlreadyRunningError, startDaemon } from "@titan-design/daemon";
|
|
|
5437
5311
|
|
|
5438
5312
|
// src/server/dashboard-routes.ts
|
|
5439
5313
|
import { promises as fs34 } from "fs";
|
|
5440
|
-
import
|
|
5314
|
+
import path46 from "path";
|
|
5441
5315
|
import { fileURLToPath } from "url";
|
|
5442
5316
|
var PLACEHOLDER_HTML = `<!doctype html>
|
|
5443
5317
|
<html lang="en">
|
|
@@ -5469,17 +5343,17 @@ var CONTENT_TYPES = {
|
|
|
5469
5343
|
".woff2": "font/woff2"
|
|
5470
5344
|
};
|
|
5471
5345
|
function contentTypeFor(filename) {
|
|
5472
|
-
const ext =
|
|
5346
|
+
const ext = path46.extname(filename).toLowerCase();
|
|
5473
5347
|
return CONTENT_TYPES[ext] ?? "application/octet-stream";
|
|
5474
5348
|
}
|
|
5475
5349
|
function dashboardDirCandidates() {
|
|
5476
|
-
const here =
|
|
5350
|
+
const here = path46.dirname(fileURLToPath(import.meta.url));
|
|
5477
5351
|
return [
|
|
5478
|
-
|
|
5352
|
+
path46.resolve(here, "dashboard"),
|
|
5479
5353
|
// bundled: dist/cli.js -> dist/dashboard
|
|
5480
|
-
|
|
5354
|
+
path46.resolve(here, "..", "dashboard"),
|
|
5481
5355
|
// legacy: dist/server -> dist/dashboard
|
|
5482
|
-
|
|
5356
|
+
path46.resolve(here, "..", "..", "dist", "dashboard")
|
|
5483
5357
|
// dev: src/server -> dist/dashboard
|
|
5484
5358
|
];
|
|
5485
5359
|
}
|
|
@@ -5505,13 +5379,13 @@ async function handleDashboard(c) {
|
|
|
5505
5379
|
const url = new URL(c.req.url);
|
|
5506
5380
|
const subpath = url.pathname.replace(/^\/ui\/?/, "");
|
|
5507
5381
|
const relative = subpath === "" ? "index.html" : subpath;
|
|
5508
|
-
const target =
|
|
5509
|
-
if (!target.startsWith(root +
|
|
5382
|
+
const target = path46.resolve(root, relative);
|
|
5383
|
+
if (!target.startsWith(root + path46.sep) && target !== root) {
|
|
5510
5384
|
return c.text("forbidden", 403);
|
|
5511
5385
|
}
|
|
5512
5386
|
const stat = await safeStat(target);
|
|
5513
5387
|
if (!stat.exists || !stat.isFile) {
|
|
5514
|
-
const indexPath =
|
|
5388
|
+
const indexPath = path46.join(root, "index.html");
|
|
5515
5389
|
const indexStat = await safeStat(indexPath);
|
|
5516
5390
|
if (!indexStat.exists) {
|
|
5517
5391
|
return c.html(PLACEHOLDER_HTML, 200);
|
|
@@ -5529,13 +5403,13 @@ async function handleDashboard(c) {
|
|
|
5529
5403
|
|
|
5530
5404
|
// src/server/logger.ts
|
|
5531
5405
|
import { mkdirSync, createWriteStream } from "fs";
|
|
5532
|
-
import
|
|
5406
|
+
import path47 from "path";
|
|
5533
5407
|
import pino, { multistream } from "pino";
|
|
5534
5408
|
var cachedLogger;
|
|
5535
5409
|
function buildLogger() {
|
|
5536
5410
|
const stateRoot = getStateRoot();
|
|
5537
5411
|
mkdirSync(stateRoot, { recursive: true });
|
|
5538
|
-
const logPath =
|
|
5412
|
+
const logPath = path47.join(stateRoot, "daemon.log");
|
|
5539
5413
|
const fileStream = createWriteStream(logPath, { flags: "a" });
|
|
5540
5414
|
const stderrIsTTY = process.stderr.isTTY === true;
|
|
5541
5415
|
const stderrStream = stderrIsTTY ? pino.transport({
|
|
@@ -5556,7 +5430,7 @@ import { transcriptsRoot as transcriptsRoot2 } from "@titan-design/session-read"
|
|
|
5556
5430
|
import { watchTree } from "@titan-design/daemon";
|
|
5557
5431
|
|
|
5558
5432
|
// src/session-index/refresh.ts
|
|
5559
|
-
import
|
|
5433
|
+
import path56 from "path";
|
|
5560
5434
|
import { promises as fs44 } from "fs";
|
|
5561
5435
|
import lockfile from "proper-lockfile";
|
|
5562
5436
|
import { discoverTranscripts, transcriptsRoot } from "@titan-design/session-read";
|
|
@@ -5564,7 +5438,7 @@ import { refreshCorpus, resetIndex } from "@titan-design/session-graph";
|
|
|
5564
5438
|
|
|
5565
5439
|
// src/session-index/tasks.ts
|
|
5566
5440
|
import { promises as fs35 } from "fs";
|
|
5567
|
-
import
|
|
5441
|
+
import path48 from "path";
|
|
5568
5442
|
var AMBIGUOUS = null;
|
|
5569
5443
|
async function initiativeSlugs(root) {
|
|
5570
5444
|
try {
|
|
@@ -5576,7 +5450,7 @@ async function initiativeSlugs(root) {
|
|
|
5576
5450
|
}
|
|
5577
5451
|
}
|
|
5578
5452
|
async function readInitiative(root, slug) {
|
|
5579
|
-
const dir =
|
|
5453
|
+
const dir = path48.join(root, slug, "tasks");
|
|
5580
5454
|
let files;
|
|
5581
5455
|
try {
|
|
5582
5456
|
files = await fs35.readdir(dir);
|
|
@@ -5588,7 +5462,7 @@ async function readInitiative(root, slug) {
|
|
|
5588
5462
|
for (const file of files) {
|
|
5589
5463
|
if (!file.endsWith(".yml")) continue;
|
|
5590
5464
|
try {
|
|
5591
|
-
const task = await readYaml(
|
|
5465
|
+
const task = await readYaml(path48.join(dir, file), TaskSchema);
|
|
5592
5466
|
found.push([task.id, { initiative: slug, title: task.title, status: task.status }]);
|
|
5593
5467
|
} catch {
|
|
5594
5468
|
continue;
|
|
@@ -5642,8 +5516,8 @@ function extractMentions(body, initiative, index) {
|
|
|
5642
5516
|
for (const id of matches(body, NOTE_REF)) {
|
|
5643
5517
|
if (index.noteRefs.has(noteRef(id))) found.add(noteRef(id));
|
|
5644
5518
|
}
|
|
5645
|
-
for (const
|
|
5646
|
-
const scoped = `${initiative}/${
|
|
5519
|
+
for (const path67 of matches(body, SOURCE_PATH)) {
|
|
5520
|
+
const scoped = `${initiative}/${path67}`;
|
|
5647
5521
|
if (index.sourcePaths.has(scoped)) found.add(sourceRef(scoped));
|
|
5648
5522
|
}
|
|
5649
5523
|
return [...found].sort();
|
|
@@ -5980,26 +5854,26 @@ function compact(spans) {
|
|
|
5980
5854
|
|
|
5981
5855
|
// src/workspace-index/scan.ts
|
|
5982
5856
|
import { promises as fs42 } from "fs";
|
|
5983
|
-
import
|
|
5857
|
+
import path55 from "path";
|
|
5984
5858
|
|
|
5985
5859
|
// src/lint/index.ts
|
|
5986
5860
|
import { promises as fs41 } from "fs";
|
|
5987
|
-
import
|
|
5861
|
+
import path54 from "path";
|
|
5988
5862
|
|
|
5989
5863
|
// src/lint/brief.ts
|
|
5990
5864
|
import { promises as fs37 } from "fs";
|
|
5991
|
-
import
|
|
5865
|
+
import path49 from "path";
|
|
5992
5866
|
|
|
5993
5867
|
// src/lint/hashes.ts
|
|
5994
5868
|
import { promises as fs38 } from "fs";
|
|
5995
|
-
import
|
|
5869
|
+
import path50 from "path";
|
|
5996
5870
|
async function lintHashes(slug, initiativeDir) {
|
|
5997
5871
|
const manifest = await readArtifactHashes(initiativeDir);
|
|
5998
5872
|
const findings = [];
|
|
5999
5873
|
for (const [relPath, storedHash] of Object.entries(manifest)) {
|
|
6000
5874
|
let content;
|
|
6001
5875
|
try {
|
|
6002
|
-
content = await fs38.readFile(
|
|
5876
|
+
content = await fs38.readFile(path50.join(initiativeDir, relPath), "utf8");
|
|
6003
5877
|
} catch (err) {
|
|
6004
5878
|
const code = err.code;
|
|
6005
5879
|
if (code === "ENOENT") continue;
|
|
@@ -6017,16 +5891,16 @@ async function lintHashes(slug, initiativeDir) {
|
|
|
6017
5891
|
}
|
|
6018
5892
|
|
|
6019
5893
|
// src/lint/open-loops.ts
|
|
6020
|
-
import
|
|
5894
|
+
import path51 from "path";
|
|
6021
5895
|
|
|
6022
5896
|
// src/lint/task.ts
|
|
6023
5897
|
import { promises as fs39 } from "fs";
|
|
6024
|
-
import
|
|
5898
|
+
import path52 from "path";
|
|
6025
5899
|
import YAML2 from "yaml";
|
|
6026
5900
|
|
|
6027
5901
|
// src/lint/zero-loops.ts
|
|
6028
5902
|
import { promises as fs40 } from "fs";
|
|
6029
|
-
import
|
|
5903
|
+
import path53 from "path";
|
|
6030
5904
|
import YAML3 from "yaml";
|
|
6031
5905
|
|
|
6032
5906
|
// src/lint/index.ts
|
|
@@ -6055,21 +5929,21 @@ function isVisible(entry, extensions) {
|
|
|
6055
5929
|
}
|
|
6056
5930
|
async function filesIn(dir, extensions) {
|
|
6057
5931
|
const entries = await readDirents(dir);
|
|
6058
|
-
return entries.filter((entry) => isVisible(entry, extensions)).map((entry) =>
|
|
5932
|
+
return entries.filter((entry) => isVisible(entry, extensions)).map((entry) => path55.join(dir, entry.name)).sort();
|
|
6059
5933
|
}
|
|
6060
5934
|
async function taskFiles(tasksDir) {
|
|
6061
5935
|
const own = await filesIn(tasksDir, [".yml", ".yaml"]);
|
|
6062
|
-
const archive = await filesIn(
|
|
5936
|
+
const archive = await filesIn(path55.join(tasksDir, "archive"), [".yml", ".yaml"]);
|
|
6063
5937
|
return [...own, ...archive];
|
|
6064
5938
|
}
|
|
6065
5939
|
async function collectSlug(activeRoot, slug) {
|
|
6066
|
-
const dir =
|
|
6067
|
-
const brief =
|
|
5940
|
+
const dir = path55.join(activeRoot, slug);
|
|
5941
|
+
const brief = path55.join(dir, "brief.md");
|
|
6068
5942
|
const [notes, tasks, sessions2, sources] = await Promise.all([
|
|
6069
|
-
filesIn(
|
|
6070
|
-
taskFiles(
|
|
6071
|
-
filesIn(
|
|
6072
|
-
filesIn(
|
|
5943
|
+
filesIn(path55.join(dir, "sources", "notes"), [".md"]),
|
|
5944
|
+
taskFiles(path55.join(dir, "tasks")),
|
|
5945
|
+
filesIn(path55.join(dir, "sessions"), [".md"]),
|
|
5946
|
+
filesIn(path55.join(dir, "sources"), [".md"])
|
|
6073
5947
|
]);
|
|
6074
5948
|
return [
|
|
6075
5949
|
...notes.map((p) => ["note", p]),
|
|
@@ -6479,7 +6353,7 @@ function refreshLockPath() {
|
|
|
6479
6353
|
}
|
|
6480
6354
|
async function withRefreshLock(fn) {
|
|
6481
6355
|
const target = refreshLockPath();
|
|
6482
|
-
await fs44.mkdir(
|
|
6356
|
+
await fs44.mkdir(path56.dirname(target), { recursive: true });
|
|
6483
6357
|
await fs44.writeFile(target, "", { flag: "a" });
|
|
6484
6358
|
const release = await lockfile.lock(target, {
|
|
6485
6359
|
realpath: false,
|
|
@@ -7011,7 +6885,7 @@ var mcp_status_default = defineCommand({
|
|
|
7011
6885
|
|
|
7012
6886
|
// src/commands/mcp-logs.ts
|
|
7013
6887
|
import { promises as fs45 } from "fs";
|
|
7014
|
-
import
|
|
6888
|
+
import path57 from "path";
|
|
7015
6889
|
import { z as z48 } from "zod";
|
|
7016
6890
|
var ArgsSchema43 = z48.object({
|
|
7017
6891
|
lines: z48.number().int().positive().optional()
|
|
@@ -7035,7 +6909,7 @@ var mcp_logs_default = defineCommand({
|
|
|
7035
6909
|
},
|
|
7036
6910
|
async run(args) {
|
|
7037
6911
|
const n = args.lines ?? DEFAULT_LINES;
|
|
7038
|
-
const logPath =
|
|
6912
|
+
const logPath = path57.join(getStateRoot(), "daemon.log");
|
|
7039
6913
|
let content;
|
|
7040
6914
|
try {
|
|
7041
6915
|
content = await fs45.readFile(logPath, "utf8");
|
|
@@ -7065,7 +6939,7 @@ import { Clusterer } from "@titan-design/cluster";
|
|
|
7065
6939
|
|
|
7066
6940
|
// src/drain/store.ts
|
|
7067
6941
|
import { promises as fs46 } from "fs";
|
|
7068
|
-
import
|
|
6942
|
+
import path58 from "path";
|
|
7069
6943
|
|
|
7070
6944
|
// src/schemas/template.ts
|
|
7071
6945
|
import { z as z49 } from "zod";
|
|
@@ -7095,10 +6969,10 @@ var TemplatesFileSchema = z49.object({
|
|
|
7095
6969
|
|
|
7096
6970
|
// src/drain/store.ts
|
|
7097
6971
|
function templatesPath(root) {
|
|
7098
|
-
return
|
|
6972
|
+
return path58.join(root, "templates.yml");
|
|
7099
6973
|
}
|
|
7100
6974
|
function occurrencesPath(root) {
|
|
7101
|
-
return
|
|
6975
|
+
return path58.join(root, "occurrences.jsonl");
|
|
7102
6976
|
}
|
|
7103
6977
|
async function loadTemplates(root = getMinerRoot()) {
|
|
7104
6978
|
try {
|
|
@@ -7136,7 +7010,7 @@ async function appendOccurrences(occurrences, root = getMinerRoot()) {
|
|
|
7136
7010
|
|
|
7137
7011
|
// src/drain/tree-store.ts
|
|
7138
7012
|
import { promises as fs47 } from "fs";
|
|
7139
|
-
import
|
|
7013
|
+
import path59 from "path";
|
|
7140
7014
|
import { z as z50 } from "zod";
|
|
7141
7015
|
var PartitionSchema = z50.object({
|
|
7142
7016
|
partition: z50.string().min(1),
|
|
@@ -7160,7 +7034,7 @@ var LegacySnapshotFileSchema = z50.object({
|
|
|
7160
7034
|
trees: z50.array(PartitionSchema.omit({ partition: true }).extend({ toolType: z50.string().min(1) }))
|
|
7161
7035
|
});
|
|
7162
7036
|
function snapshotPath(root) {
|
|
7163
|
-
return
|
|
7037
|
+
return path59.join(root, "drain-trees.json");
|
|
7164
7038
|
}
|
|
7165
7039
|
function empty() {
|
|
7166
7040
|
return { version: 1, partitions: [] };
|
|
@@ -7339,7 +7213,7 @@ function extractBlobs(line, toolNames) {
|
|
|
7339
7213
|
|
|
7340
7214
|
// src/drain/reader-state.ts
|
|
7341
7215
|
import { promises as fs48 } from "fs";
|
|
7342
|
-
import
|
|
7216
|
+
import path60 from "path";
|
|
7343
7217
|
import { z as z51 } from "zod";
|
|
7344
7218
|
var TranscriptStateSchema = z51.object({
|
|
7345
7219
|
/** `~`-relative path, matching `session-index/discover.ts`'s display form. */
|
|
@@ -7360,7 +7234,7 @@ var ReaderStateSchema = z51.object({
|
|
|
7360
7234
|
});
|
|
7361
7235
|
var MAX_PENDING_TOOL_NAMES = 256;
|
|
7362
7236
|
function readerStatePath(root = getMinerRoot()) {
|
|
7363
|
-
return
|
|
7237
|
+
return path60.join(root, "reader-state.json");
|
|
7364
7238
|
}
|
|
7365
7239
|
async function loadReaderState(root = getMinerRoot()) {
|
|
7366
7240
|
try {
|
|
@@ -8011,7 +7885,7 @@ async function readStdinJson(stream = process.stdin) {
|
|
|
8011
7885
|
|
|
8012
7886
|
// src/utils/agent-chat-hook-state.ts
|
|
8013
7887
|
import { promises as fs49 } from "fs";
|
|
8014
|
-
import
|
|
7888
|
+
import path61 from "path";
|
|
8015
7889
|
import { z as z56 } from "zod";
|
|
8016
7890
|
var SpawnContextSchema = z56.object({
|
|
8017
7891
|
slug: z56.string().min(1),
|
|
@@ -8031,10 +7905,10 @@ var SpawnContextSchema = z56.object({
|
|
|
8031
7905
|
briefing: z56.string().nullable().default(null)
|
|
8032
7906
|
});
|
|
8033
7907
|
function stateDir() {
|
|
8034
|
-
return
|
|
7908
|
+
return path61.join(getStateRoot(), "agent-chat-hooks");
|
|
8035
7909
|
}
|
|
8036
7910
|
function stateFile(agentId) {
|
|
8037
|
-
return
|
|
7911
|
+
return path61.join(stateDir(), `${agentId}.json`);
|
|
8038
7912
|
}
|
|
8039
7913
|
async function stashSpawnContext(agentId, context) {
|
|
8040
7914
|
await fs49.mkdir(stateDir(), { recursive: true });
|
|
@@ -8204,7 +8078,7 @@ import { join } from "path";
|
|
|
8204
8078
|
|
|
8205
8079
|
// src/migrations/v1-to-v2-artifacts.ts
|
|
8206
8080
|
import { promises as fs50 } from "fs";
|
|
8207
|
-
import
|
|
8081
|
+
import path62 from "path";
|
|
8208
8082
|
import YAML4 from "yaml";
|
|
8209
8083
|
function asArray(value) {
|
|
8210
8084
|
return Array.isArray(value) ? value : [];
|
|
@@ -8264,7 +8138,7 @@ async function walkArtifactsFiles(activeRoot) {
|
|
|
8264
8138
|
for (const entry of entries) {
|
|
8265
8139
|
if (!entry.isDirectory()) continue;
|
|
8266
8140
|
if (entry.name.startsWith(".")) continue;
|
|
8267
|
-
const candidate =
|
|
8141
|
+
const candidate = path62.join(activeRoot, entry.name, "artifacts.yml");
|
|
8268
8142
|
try {
|
|
8269
8143
|
await fs50.access(candidate);
|
|
8270
8144
|
out.push(candidate);
|
|
@@ -8273,14 +8147,14 @@ async function walkArtifactsFiles(activeRoot) {
|
|
|
8273
8147
|
}
|
|
8274
8148
|
} catch {
|
|
8275
8149
|
}
|
|
8276
|
-
const archiveRoot =
|
|
8150
|
+
const archiveRoot = path62.resolve(activeRoot, "..");
|
|
8277
8151
|
try {
|
|
8278
8152
|
const domains = await fs50.readdir(archiveRoot, { withFileTypes: true });
|
|
8279
8153
|
for (const domain of domains) {
|
|
8280
8154
|
if (!domain.isDirectory()) continue;
|
|
8281
8155
|
if (domain.name.startsWith(".")) continue;
|
|
8282
|
-
if (
|
|
8283
|
-
const archiveDir =
|
|
8156
|
+
if (path62.join(archiveRoot, domain.name) === path62.resolve(activeRoot)) continue;
|
|
8157
|
+
const archiveDir = path62.join(archiveRoot, domain.name, "archive");
|
|
8284
8158
|
let archived;
|
|
8285
8159
|
try {
|
|
8286
8160
|
archived = await fs50.readdir(archiveDir, { withFileTypes: true });
|
|
@@ -8289,7 +8163,7 @@ async function walkArtifactsFiles(activeRoot) {
|
|
|
8289
8163
|
}
|
|
8290
8164
|
for (const entry of archived) {
|
|
8291
8165
|
if (!entry.isDirectory()) continue;
|
|
8292
|
-
const candidate =
|
|
8166
|
+
const candidate = path62.join(archiveDir, entry.name, "artifacts.yml");
|
|
8293
8167
|
try {
|
|
8294
8168
|
await fs50.access(candidate);
|
|
8295
8169
|
out.push(candidate);
|
|
@@ -8303,7 +8177,7 @@ async function walkArtifactsFiles(activeRoot) {
|
|
|
8303
8177
|
}
|
|
8304
8178
|
async function appendMigrationLog(activeRoot, lines) {
|
|
8305
8179
|
if (lines.length === 0) return;
|
|
8306
|
-
const logPath =
|
|
8180
|
+
const logPath = path62.join(activeRoot, ".migrations.log");
|
|
8307
8181
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
8308
8182
|
const body = lines.map((l) => `${stamp} v1->v2 ${l}
|
|
8309
8183
|
`).join("");
|
|
@@ -8335,7 +8209,7 @@ var v1ToV2Artifacts = {
|
|
|
8335
8209
|
|
|
8336
8210
|
// src/migrations/v2-to-v3-open-loops.ts
|
|
8337
8211
|
import { promises as fs53 } from "fs";
|
|
8338
|
-
import
|
|
8212
|
+
import path64 from "path";
|
|
8339
8213
|
|
|
8340
8214
|
// src/migrations/v3-proposal.ts
|
|
8341
8215
|
import { promises as fs51 } from "fs";
|
|
@@ -9235,17 +9109,17 @@ async function loadProposal() {
|
|
|
9235
9109
|
|
|
9236
9110
|
// src/migrations/v3-repairs.ts
|
|
9237
9111
|
import { promises as fs52 } from "fs";
|
|
9238
|
-
import
|
|
9112
|
+
import path63 from "path";
|
|
9239
9113
|
var KNOWN_REPAIRS = [
|
|
9240
9114
|
{
|
|
9241
|
-
file:
|
|
9115
|
+
file: path63.join("audiobook", "sessions", "2026-07-23-0549-2026-07-26-book1-m4b-packaging.md"),
|
|
9242
9116
|
kind: "retrack",
|
|
9243
9117
|
why: "track is a branch name ('feat/tts-quality'), not one of canonical|sidecar|adhoc"
|
|
9244
9118
|
},
|
|
9245
9119
|
{
|
|
9246
|
-
file:
|
|
9120
|
+
file: path63.join("voltras-workspace", "sessions", "ARCHIVED-handoff-through-2026-07-15.md"),
|
|
9247
9121
|
kind: "relocate",
|
|
9248
|
-
target:
|
|
9122
|
+
target: path63.join("voltras-workspace", "sources", "ARCHIVED-handoff-through-2026-07-15.md"),
|
|
9249
9123
|
why: "not a session file \u2014 a hand-archived handoff parked in sessions/"
|
|
9250
9124
|
}
|
|
9251
9125
|
];
|
|
@@ -9304,7 +9178,7 @@ async function exists3(p) {
|
|
|
9304
9178
|
async function planRepairs(activeRoot) {
|
|
9305
9179
|
const plans = [];
|
|
9306
9180
|
for (const repair of KNOWN_REPAIRS) {
|
|
9307
|
-
const fullPath =
|
|
9181
|
+
const fullPath = path63.join(activeRoot, repair.file);
|
|
9308
9182
|
if (!await exists3(fullPath)) {
|
|
9309
9183
|
plans.push({ action: "skip", file: repair.file, detail: "already absent" });
|
|
9310
9184
|
continue;
|
|
@@ -9314,7 +9188,7 @@ async function planRepairs(activeRoot) {
|
|
|
9314
9188
|
continue;
|
|
9315
9189
|
}
|
|
9316
9190
|
const target = repair.target;
|
|
9317
|
-
if (await exists3(
|
|
9191
|
+
if (await exists3(path63.join(activeRoot, target))) {
|
|
9318
9192
|
plans.push({
|
|
9319
9193
|
action: "skip",
|
|
9320
9194
|
file: repair.file,
|
|
@@ -9328,7 +9202,7 @@ async function planRepairs(activeRoot) {
|
|
|
9328
9202
|
return plans;
|
|
9329
9203
|
}
|
|
9330
9204
|
async function applyRepair(activeRoot, plan) {
|
|
9331
|
-
const fullPath =
|
|
9205
|
+
const fullPath = path63.join(activeRoot, plan.file);
|
|
9332
9206
|
if (plan.action === "retrack" && plan.repaired !== void 0) {
|
|
9333
9207
|
await writeFrontmatter(
|
|
9334
9208
|
fullPath,
|
|
@@ -9339,15 +9213,15 @@ async function applyRepair(activeRoot, plan) {
|
|
|
9339
9213
|
return;
|
|
9340
9214
|
}
|
|
9341
9215
|
if (plan.action === "relocate") {
|
|
9342
|
-
const target =
|
|
9343
|
-
await fs52.mkdir(
|
|
9216
|
+
const target = path63.join(activeRoot, plan.target);
|
|
9217
|
+
await fs52.mkdir(path63.dirname(target), { recursive: true });
|
|
9344
9218
|
await fs52.rename(fullPath, target);
|
|
9345
9219
|
}
|
|
9346
9220
|
}
|
|
9347
9221
|
|
|
9348
9222
|
// src/migrations/v2-to-v3-open-loops.ts
|
|
9349
9223
|
var HANDOFF_FILE = "handoff.md";
|
|
9350
|
-
var HANDOFF_ARCHIVE =
|
|
9224
|
+
var HANDOFF_ARCHIVE = path64.join("sources", "handoff-archive.md");
|
|
9351
9225
|
async function pathExists(p) {
|
|
9352
9226
|
try {
|
|
9353
9227
|
await fs53.access(p);
|
|
@@ -9366,7 +9240,7 @@ async function listInitiativeSlugs3(activeRoot) {
|
|
|
9366
9240
|
const slugs = [];
|
|
9367
9241
|
for (const entry of entries) {
|
|
9368
9242
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
9369
|
-
if (await pathExists(
|
|
9243
|
+
if (await pathExists(path64.join(activeRoot, entry.name, "brief.md"))) {
|
|
9370
9244
|
slugs.push(entry.name);
|
|
9371
9245
|
}
|
|
9372
9246
|
}
|
|
@@ -9374,9 +9248,9 @@ async function listInitiativeSlugs3(activeRoot) {
|
|
|
9374
9248
|
}
|
|
9375
9249
|
async function maxOnDiskTaskNumber2(initiativeDir, prefix) {
|
|
9376
9250
|
const re = new RegExp(`^${prefix}-(\\d+)\\.yml$`);
|
|
9377
|
-
const tasksDir =
|
|
9251
|
+
const tasksDir = path64.join(initiativeDir, "tasks");
|
|
9378
9252
|
let max = 0;
|
|
9379
|
-
for (const dir of [tasksDir,
|
|
9253
|
+
for (const dir of [tasksDir, path64.join(tasksDir, "archive")]) {
|
|
9380
9254
|
let names;
|
|
9381
9255
|
try {
|
|
9382
9256
|
names = await fs53.readdir(dir);
|
|
@@ -9398,7 +9272,7 @@ async function nextTaskSeq(initiativeDir, frontmatter2) {
|
|
|
9398
9272
|
return max > 0 ? max : null;
|
|
9399
9273
|
}
|
|
9400
9274
|
async function planBrief(initiativeDir, slug) {
|
|
9401
|
-
const raw = await readRawFrontmatter(
|
|
9275
|
+
const raw = await readRawFrontmatter(path64.join(initiativeDir, "brief.md"));
|
|
9402
9276
|
const repaired = repairBriefFrontmatter(slug, raw.frontmatter);
|
|
9403
9277
|
const taskSeq = await nextTaskSeq(initiativeDir, repaired.frontmatter);
|
|
9404
9278
|
if (taskSeq === null && repaired.applied.length === 0) return { write: null };
|
|
@@ -9415,8 +9289,8 @@ async function planBrief(initiativeDir, slug) {
|
|
|
9415
9289
|
};
|
|
9416
9290
|
}
|
|
9417
9291
|
async function planHandoff(initiativeDir) {
|
|
9418
|
-
if (!await pathExists(
|
|
9419
|
-
if (await pathExists(
|
|
9292
|
+
if (!await pathExists(path64.join(initiativeDir, HANDOFF_FILE))) return "absent";
|
|
9293
|
+
if (await pathExists(path64.join(initiativeDir, HANDOFF_ARCHIVE))) return "archive-exists";
|
|
9420
9294
|
return "archive-and-remove";
|
|
9421
9295
|
}
|
|
9422
9296
|
function buildOpenSession(entry) {
|
|
@@ -9506,7 +9380,7 @@ function draftSessions(entry, abandonedAt) {
|
|
|
9506
9380
|
return [open, buildAbandonSession(entry, open.stem, abandonedAt)];
|
|
9507
9381
|
}
|
|
9508
9382
|
async function planInitiative(activeRoot, slug, entry, abandonedAt) {
|
|
9509
|
-
const initiativeDir =
|
|
9383
|
+
const initiativeDir = path64.join(activeRoot, slug);
|
|
9510
9384
|
const brief = await planBrief(initiativeDir, slug);
|
|
9511
9385
|
const base = {
|
|
9512
9386
|
slug,
|
|
@@ -9545,9 +9419,9 @@ async function planV2ToV3(activeRoot) {
|
|
|
9545
9419
|
return { proposalOrigin: origin, initiatives, repairs: await planRepairs(activeRoot) };
|
|
9546
9420
|
}
|
|
9547
9421
|
async function archiveHandoff(initiativeDir) {
|
|
9548
|
-
const source =
|
|
9549
|
-
const target =
|
|
9550
|
-
await fs53.mkdir(
|
|
9422
|
+
const source = path64.join(initiativeDir, HANDOFF_FILE);
|
|
9423
|
+
const target = path64.join(initiativeDir, HANDOFF_ARCHIVE);
|
|
9424
|
+
await fs53.mkdir(path64.dirname(target), { recursive: true });
|
|
9551
9425
|
await fs53.copyFile(source, target);
|
|
9552
9426
|
await fs53.rm(source);
|
|
9553
9427
|
}
|
|
@@ -9566,15 +9440,15 @@ async function writePlannedSession(activeRoot, slug, session) {
|
|
|
9566
9440
|
});
|
|
9567
9441
|
}
|
|
9568
9442
|
async function applyInitiative(activeRoot, plan) {
|
|
9569
|
-
const initiativeDir =
|
|
9570
|
-
await withFileLock(
|
|
9443
|
+
const initiativeDir = path64.join(activeRoot, plan.slug);
|
|
9444
|
+
await withFileLock(path64.join(initiativeDir, ".lock"), async () => {
|
|
9571
9445
|
for (const session of plan.sessions) {
|
|
9572
9446
|
if (session.exists) continue;
|
|
9573
9447
|
await writePlannedSession(activeRoot, plan.slug, session);
|
|
9574
9448
|
}
|
|
9575
9449
|
if (plan.brief !== null) {
|
|
9576
9450
|
await writeFrontmatter(
|
|
9577
|
-
|
|
9451
|
+
path64.join(initiativeDir, "brief.md"),
|
|
9578
9452
|
plan.brief.frontmatter,
|
|
9579
9453
|
plan.brief.body,
|
|
9580
9454
|
BriefFrontmatterSchema
|
|
@@ -9605,12 +9479,12 @@ var v2ToV3OpenLoops = {
|
|
|
9605
9479
|
|
|
9606
9480
|
// src/migrations/v3-to-v4-worktrees.ts
|
|
9607
9481
|
import { promises as fs54 } from "fs";
|
|
9608
|
-
import
|
|
9482
|
+
import path65 from "path";
|
|
9609
9483
|
import matter5 from "gray-matter";
|
|
9610
9484
|
import YAML5 from "yaml";
|
|
9611
9485
|
function normalize(value) {
|
|
9612
|
-
const expanded = value.startsWith("~") ?
|
|
9613
|
-
return
|
|
9486
|
+
const expanded = value.startsWith("~") ? path65.join(process.env.HOME ?? "", value.slice(1)) : value;
|
|
9487
|
+
return path65.resolve(expanded);
|
|
9614
9488
|
}
|
|
9615
9489
|
function toEntries(raw) {
|
|
9616
9490
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
|
|
@@ -9657,7 +9531,7 @@ async function readArtifacts2(file) {
|
|
|
9657
9531
|
}
|
|
9658
9532
|
}
|
|
9659
9533
|
async function migrateOne2(initiativeDir) {
|
|
9660
|
-
const briefPath =
|
|
9534
|
+
const briefPath = path65.join(initiativeDir, "brief.md");
|
|
9661
9535
|
let raw;
|
|
9662
9536
|
try {
|
|
9663
9537
|
raw = await fs54.readFile(briefPath, "utf8");
|
|
@@ -9670,7 +9544,7 @@ async function migrateOne2(initiativeDir) {
|
|
|
9670
9544
|
const incoming = toEntries(data.worktrees);
|
|
9671
9545
|
delete data.worktrees;
|
|
9672
9546
|
if (incoming.length > 0) {
|
|
9673
|
-
const artifactsPath2 =
|
|
9547
|
+
const artifactsPath2 = path65.join(initiativeDir, "artifacts.yml");
|
|
9674
9548
|
const current = await readArtifacts2(artifactsPath2);
|
|
9675
9549
|
await writeYaml(
|
|
9676
9550
|
artifactsPath2,
|
|
@@ -9695,9 +9569,9 @@ async function initiativeDirs(activeRoot) {
|
|
|
9695
9569
|
}
|
|
9696
9570
|
for (const entry of entries) {
|
|
9697
9571
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
9698
|
-
const dir =
|
|
9572
|
+
const dir = path65.join(activeRoot, entry.name);
|
|
9699
9573
|
try {
|
|
9700
|
-
await fs54.access(
|
|
9574
|
+
await fs54.access(path65.join(dir, "brief.md"));
|
|
9701
9575
|
out.push(dir);
|
|
9702
9576
|
} catch {
|
|
9703
9577
|
}
|
|
@@ -9712,12 +9586,12 @@ var v3ToV4Worktrees = {
|
|
|
9712
9586
|
const moved = [];
|
|
9713
9587
|
for (const dir of await initiativeDirs(activeRoot)) {
|
|
9714
9588
|
const count = await migrateOne2(dir);
|
|
9715
|
-
if (count > 0) moved.push(`${
|
|
9589
|
+
if (count > 0) moved.push(`${path65.basename(dir)} ${count} worktree(s)`);
|
|
9716
9590
|
}
|
|
9717
9591
|
if (moved.length === 0) return;
|
|
9718
9592
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
9719
9593
|
await fs54.appendFile(
|
|
9720
|
-
|
|
9594
|
+
path65.join(activeRoot, ".migrations.log"),
|
|
9721
9595
|
moved.map((line) => `${stamp} v3->v4 ${line}
|
|
9722
9596
|
`).join(""),
|
|
9723
9597
|
"utf8"
|
|
@@ -9727,12 +9601,12 @@ var v3ToV4Worktrees = {
|
|
|
9727
9601
|
|
|
9728
9602
|
// src/migrations/index.ts
|
|
9729
9603
|
var BASE_VERSION = 1;
|
|
9730
|
-
var
|
|
9731
|
-
var CURRENT_VERSION = targetVersion(
|
|
9604
|
+
var MIGRATIONS = [v1ToV2Artifacts, v2ToV3OpenLoops, v3ToV4Worktrees];
|
|
9605
|
+
var CURRENT_VERSION = targetVersion(MIGRATIONS);
|
|
9732
9606
|
function targetVersion(migrations) {
|
|
9733
9607
|
return migrations.reduce((highest, m) => Math.max(highest, m.to), BASE_VERSION);
|
|
9734
9608
|
}
|
|
9735
|
-
async function
|
|
9609
|
+
async function runMigrations(activeRoot, fromVersion, migrations = MIGRATIONS) {
|
|
9736
9610
|
if (fromVersion === CURRENT_VERSION) {
|
|
9737
9611
|
return { ran: [] };
|
|
9738
9612
|
}
|
|
@@ -9770,10 +9644,10 @@ var SCHEMA_VERSION_FILENAME = ".schema-version";
|
|
|
9770
9644
|
var schemaVersionPath = (activeRoot) => join(activeRoot, SCHEMA_VERSION_FILENAME);
|
|
9771
9645
|
var isNodeErrnoException = (err) => typeof err === "object" && err !== null && "code" in err;
|
|
9772
9646
|
async function readSchemaVersion(activeRoot) {
|
|
9773
|
-
const
|
|
9647
|
+
const path67 = schemaVersionPath(activeRoot);
|
|
9774
9648
|
let raw;
|
|
9775
9649
|
try {
|
|
9776
|
-
raw = await readFile(
|
|
9650
|
+
raw = await readFile(path67, "utf8");
|
|
9777
9651
|
} catch (err) {
|
|
9778
9652
|
if (isNodeErrnoException(err) && err.code === "ENOENT") {
|
|
9779
9653
|
return 0;
|
|
@@ -9783,13 +9657,13 @@ async function readSchemaVersion(activeRoot) {
|
|
|
9783
9657
|
const trimmed = raw.trim();
|
|
9784
9658
|
if (trimmed === "" || !/^\d+$/.test(trimmed)) {
|
|
9785
9659
|
throw new Error(
|
|
9786
|
-
`Invalid schema version in ${
|
|
9660
|
+
`Invalid schema version in ${path67}: expected a positive integer, got ${JSON.stringify(raw)}`
|
|
9787
9661
|
);
|
|
9788
9662
|
}
|
|
9789
9663
|
const parsed = Number(trimmed);
|
|
9790
9664
|
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
9791
9665
|
throw new Error(
|
|
9792
|
-
`Invalid schema version in ${
|
|
9666
|
+
`Invalid schema version in ${path67}: expected a positive integer, got ${JSON.stringify(raw)}`
|
|
9793
9667
|
);
|
|
9794
9668
|
}
|
|
9795
9669
|
return parsed;
|
|
@@ -9802,10 +9676,10 @@ async function writeSchemaVersion(activeRoot, version) {
|
|
|
9802
9676
|
`, "utf8");
|
|
9803
9677
|
}
|
|
9804
9678
|
async function readRawSchemaVersion(activeRoot) {
|
|
9805
|
-
const
|
|
9679
|
+
const path67 = schemaVersionPath(activeRoot);
|
|
9806
9680
|
let raw;
|
|
9807
9681
|
try {
|
|
9808
|
-
raw = await readFile(
|
|
9682
|
+
raw = await readFile(path67, "utf8");
|
|
9809
9683
|
} catch (err) {
|
|
9810
9684
|
if (isNodeErrnoException(err) && err.code === "ENOENT") {
|
|
9811
9685
|
return { present: false };
|
|
@@ -9815,13 +9689,13 @@ async function readRawSchemaVersion(activeRoot) {
|
|
|
9815
9689
|
const trimmed = raw.trim();
|
|
9816
9690
|
if (trimmed === "" || !/^\d+$/.test(trimmed)) {
|
|
9817
9691
|
throw new Error(
|
|
9818
|
-
`Invalid schema version in ${
|
|
9692
|
+
`Invalid schema version in ${path67}: expected a non-negative integer, got ${JSON.stringify(raw)}`
|
|
9819
9693
|
);
|
|
9820
9694
|
}
|
|
9821
9695
|
const parsed = Number(trimmed);
|
|
9822
9696
|
if (!Number.isInteger(parsed) || parsed < 0) {
|
|
9823
9697
|
throw new Error(
|
|
9824
|
-
`Invalid schema version in ${
|
|
9698
|
+
`Invalid schema version in ${path67}: expected a non-negative integer, got ${JSON.stringify(raw)}`
|
|
9825
9699
|
);
|
|
9826
9700
|
}
|
|
9827
9701
|
return { present: true, version: parsed };
|
|
@@ -9841,7 +9715,7 @@ async function ensureSchemaVersion(activeRoot) {
|
|
|
9841
9715
|
if (before === CURRENT_VERSION) {
|
|
9842
9716
|
return { before, after: before, migrated: false, ran: [] };
|
|
9843
9717
|
}
|
|
9844
|
-
const { ran } = await
|
|
9718
|
+
const { ran } = await runMigrations(activeRoot, before);
|
|
9845
9719
|
await writeSchemaVersion(activeRoot, CURRENT_VERSION);
|
|
9846
9720
|
return {
|
|
9847
9721
|
before,
|
|
@@ -12040,14 +11914,14 @@ import { readCommanderOption } from "@titan-design/registry";
|
|
|
12040
11914
|
|
|
12041
11915
|
// src/utils/usage-log.ts
|
|
12042
11916
|
import { promises as fs56 } from "fs";
|
|
12043
|
-
import
|
|
11917
|
+
import path66 from "path";
|
|
12044
11918
|
function usageLogPath() {
|
|
12045
|
-
return
|
|
11919
|
+
return path66.join(getStateRoot(), "usage.jsonl");
|
|
12046
11920
|
}
|
|
12047
11921
|
async function appendUsage(rec) {
|
|
12048
11922
|
try {
|
|
12049
11923
|
const file = usageLogPath();
|
|
12050
|
-
await fs56.mkdir(
|
|
11924
|
+
await fs56.mkdir(path66.dirname(file), { recursive: true });
|
|
12051
11925
|
await fs56.appendFile(file, JSON.stringify(rec) + "\n", "utf8");
|
|
12052
11926
|
} catch {
|
|
12053
11927
|
}
|