@basou/cli 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +190 -119
- package/dist/index.js.map +1 -1
- package/dist/program.js +190 -119
- package/dist/program.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2259,19 +2259,19 @@ function parseInterval(value) {
|
|
|
2259
2259
|
return seconds;
|
|
2260
2260
|
}
|
|
2261
2261
|
function abortableSleep(ms, signal) {
|
|
2262
|
-
return new Promise((
|
|
2262
|
+
return new Promise((resolve4) => {
|
|
2263
2263
|
if (signal.aborted) {
|
|
2264
|
-
|
|
2264
|
+
resolve4();
|
|
2265
2265
|
return;
|
|
2266
2266
|
}
|
|
2267
2267
|
let timer;
|
|
2268
2268
|
const onAbort = () => {
|
|
2269
2269
|
clearTimeout(timer);
|
|
2270
|
-
|
|
2270
|
+
resolve4();
|
|
2271
2271
|
};
|
|
2272
2272
|
timer = setTimeout(() => {
|
|
2273
2273
|
signal.removeEventListener("abort", onAbort);
|
|
2274
|
-
|
|
2274
|
+
resolve4();
|
|
2275
2275
|
}, ms);
|
|
2276
2276
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
2277
2277
|
});
|
|
@@ -2411,14 +2411,92 @@ async function assertWorkspaceInitialized6(basouRoot) {
|
|
|
2411
2411
|
}
|
|
2412
2412
|
}
|
|
2413
2413
|
|
|
2414
|
+
// src/commands/report.ts
|
|
2415
|
+
import { isAbsolute, resolve as resolve3 } from "path";
|
|
2416
|
+
import {
|
|
2417
|
+
assertBasouRootSafe as assertBasouRootSafe8,
|
|
2418
|
+
basouPaths as basouPaths8,
|
|
2419
|
+
findErrorCode as findErrorCode8,
|
|
2420
|
+
renderReport,
|
|
2421
|
+
resolveRepositoryRoot as resolveRepositoryRoot9,
|
|
2422
|
+
writeMarkdownFile as writeMarkdownFile4
|
|
2423
|
+
} from "@basou/core";
|
|
2424
|
+
function registerReportCommand(program2) {
|
|
2425
|
+
const report = program2.command("report").description(
|
|
2426
|
+
"Generate a work report \u2014 a shareable export explaining the work in this workspace"
|
|
2427
|
+
);
|
|
2428
|
+
report.command("generate").description("Generate a work report from the current workspace state").option("--out <path>", "Write the markdown report to a file instead of stdout").option("--json", "Emit the structured report data as JSON to stdout").option("--title <text>", "Subject line shown in the report header").option("-v, --verbose", "Show error causes").action(async (opts) => {
|
|
2429
|
+
await runReportGenerate(opts);
|
|
2430
|
+
});
|
|
2431
|
+
}
|
|
2432
|
+
async function runReportGenerate(options, ctx = {}) {
|
|
2433
|
+
try {
|
|
2434
|
+
await doRunReportGenerate(options, ctx);
|
|
2435
|
+
} catch (error) {
|
|
2436
|
+
renderCliError(error, { verbose: isVerbose(options) });
|
|
2437
|
+
process.exitCode = 1;
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
async function doRunReportGenerate(options, ctx) {
|
|
2441
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
2442
|
+
const repositoryRoot = await resolveRepositoryRootForReport(cwd);
|
|
2443
|
+
const paths = basouPaths8(repositoryRoot);
|
|
2444
|
+
await assertWorkspaceInitialized7(paths.root);
|
|
2445
|
+
const nowIso = (ctx.nowProvider?.() ?? /* @__PURE__ */ new Date()).toISOString();
|
|
2446
|
+
const result = await renderReport({
|
|
2447
|
+
paths,
|
|
2448
|
+
nowIso,
|
|
2449
|
+
...options.title !== void 0 ? { title: options.title } : {},
|
|
2450
|
+
onWarning: (w, sid) => printReplayWarning(w, sid),
|
|
2451
|
+
onSessionSkip: (sid, reason) => printSessionSkip(sid, reason),
|
|
2452
|
+
onTaskSkip: (taskId, reason) => printTaskSkip(taskId, reason)
|
|
2453
|
+
});
|
|
2454
|
+
if (options.out !== void 0) {
|
|
2455
|
+
const outPath = isAbsolute(options.out) ? options.out : resolve3(cwd, options.out);
|
|
2456
|
+
await writeMarkdownFile4(outPath, result.body);
|
|
2457
|
+
const { sessions, decisions, tasks } = result.data;
|
|
2458
|
+
console.error(
|
|
2459
|
+
`Wrote report to ${options.out} (sessions: ${sessions.total}, decisions: ${decisions.count}, tasks: ${tasks.total})`
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
if (options.json === true) {
|
|
2463
|
+
console.log(JSON.stringify(result.data, null, 2));
|
|
2464
|
+
} else if (options.out === void 0) {
|
|
2465
|
+
console.log(result.body);
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
async function resolveRepositoryRootForReport(cwd) {
|
|
2469
|
+
try {
|
|
2470
|
+
return await resolveRepositoryRoot9(cwd);
|
|
2471
|
+
} catch (error) {
|
|
2472
|
+
if (error instanceof Error && error.message === "Not a git repository") {
|
|
2473
|
+
throw new Error(
|
|
2474
|
+
"Not a git repository. Run 'git init' first, then re-run 'basou report generate'.",
|
|
2475
|
+
{ cause: error }
|
|
2476
|
+
);
|
|
2477
|
+
}
|
|
2478
|
+
throw error;
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
async function assertWorkspaceInitialized7(basouRoot) {
|
|
2482
|
+
try {
|
|
2483
|
+
await assertBasouRootSafe8(basouRoot);
|
|
2484
|
+
} catch (error) {
|
|
2485
|
+
if (findErrorCode8(error, "ENOENT")) {
|
|
2486
|
+
throw new Error("Workspace not initialized. Run 'basou init' first.");
|
|
2487
|
+
}
|
|
2488
|
+
throw error;
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2414
2492
|
// src/commands/run.ts
|
|
2415
2493
|
import { mkdir as mkdir2 } from "fs/promises";
|
|
2416
2494
|
import { homedir as homedir4 } from "os";
|
|
2417
2495
|
import { join as join5 } from "path";
|
|
2418
2496
|
import {
|
|
2419
2497
|
acquireLock as acquireLock4,
|
|
2420
|
-
assertBasouRootSafe as
|
|
2421
|
-
basouPaths as
|
|
2498
|
+
assertBasouRootSafe as assertBasouRootSafe9,
|
|
2499
|
+
basouPaths as basouPaths9,
|
|
2422
2500
|
ChildProcessRunner as ChildProcessRunner2,
|
|
2423
2501
|
claudeCodeAdapterMetadata,
|
|
2424
2502
|
appendChainedEvent as coreAppendChainedEvent2,
|
|
@@ -2430,7 +2508,7 @@ import {
|
|
|
2430
2508
|
readManifest as readManifest4,
|
|
2431
2509
|
readYamlFile as readYamlFile3,
|
|
2432
2510
|
resolveClaudeCodeCommand,
|
|
2433
|
-
resolveRepositoryRoot as
|
|
2511
|
+
resolveRepositoryRoot as resolveRepositoryRoot10,
|
|
2434
2512
|
SessionSchema as SessionSchema2,
|
|
2435
2513
|
sanitizeRelatedFiles,
|
|
2436
2514
|
sanitizeWorkingDirectory as sanitizeWorkingDirectory2,
|
|
@@ -2463,8 +2541,8 @@ async function runClaudeCode(args, options, ctx = {}) {
|
|
|
2463
2541
|
const { command } = await resolveCommand();
|
|
2464
2542
|
const cwd = options.cwd ?? process.cwd();
|
|
2465
2543
|
const repoRoot = await resolveRepositoryRootForRun(cwd);
|
|
2466
|
-
const paths =
|
|
2467
|
-
await
|
|
2544
|
+
const paths = basouPaths9(repoRoot);
|
|
2545
|
+
await assertBasouRootSafe9(paths.root);
|
|
2468
2546
|
const manifest = await readManifest4(paths);
|
|
2469
2547
|
const sessionId = prefixedUlid4("ses");
|
|
2470
2548
|
const sessionDir = join5(paths.sessions, sessionId);
|
|
@@ -2803,7 +2881,7 @@ async function finalizeSessionAsFailed2(paths, sessionDir, sessionId, appendEven
|
|
|
2803
2881
|
}
|
|
2804
2882
|
async function resolveRepositoryRootForRun(cwd) {
|
|
2805
2883
|
try {
|
|
2806
|
-
return await
|
|
2884
|
+
return await resolveRepositoryRoot10(cwd);
|
|
2807
2885
|
} catch (error) {
|
|
2808
2886
|
if (error instanceof Error && error.message === "Not a git repository") {
|
|
2809
2887
|
throw new Error("Not a git repository. Run 'git init' first, then re-run 'basou run'.", {
|
|
@@ -2816,21 +2894,21 @@ async function resolveRepositoryRootForRun(cwd) {
|
|
|
2816
2894
|
|
|
2817
2895
|
// src/commands/session.ts
|
|
2818
2896
|
import { readFile as readFile2 } from "fs/promises";
|
|
2819
|
-
import { basename as basename3, isAbsolute, join as join6, relative as relative2 } from "path";
|
|
2897
|
+
import { basename as basename3, isAbsolute as isAbsolute2, join as join6, relative as relative2 } from "path";
|
|
2820
2898
|
import {
|
|
2821
2899
|
acquireLock as acquireLock5,
|
|
2822
2900
|
appendEventToExistingSession as appendEventToExistingSession2,
|
|
2823
|
-
assertBasouRootSafe as
|
|
2824
|
-
basouPaths as
|
|
2901
|
+
assertBasouRootSafe as assertBasouRootSafe10,
|
|
2902
|
+
basouPaths as basouPaths10,
|
|
2825
2903
|
enumerateSessionDirs as enumerateSessionDirs2,
|
|
2826
|
-
findErrorCode as
|
|
2904
|
+
findErrorCode as findErrorCode9,
|
|
2827
2905
|
importSessionFromJson as importSessionFromJson2,
|
|
2828
2906
|
loadSessionEntries,
|
|
2829
2907
|
readAllEvents,
|
|
2830
2908
|
readManifest as readManifest5,
|
|
2831
2909
|
readYamlFile as readYamlFile4,
|
|
2832
2910
|
rechainSessionInPlace,
|
|
2833
|
-
resolveRepositoryRoot as
|
|
2911
|
+
resolveRepositoryRoot as resolveRepositoryRoot11,
|
|
2834
2912
|
resolveSessionId as resolveSessionId2,
|
|
2835
2913
|
resolveTaskId,
|
|
2836
2914
|
SessionImportPayloadSchema as SessionImportPayloadSchema2,
|
|
@@ -2841,15 +2919,7 @@ import {
|
|
|
2841
2919
|
import { InvalidArgumentError as InvalidArgumentError3 } from "commander";
|
|
2842
2920
|
|
|
2843
2921
|
// src/lib/format-duration.ts
|
|
2844
|
-
|
|
2845
|
-
const totalSeconds = Math.round(ms / 1e3);
|
|
2846
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
2847
|
-
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
2848
|
-
const seconds = totalSeconds % 60;
|
|
2849
|
-
if (hours > 0) return `${hours}h ${String(minutes).padStart(2, "0")}m`;
|
|
2850
|
-
if (minutes > 0) return `${minutes}m ${String(seconds).padStart(2, "0")}s`;
|
|
2851
|
-
return `${seconds}s`;
|
|
2852
|
-
}
|
|
2922
|
+
import { formatDurationMs } from "@basou/core";
|
|
2853
2923
|
|
|
2854
2924
|
// src/commands/session.ts
|
|
2855
2925
|
var SES_PREFIX3 = "ses_";
|
|
@@ -2895,8 +2965,8 @@ async function runSessionList(options, ctx = {}) {
|
|
|
2895
2965
|
async function doRunSessionList(options, ctx) {
|
|
2896
2966
|
const cwd = ctx.cwd ?? process.cwd();
|
|
2897
2967
|
const repositoryRoot = await resolveRepositoryRootForSession(cwd, "list");
|
|
2898
|
-
const paths =
|
|
2899
|
-
await
|
|
2968
|
+
const paths = basouPaths10(repositoryRoot);
|
|
2969
|
+
await assertWorkspaceInitialized8(paths.root);
|
|
2900
2970
|
const now = /* @__PURE__ */ new Date();
|
|
2901
2971
|
const records = (await loadSessionEntries(paths, {
|
|
2902
2972
|
now,
|
|
@@ -2947,8 +3017,8 @@ async function runSessionShow(idInput, options, ctx = {}) {
|
|
|
2947
3017
|
async function doRunSessionShow(idInput, options, ctx) {
|
|
2948
3018
|
const cwd = ctx.cwd ?? process.cwd();
|
|
2949
3019
|
const repositoryRoot = await resolveRepositoryRootForSession(cwd, "show");
|
|
2950
|
-
const paths =
|
|
2951
|
-
await
|
|
3020
|
+
const paths = basouPaths10(repositoryRoot);
|
|
3021
|
+
await assertWorkspaceInitialized8(paths.root);
|
|
2952
3022
|
const sessionId = await resolveSessionId2(paths, idInput);
|
|
2953
3023
|
const sessionDir = join6(paths.sessions, sessionId);
|
|
2954
3024
|
const sessionYamlPath = join6(sessionDir, "session.yaml");
|
|
@@ -2957,7 +3027,7 @@ async function doRunSessionShow(idInput, options, ctx) {
|
|
|
2957
3027
|
const raw = await readYamlFile4(sessionYamlPath);
|
|
2958
3028
|
session = SessionSchema3.parse(raw);
|
|
2959
3029
|
} catch (error) {
|
|
2960
|
-
if (
|
|
3030
|
+
if (findErrorCode9(error, "ENOENT")) {
|
|
2961
3031
|
throw new Error(`Session not found: ${idInput}`);
|
|
2962
3032
|
}
|
|
2963
3033
|
throw new Error("Failed to read session", { cause: error });
|
|
@@ -3072,7 +3142,7 @@ function formatSessionWork(session, events, now) {
|
|
|
3072
3142
|
}
|
|
3073
3143
|
function formatWorkingDir(workingDir, repositoryRoot, options) {
|
|
3074
3144
|
if (options.fullPath === true) return workingDir;
|
|
3075
|
-
if (!
|
|
3145
|
+
if (!isAbsolute2(workingDir)) {
|
|
3076
3146
|
if (workingDir === ".") return "<repository_root>";
|
|
3077
3147
|
return workingDir;
|
|
3078
3148
|
}
|
|
@@ -3192,7 +3262,7 @@ function maxLen2(values, floor) {
|
|
|
3192
3262
|
}
|
|
3193
3263
|
async function resolveRepositoryRootForSession(cwd, subcmd) {
|
|
3194
3264
|
try {
|
|
3195
|
-
return await
|
|
3265
|
+
return await resolveRepositoryRoot11(cwd);
|
|
3196
3266
|
} catch (error) {
|
|
3197
3267
|
if (error instanceof Error && error.message === "Not a git repository") {
|
|
3198
3268
|
throw new Error(
|
|
@@ -3203,11 +3273,11 @@ async function resolveRepositoryRootForSession(cwd, subcmd) {
|
|
|
3203
3273
|
throw error;
|
|
3204
3274
|
}
|
|
3205
3275
|
}
|
|
3206
|
-
async function
|
|
3276
|
+
async function assertWorkspaceInitialized8(basouRoot) {
|
|
3207
3277
|
try {
|
|
3208
|
-
await
|
|
3278
|
+
await assertBasouRootSafe10(basouRoot);
|
|
3209
3279
|
} catch (error) {
|
|
3210
|
-
if (
|
|
3280
|
+
if (findErrorCode9(error, "ENOENT")) {
|
|
3211
3281
|
throw new Error("Workspace not initialized. Run 'basou init' first.");
|
|
3212
3282
|
}
|
|
3213
3283
|
throw error;
|
|
@@ -3245,8 +3315,8 @@ async function runSessionImport(options, ctx = {}) {
|
|
|
3245
3315
|
async function doRunSessionImport(options, ctx) {
|
|
3246
3316
|
const cwd = ctx.cwd ?? process.cwd();
|
|
3247
3317
|
const repositoryRoot = await resolveRepositoryRootForSession(cwd, "import");
|
|
3248
|
-
const paths =
|
|
3249
|
-
await
|
|
3318
|
+
const paths = basouPaths10(repositoryRoot);
|
|
3319
|
+
await assertWorkspaceInitialized8(paths.root);
|
|
3250
3320
|
const manifest = await readManifest5(paths);
|
|
3251
3321
|
const rawBody = await readInputFile(options.from);
|
|
3252
3322
|
const json = parseJsonStrict(rawBody);
|
|
@@ -3276,10 +3346,10 @@ async function readInputFile(path) {
|
|
|
3276
3346
|
try {
|
|
3277
3347
|
return await readFile2(path, "utf8");
|
|
3278
3348
|
} catch (error) {
|
|
3279
|
-
if (
|
|
3349
|
+
if (findErrorCode9(error, "ENOENT")) {
|
|
3280
3350
|
throw new Error("Import source not found", { cause: error });
|
|
3281
3351
|
}
|
|
3282
|
-
if (
|
|
3352
|
+
if (findErrorCode9(error, "EISDIR")) {
|
|
3283
3353
|
throw new Error("Import source is not a file", { cause: error });
|
|
3284
3354
|
}
|
|
3285
3355
|
throw new Error("Failed to read import source", { cause: error });
|
|
@@ -3359,8 +3429,8 @@ async function doRunSessionNote(sessionIdInput, options, ctx) {
|
|
|
3359
3429
|
}
|
|
3360
3430
|
const cwd = ctx.cwd ?? process.cwd();
|
|
3361
3431
|
const repositoryRoot = await resolveRepositoryRootForSession(cwd, "note");
|
|
3362
|
-
const paths =
|
|
3363
|
-
await
|
|
3432
|
+
const paths = basouPaths10(repositoryRoot);
|
|
3433
|
+
await assertWorkspaceInitialized8(paths.root);
|
|
3364
3434
|
const sessionId = await resolveSessionId2(paths, sessionIdInput);
|
|
3365
3435
|
const body = hasBody ? options.body : await readNoteFile(options.fromFile);
|
|
3366
3436
|
if (body.length === 0) {
|
|
@@ -3393,10 +3463,10 @@ async function readNoteFile(path) {
|
|
|
3393
3463
|
try {
|
|
3394
3464
|
return await readFile2(path, "utf8");
|
|
3395
3465
|
} catch (error) {
|
|
3396
|
-
if (
|
|
3466
|
+
if (findErrorCode9(error, "ENOENT")) {
|
|
3397
3467
|
throw new Error("Note source not found", { cause: error });
|
|
3398
3468
|
}
|
|
3399
|
-
if (
|
|
3469
|
+
if (findErrorCode9(error, "EISDIR")) {
|
|
3400
3470
|
throw new Error("Note source is not a file", { cause: error });
|
|
3401
3471
|
}
|
|
3402
3472
|
throw new Error("Failed to read note source", { cause: error });
|
|
@@ -3441,8 +3511,8 @@ async function doRunSessionRechain(options, ctx) {
|
|
|
3441
3511
|
}
|
|
3442
3512
|
const cwd = ctx.cwd ?? process.cwd();
|
|
3443
3513
|
const repositoryRoot = await resolveRepositoryRootForSession(cwd, "rechain");
|
|
3444
|
-
const paths =
|
|
3445
|
-
await
|
|
3514
|
+
const paths = basouPaths10(repositoryRoot);
|
|
3515
|
+
await assertWorkspaceInitialized8(paths.root);
|
|
3446
3516
|
const sessionIds = options.session !== void 0 ? [await resolveSessionId2(paths, options.session)] : await enumerateSessionDirs2(paths);
|
|
3447
3517
|
const dryRun = options.dryRun === true;
|
|
3448
3518
|
const rows = [];
|
|
@@ -3495,11 +3565,11 @@ function renderRechainRow(row, dryRun) {
|
|
|
3495
3565
|
|
|
3496
3566
|
// src/commands/stats.ts
|
|
3497
3567
|
import {
|
|
3498
|
-
assertBasouRootSafe as
|
|
3499
|
-
basouPaths as
|
|
3568
|
+
assertBasouRootSafe as assertBasouRootSafe11,
|
|
3569
|
+
basouPaths as basouPaths11,
|
|
3500
3570
|
computeWorkStats,
|
|
3501
|
-
findErrorCode as
|
|
3502
|
-
resolveRepositoryRoot as
|
|
3571
|
+
findErrorCode as findErrorCode10,
|
|
3572
|
+
resolveRepositoryRoot as resolveRepositoryRoot12
|
|
3503
3573
|
} from "@basou/core";
|
|
3504
3574
|
function registerStatsCommand(program2) {
|
|
3505
3575
|
program2.command("stats").description("Report how much the AI worked (output volume + time proxies) across sessions").option("--by-source", "Break the totals down by session source kind").option("--by-day", "Break billable time and volume down by calendar day").option("--json", "Output the full stats as JSON").option("-v, --verbose", "Show error causes").action(async (options) => {
|
|
@@ -3517,8 +3587,8 @@ async function runStats(options, ctx = {}) {
|
|
|
3517
3587
|
async function doRunStats(options, ctx) {
|
|
3518
3588
|
const cwd = ctx.cwd ?? process.cwd();
|
|
3519
3589
|
const repositoryRoot = await resolveRepositoryRootForStats(cwd);
|
|
3520
|
-
const paths =
|
|
3521
|
-
await
|
|
3590
|
+
const paths = basouPaths11(repositoryRoot);
|
|
3591
|
+
await assertWorkspaceInitialized9(paths.root);
|
|
3522
3592
|
const now = ctx.nowProvider?.() ?? /* @__PURE__ */ new Date();
|
|
3523
3593
|
const result = await computeWorkStats({
|
|
3524
3594
|
paths,
|
|
@@ -3602,7 +3672,7 @@ function formatInt(n) {
|
|
|
3602
3672
|
}
|
|
3603
3673
|
async function resolveRepositoryRootForStats(cwd) {
|
|
3604
3674
|
try {
|
|
3605
|
-
return await
|
|
3675
|
+
return await resolveRepositoryRoot12(cwd);
|
|
3606
3676
|
} catch (error) {
|
|
3607
3677
|
if (error instanceof Error && error.message === "Not a git repository") {
|
|
3608
3678
|
throw new Error("Not a git repository. Run 'git init' first, then re-run 'basou stats'.", {
|
|
@@ -3612,11 +3682,11 @@ async function resolveRepositoryRootForStats(cwd) {
|
|
|
3612
3682
|
throw error;
|
|
3613
3683
|
}
|
|
3614
3684
|
}
|
|
3615
|
-
async function
|
|
3685
|
+
async function assertWorkspaceInitialized9(basouRoot) {
|
|
3616
3686
|
try {
|
|
3617
|
-
await
|
|
3687
|
+
await assertBasouRootSafe11(basouRoot);
|
|
3618
3688
|
} catch (error) {
|
|
3619
|
-
if (
|
|
3689
|
+
if (findErrorCode10(error, "ENOENT")) {
|
|
3620
3690
|
throw new Error("Workspace not initialized. Run 'basou init' first.");
|
|
3621
3691
|
}
|
|
3622
3692
|
throw error;
|
|
@@ -3625,12 +3695,12 @@ async function assertWorkspaceInitialized8(basouRoot) {
|
|
|
3625
3695
|
|
|
3626
3696
|
// src/commands/status.ts
|
|
3627
3697
|
import {
|
|
3628
|
-
assertBasouRootSafe as
|
|
3629
|
-
basouPaths as
|
|
3698
|
+
assertBasouRootSafe as assertBasouRootSafe12,
|
|
3699
|
+
basouPaths as basouPaths12,
|
|
3630
3700
|
buildStatusSnapshot,
|
|
3631
|
-
findErrorCode as
|
|
3701
|
+
findErrorCode as findErrorCode11,
|
|
3632
3702
|
readManifest as readManifest6,
|
|
3633
|
-
resolveRepositoryRoot as
|
|
3703
|
+
resolveRepositoryRoot as resolveRepositoryRoot13,
|
|
3634
3704
|
writeStatus
|
|
3635
3705
|
} from "@basou/core";
|
|
3636
3706
|
function registerStatusCommand(program2) {
|
|
@@ -3649,11 +3719,11 @@ async function runStatus(options, ctx = {}) {
|
|
|
3649
3719
|
async function doRunStatus(options, ctx) {
|
|
3650
3720
|
const cwd = ctx.cwd ?? process.cwd();
|
|
3651
3721
|
const repositoryRoot = await resolveRepositoryRootForStatus(cwd);
|
|
3652
|
-
const paths =
|
|
3722
|
+
const paths = basouPaths12(repositoryRoot);
|
|
3653
3723
|
try {
|
|
3654
|
-
await
|
|
3724
|
+
await assertBasouRootSafe12(paths.root);
|
|
3655
3725
|
} catch (error) {
|
|
3656
|
-
if (
|
|
3726
|
+
if (findErrorCode11(error, "ENOENT")) {
|
|
3657
3727
|
throw new Error("Workspace not initialized. Run 'basou init' first.");
|
|
3658
3728
|
}
|
|
3659
3729
|
throw error;
|
|
@@ -3662,7 +3732,7 @@ async function doRunStatus(options, ctx) {
|
|
|
3662
3732
|
try {
|
|
3663
3733
|
manifest = await readManifest6(paths);
|
|
3664
3734
|
} catch (error) {
|
|
3665
|
-
if (
|
|
3735
|
+
if (findErrorCode11(error, "ENOENT")) {
|
|
3666
3736
|
throw new Error("Workspace not initialized. Run 'basou init' first.");
|
|
3667
3737
|
}
|
|
3668
3738
|
throw new Error("Failed to read workspace manifest", { cause: error });
|
|
@@ -3686,7 +3756,7 @@ function renderTextStatus(s) {
|
|
|
3686
3756
|
}
|
|
3687
3757
|
async function resolveRepositoryRootForStatus(cwd) {
|
|
3688
3758
|
try {
|
|
3689
|
-
return await
|
|
3759
|
+
return await resolveRepositoryRoot13(cwd);
|
|
3690
3760
|
} catch (error) {
|
|
3691
3761
|
if (error instanceof Error && error.message === "Not a git repository") {
|
|
3692
3762
|
throw new Error("Not a git repository. Run 'git init' first, then re-run 'basou status'.", {
|
|
@@ -3702,13 +3772,13 @@ import { readFile as readFile3 } from "fs/promises";
|
|
|
3702
3772
|
import { join as join7 } from "path";
|
|
3703
3773
|
import {
|
|
3704
3774
|
archiveTask,
|
|
3705
|
-
assertBasouRootSafe as
|
|
3706
|
-
basouPaths as
|
|
3775
|
+
assertBasouRootSafe as assertBasouRootSafe13,
|
|
3776
|
+
basouPaths as basouPaths13,
|
|
3707
3777
|
createTaskWithEvent,
|
|
3708
3778
|
deleteTask,
|
|
3709
3779
|
editTask,
|
|
3710
3780
|
enumerateArchivedTaskIds,
|
|
3711
|
-
findErrorCode as
|
|
3781
|
+
findErrorCode as findErrorCode12,
|
|
3712
3782
|
loadSessionEntries as loadSessionEntries2,
|
|
3713
3783
|
loadTaskEntries,
|
|
3714
3784
|
prefixedUlid as prefixedUlid5,
|
|
@@ -3719,7 +3789,7 @@ import {
|
|
|
3719
3789
|
reconcileTask,
|
|
3720
3790
|
refreshTaskLinkedSessions,
|
|
3721
3791
|
replayEvents as replayEvents2,
|
|
3722
|
-
resolveRepositoryRoot as
|
|
3792
|
+
resolveRepositoryRoot as resolveRepositoryRoot14,
|
|
3723
3793
|
resolveSessionId as resolveSessionId3,
|
|
3724
3794
|
resolveTaskId as resolveTaskId2,
|
|
3725
3795
|
TaskStatusSchema,
|
|
@@ -3805,8 +3875,8 @@ async function doRunTaskNew(options, ctx) {
|
|
|
3805
3875
|
}
|
|
3806
3876
|
const cwd = ctx.cwd ?? process.cwd();
|
|
3807
3877
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "new");
|
|
3808
|
-
const paths =
|
|
3809
|
-
await
|
|
3878
|
+
const paths = basouPaths13(repositoryRoot);
|
|
3879
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
3810
3880
|
const description = options.description !== void 0 ? options.description : options.fromFile !== void 0 ? await readDescriptionFile(options.fromFile) : "";
|
|
3811
3881
|
const now = ctx.nowProvider !== void 0 ? ctx.nowProvider() : /* @__PURE__ */ new Date();
|
|
3812
3882
|
const occurredAt = now.toISOString();
|
|
@@ -3914,8 +3984,8 @@ async function runTaskList(options, ctx = {}) {
|
|
|
3914
3984
|
async function doRunTaskList(options, ctx) {
|
|
3915
3985
|
const cwd = ctx.cwd ?? process.cwd();
|
|
3916
3986
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "list");
|
|
3917
|
-
const paths =
|
|
3918
|
-
await
|
|
3987
|
+
const paths = basouPaths13(repositoryRoot);
|
|
3988
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
3919
3989
|
const entries = await loadTaskEntries(paths, {
|
|
3920
3990
|
onSkip: (id, reason) => printTaskSkip(id, reason)
|
|
3921
3991
|
});
|
|
@@ -4018,8 +4088,8 @@ async function runTaskShow(idInput, options, ctx = {}) {
|
|
|
4018
4088
|
async function doRunTaskShow(idInput, options, ctx) {
|
|
4019
4089
|
const cwd = ctx.cwd ?? process.cwd();
|
|
4020
4090
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "show");
|
|
4021
|
-
const paths =
|
|
4022
|
-
await
|
|
4091
|
+
const paths = basouPaths13(repositoryRoot);
|
|
4092
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
4023
4093
|
const taskId = await resolveTaskId2(paths, idInput, { includeArchived: true });
|
|
4024
4094
|
const { doc, archived } = await readTaskFileWithArchiveFallback(paths, taskId);
|
|
4025
4095
|
const sessions = await loadSessionEntries2(paths, { now: /* @__PURE__ */ new Date() });
|
|
@@ -4162,8 +4232,8 @@ async function doRunTaskStatus(taskIdInput, newStatusInput, options, ctx) {
|
|
|
4162
4232
|
const newStatus = parseTaskStatusPositional(newStatusInput);
|
|
4163
4233
|
const cwd = ctx.cwd ?? process.cwd();
|
|
4164
4234
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "status");
|
|
4165
|
-
const paths =
|
|
4166
|
-
await
|
|
4235
|
+
const paths = basouPaths13(repositoryRoot);
|
|
4236
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
4167
4237
|
const taskId = await resolveTaskId2(paths, taskIdInput);
|
|
4168
4238
|
const now = ctx.nowProvider !== void 0 ? ctx.nowProvider() : /* @__PURE__ */ new Date();
|
|
4169
4239
|
const occurredAt = now.toISOString();
|
|
@@ -4239,8 +4309,8 @@ async function runTaskReconcile(options, ctx = {}) {
|
|
|
4239
4309
|
async function doRunTaskReconcile(options, ctx) {
|
|
4240
4310
|
const cwd = ctx.cwd ?? process.cwd();
|
|
4241
4311
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "reconcile");
|
|
4242
|
-
const paths =
|
|
4243
|
-
await
|
|
4312
|
+
const paths = basouPaths13(repositoryRoot);
|
|
4313
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
4244
4314
|
const manifest = await readManifest7(paths);
|
|
4245
4315
|
const nowProvider = ctx.nowProvider ?? (() => /* @__PURE__ */ new Date());
|
|
4246
4316
|
const write = options.write === true;
|
|
@@ -4419,8 +4489,8 @@ async function doRunTaskRefreshLinkage(taskIdInput, options, ctx) {
|
|
|
4419
4489
|
}
|
|
4420
4490
|
const cwd = ctx.cwd ?? process.cwd();
|
|
4421
4491
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "refresh-linkage");
|
|
4422
|
-
const paths =
|
|
4423
|
-
await
|
|
4492
|
+
const paths = basouPaths13(repositoryRoot);
|
|
4493
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
4424
4494
|
const manifest = await readManifest7(paths);
|
|
4425
4495
|
const taskId = await resolveTaskId2(paths, taskIdInput);
|
|
4426
4496
|
const nowProvider = ctx.nowProvider ?? (() => /* @__PURE__ */ new Date());
|
|
@@ -4499,8 +4569,8 @@ async function doRunTaskEdit(taskIdInput, options, ctx) {
|
|
|
4499
4569
|
}
|
|
4500
4570
|
const cwd = ctx.cwd ?? process.cwd();
|
|
4501
4571
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "edit");
|
|
4502
|
-
const paths =
|
|
4503
|
-
await
|
|
4572
|
+
const paths = basouPaths13(repositoryRoot);
|
|
4573
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
4504
4574
|
const manifest = await readManifest7(paths);
|
|
4505
4575
|
const taskId = await resolveTaskId2(paths, taskIdInput);
|
|
4506
4576
|
const now = ctx.nowProvider !== void 0 ? ctx.nowProvider() : /* @__PURE__ */ new Date();
|
|
@@ -4555,8 +4625,8 @@ async function doRunTaskDelete(taskIdInput, options, ctx) {
|
|
|
4555
4625
|
}
|
|
4556
4626
|
const cwd = ctx.cwd ?? process.cwd();
|
|
4557
4627
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "delete");
|
|
4558
|
-
const paths =
|
|
4559
|
-
await
|
|
4628
|
+
const paths = basouPaths13(repositoryRoot);
|
|
4629
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
4560
4630
|
const manifest = await readManifest7(paths);
|
|
4561
4631
|
const taskId = await resolveTaskId2(paths, taskIdInput);
|
|
4562
4632
|
if (options.yes !== true) {
|
|
@@ -4600,8 +4670,8 @@ async function doRunTaskArchive(taskIdInput, options, ctx) {
|
|
|
4600
4670
|
}
|
|
4601
4671
|
const cwd = ctx.cwd ?? process.cwd();
|
|
4602
4672
|
const repositoryRoot = await resolveRepositoryRootForTask(cwd, "archive");
|
|
4603
|
-
const paths =
|
|
4604
|
-
await
|
|
4673
|
+
const paths = basouPaths13(repositoryRoot);
|
|
4674
|
+
await assertWorkspaceInitialized10(paths.root);
|
|
4605
4675
|
const manifest = await readManifest7(paths);
|
|
4606
4676
|
const taskId = await resolveTaskId2(paths, taskIdInput);
|
|
4607
4677
|
if (options.yes !== true) {
|
|
@@ -4716,10 +4786,10 @@ async function readDescriptionFile(path) {
|
|
|
4716
4786
|
try {
|
|
4717
4787
|
return await readFile3(path, "utf8");
|
|
4718
4788
|
} catch (error) {
|
|
4719
|
-
if (
|
|
4789
|
+
if (findErrorCode12(error, "ENOENT")) {
|
|
4720
4790
|
throw new Error("Description source not found", { cause: error });
|
|
4721
4791
|
}
|
|
4722
|
-
if (
|
|
4792
|
+
if (findErrorCode12(error, "EISDIR")) {
|
|
4723
4793
|
throw new Error("Description source is not a file", { cause: error });
|
|
4724
4794
|
}
|
|
4725
4795
|
throw new Error("Failed to read description source", { cause: error });
|
|
@@ -4727,7 +4797,7 @@ async function readDescriptionFile(path) {
|
|
|
4727
4797
|
}
|
|
4728
4798
|
async function resolveRepositoryRootForTask(cwd, subcmd) {
|
|
4729
4799
|
try {
|
|
4730
|
-
return await
|
|
4800
|
+
return await resolveRepositoryRoot14(cwd);
|
|
4731
4801
|
} catch (error) {
|
|
4732
4802
|
if (error instanceof Error && error.message === "Not a git repository") {
|
|
4733
4803
|
throw new Error(
|
|
@@ -4738,11 +4808,11 @@ async function resolveRepositoryRootForTask(cwd, subcmd) {
|
|
|
4738
4808
|
throw error;
|
|
4739
4809
|
}
|
|
4740
4810
|
}
|
|
4741
|
-
async function
|
|
4811
|
+
async function assertWorkspaceInitialized10(basouRoot) {
|
|
4742
4812
|
try {
|
|
4743
|
-
await
|
|
4813
|
+
await assertBasouRootSafe13(basouRoot);
|
|
4744
4814
|
} catch (error) {
|
|
4745
|
-
if (
|
|
4815
|
+
if (findErrorCode12(error, "ENOENT")) {
|
|
4746
4816
|
throw new Error("Workspace not initialized. Run 'basou init' first.");
|
|
4747
4817
|
}
|
|
4748
4818
|
throw error;
|
|
@@ -4830,11 +4900,11 @@ function maxLen3(values, floor) {
|
|
|
4830
4900
|
|
|
4831
4901
|
// src/commands/verify.ts
|
|
4832
4902
|
import {
|
|
4833
|
-
assertBasouRootSafe as
|
|
4834
|
-
basouPaths as
|
|
4903
|
+
assertBasouRootSafe as assertBasouRootSafe14,
|
|
4904
|
+
basouPaths as basouPaths14,
|
|
4835
4905
|
enumerateSessionDirs as enumerateSessionDirs3,
|
|
4836
|
-
findErrorCode as
|
|
4837
|
-
resolveRepositoryRoot as
|
|
4906
|
+
findErrorCode as findErrorCode13,
|
|
4907
|
+
resolveRepositoryRoot as resolveRepositoryRoot15,
|
|
4838
4908
|
resolveSessionId as resolveSessionId4,
|
|
4839
4909
|
verifyEventsChain
|
|
4840
4910
|
} from "@basou/core";
|
|
@@ -4857,8 +4927,8 @@ async function doRunVerify(options, ctx) {
|
|
|
4857
4927
|
}
|
|
4858
4928
|
const cwd = ctx.cwd ?? process.cwd();
|
|
4859
4929
|
const repositoryRoot = await resolveRepositoryRootForVerify(cwd);
|
|
4860
|
-
const paths =
|
|
4861
|
-
await
|
|
4930
|
+
const paths = basouPaths14(repositoryRoot);
|
|
4931
|
+
await assertWorkspaceInitialized11(paths.root);
|
|
4862
4932
|
const sessionIds = options.session !== void 0 ? [await resolveSessionId4(paths, options.session)] : await enumerateSessionDirs3(paths);
|
|
4863
4933
|
const rows = [];
|
|
4864
4934
|
for (const sessionId of sessionIds) {
|
|
@@ -4905,7 +4975,7 @@ function renderVerdict(row) {
|
|
|
4905
4975
|
}
|
|
4906
4976
|
async function resolveRepositoryRootForVerify(cwd) {
|
|
4907
4977
|
try {
|
|
4908
|
-
return await
|
|
4978
|
+
return await resolveRepositoryRoot15(cwd);
|
|
4909
4979
|
} catch (error) {
|
|
4910
4980
|
if (error instanceof Error && error.message === "Not a git repository") {
|
|
4911
4981
|
throw new Error("Not a git repository. Run 'git init' first, then re-run 'basou verify'.", {
|
|
@@ -4915,11 +4985,11 @@ async function resolveRepositoryRootForVerify(cwd) {
|
|
|
4915
4985
|
throw error;
|
|
4916
4986
|
}
|
|
4917
4987
|
}
|
|
4918
|
-
async function
|
|
4988
|
+
async function assertWorkspaceInitialized11(basouRoot) {
|
|
4919
4989
|
try {
|
|
4920
|
-
await
|
|
4990
|
+
await assertBasouRootSafe14(basouRoot);
|
|
4921
4991
|
} catch (error) {
|
|
4922
|
-
if (
|
|
4992
|
+
if (findErrorCode13(error, "ENOENT")) {
|
|
4923
4993
|
throw new Error("Workspace not initialized. Run 'basou init' first.");
|
|
4924
4994
|
}
|
|
4925
4995
|
throw error;
|
|
@@ -4928,7 +4998,7 @@ async function assertWorkspaceInitialized10(basouRoot) {
|
|
|
4928
4998
|
|
|
4929
4999
|
// src/commands/view.ts
|
|
4930
5000
|
import { spawn } from "child_process";
|
|
4931
|
-
import { assertBasouRootSafe as
|
|
5001
|
+
import { assertBasouRootSafe as assertBasouRootSafe15, basouPaths as basouPaths15, findErrorCode as findErrorCode15, resolveRepositoryRoot as resolveRepositoryRoot16 } from "@basou/core";
|
|
4932
5002
|
import { InvalidArgumentError as InvalidArgumentError5 } from "commander";
|
|
4933
5003
|
|
|
4934
5004
|
// src/lib/view-server.ts
|
|
@@ -4937,7 +5007,7 @@ import { join as join8 } from "path";
|
|
|
4937
5007
|
import {
|
|
4938
5008
|
computeWorkStats as computeWorkStats2,
|
|
4939
5009
|
enumerateApprovals as enumerateApprovals2,
|
|
4940
|
-
findErrorCode as
|
|
5010
|
+
findErrorCode as findErrorCode14,
|
|
4941
5011
|
isLazyExpired as isLazyExpired2,
|
|
4942
5012
|
loadApproval as loadApproval2,
|
|
4943
5013
|
loadSessionEntries as loadSessionEntries3,
|
|
@@ -5410,7 +5480,7 @@ function startViewServer(opts) {
|
|
|
5410
5480
|
};
|
|
5411
5481
|
let boundPort = port;
|
|
5412
5482
|
const getPort = () => boundPort;
|
|
5413
|
-
return new Promise((
|
|
5483
|
+
return new Promise((resolve4, reject) => {
|
|
5414
5484
|
const server = createServer((req, res) => {
|
|
5415
5485
|
handleRequest(req, res, deps, getPort, runExclusive).catch((error) => {
|
|
5416
5486
|
sendError(res, error instanceof HttpError ? error.status : 500, pathlessMessage(error));
|
|
@@ -5421,7 +5491,7 @@ function startViewServer(opts) {
|
|
|
5421
5491
|
const address = server.address();
|
|
5422
5492
|
boundPort = isAddressInfo(address) ? address.port : port;
|
|
5423
5493
|
server.off("error", reject);
|
|
5424
|
-
|
|
5494
|
+
resolve4({
|
|
5425
5495
|
url: `http://${host}:${boundPort}`,
|
|
5426
5496
|
port: boundPort,
|
|
5427
5497
|
close: () => closeServer(server)
|
|
@@ -5433,8 +5503,8 @@ function isAddressInfo(value) {
|
|
|
5433
5503
|
return value !== null && typeof value === "object";
|
|
5434
5504
|
}
|
|
5435
5505
|
function closeServer(server) {
|
|
5436
|
-
return new Promise((
|
|
5437
|
-
server.close(() =>
|
|
5506
|
+
return new Promise((resolve4) => {
|
|
5507
|
+
server.close(() => resolve4());
|
|
5438
5508
|
server.closeAllConnections();
|
|
5439
5509
|
});
|
|
5440
5510
|
}
|
|
@@ -5539,7 +5609,7 @@ async function overview(deps) {
|
|
|
5539
5609
|
try {
|
|
5540
5610
|
manifest = await readManifest8(deps.paths);
|
|
5541
5611
|
} catch (error) {
|
|
5542
|
-
if (
|
|
5612
|
+
if (findErrorCode14(error, "ENOENT")) {
|
|
5543
5613
|
return { initialized: false, repoRoot: deps.repoRoot };
|
|
5544
5614
|
}
|
|
5545
5615
|
throw error;
|
|
@@ -5754,8 +5824,8 @@ async function runView(options, ctx = {}) {
|
|
|
5754
5824
|
async function doRunView(options, ctx) {
|
|
5755
5825
|
const cwd = ctx.cwd ?? process.cwd();
|
|
5756
5826
|
const repositoryRoot = await resolveRepositoryRootForView(cwd);
|
|
5757
|
-
const paths =
|
|
5758
|
-
await
|
|
5827
|
+
const paths = basouPaths15(repositoryRoot);
|
|
5828
|
+
await assertWorkspaceInitialized12(paths.root);
|
|
5759
5829
|
const deps = {
|
|
5760
5830
|
paths,
|
|
5761
5831
|
repoRoot: repositoryRoot,
|
|
@@ -5786,7 +5856,7 @@ async function startListening(port, deps) {
|
|
|
5786
5856
|
try {
|
|
5787
5857
|
return await startViewServer({ port, deps });
|
|
5788
5858
|
} catch (error) {
|
|
5789
|
-
if (
|
|
5859
|
+
if (findErrorCode15(error, "EADDRINUSE")) {
|
|
5790
5860
|
throw new Error(`Port ${port} is already in use. Pass --port <n> to choose another.`, {
|
|
5791
5861
|
cause: error
|
|
5792
5862
|
});
|
|
@@ -5809,7 +5879,7 @@ function openInBrowser(url, override) {
|
|
|
5809
5879
|
}
|
|
5810
5880
|
}
|
|
5811
5881
|
function waitForShutdown(signal) {
|
|
5812
|
-
return new Promise((
|
|
5882
|
+
return new Promise((resolve4) => {
|
|
5813
5883
|
const cleanup = () => {
|
|
5814
5884
|
process.off("SIGINT", onSignal);
|
|
5815
5885
|
process.off("SIGTERM", onSignal);
|
|
@@ -5817,18 +5887,18 @@ function waitForShutdown(signal) {
|
|
|
5817
5887
|
};
|
|
5818
5888
|
const onSignal = () => {
|
|
5819
5889
|
cleanup();
|
|
5820
|
-
|
|
5890
|
+
resolve4();
|
|
5821
5891
|
};
|
|
5822
5892
|
const onAbort = () => {
|
|
5823
5893
|
cleanup();
|
|
5824
|
-
|
|
5894
|
+
resolve4();
|
|
5825
5895
|
};
|
|
5826
5896
|
process.on("SIGINT", onSignal);
|
|
5827
5897
|
process.on("SIGTERM", onSignal);
|
|
5828
5898
|
if (signal !== void 0) {
|
|
5829
5899
|
if (signal.aborted) {
|
|
5830
5900
|
cleanup();
|
|
5831
|
-
|
|
5901
|
+
resolve4();
|
|
5832
5902
|
return;
|
|
5833
5903
|
}
|
|
5834
5904
|
signal.addEventListener("abort", onAbort);
|
|
@@ -5837,7 +5907,7 @@ function waitForShutdown(signal) {
|
|
|
5837
5907
|
}
|
|
5838
5908
|
async function resolveRepositoryRootForView(cwd) {
|
|
5839
5909
|
try {
|
|
5840
|
-
return await
|
|
5910
|
+
return await resolveRepositoryRoot16(cwd);
|
|
5841
5911
|
} catch (error) {
|
|
5842
5912
|
if (error instanceof Error && error.message === "Not a git repository") {
|
|
5843
5913
|
throw new Error("Not a git repository. Run 'git init' first, then re-run 'basou view'.", {
|
|
@@ -5847,11 +5917,11 @@ async function resolveRepositoryRootForView(cwd) {
|
|
|
5847
5917
|
throw error;
|
|
5848
5918
|
}
|
|
5849
5919
|
}
|
|
5850
|
-
async function
|
|
5920
|
+
async function assertWorkspaceInitialized12(basouRoot) {
|
|
5851
5921
|
try {
|
|
5852
|
-
await
|
|
5922
|
+
await assertBasouRootSafe15(basouRoot);
|
|
5853
5923
|
} catch (error) {
|
|
5854
|
-
if (
|
|
5924
|
+
if (findErrorCode15(error, "ENOENT")) {
|
|
5855
5925
|
throw new Error("Workspace not initialized. Run 'basou init' first.");
|
|
5856
5926
|
}
|
|
5857
5927
|
throw error;
|
|
@@ -5880,6 +5950,7 @@ function buildProgram() {
|
|
|
5880
5950
|
registerTaskCommand(program2);
|
|
5881
5951
|
registerHandoffCommand(program2);
|
|
5882
5952
|
registerDecisionsCommand(program2);
|
|
5953
|
+
registerReportCommand(program2);
|
|
5883
5954
|
return program2;
|
|
5884
5955
|
}
|
|
5885
5956
|
|