@sechroom/cli 2026.7.9 → 2026.7.11
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 +287 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { readFileSync as
|
|
4
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
|
|
7
7
|
// src/auth.ts
|
|
@@ -633,7 +633,22 @@ async function runApi(label, fn) {
|
|
|
633
633
|
return res.data;
|
|
634
634
|
}
|
|
635
635
|
function fail(error) {
|
|
636
|
-
|
|
636
|
+
let msg;
|
|
637
|
+
if (typeof error === "object" && error !== null && "title" in error) {
|
|
638
|
+
const problem = error;
|
|
639
|
+
msg = String(problem.title);
|
|
640
|
+
if (problem.errors && typeof problem.errors === "object") {
|
|
641
|
+
const detail = Object.entries(problem.errors).flatMap(
|
|
642
|
+
([field, msgs]) => (Array.isArray(msgs) ? msgs : [msgs]).map((m) => ` ${field}: ${String(m)}`)
|
|
643
|
+
);
|
|
644
|
+
if (detail.length > 0) msg += `
|
|
645
|
+
${detail.join("\n")}`;
|
|
646
|
+
}
|
|
647
|
+
} else if (typeof error === "object" && error !== null) {
|
|
648
|
+
msg = JSON.stringify(error);
|
|
649
|
+
} else {
|
|
650
|
+
msg = String(error);
|
|
651
|
+
}
|
|
637
652
|
process.stderr.write(`error: ${msg}
|
|
638
653
|
`);
|
|
639
654
|
process.exit(1);
|
|
@@ -2533,6 +2548,149 @@ Examples:
|
|
|
2533
2548
|
});
|
|
2534
2549
|
}
|
|
2535
2550
|
|
|
2551
|
+
// src/commands/close.ts
|
|
2552
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
2553
|
+
var VERDICTS = ["pass", "soft-fail", "plan-invalid", "blocked"];
|
|
2554
|
+
function registerClose(program2) {
|
|
2555
|
+
program2.command("close").description(
|
|
2556
|
+
"Close a dispatched WorkTask in one call: closeout memo (verdict + correlation) + Reference edge + source status flip. Managed runs stamp the run's matchTags verbatim (SBC-1180)."
|
|
2557
|
+
).requiredOption("--task <id>", "The WorkTask memory id being closed").requiredOption("--verdict <verdict>", `Verdict: ${VERDICTS.join(" | ")}`).requiredOption(
|
|
2558
|
+
"--workspace <wsp>",
|
|
2559
|
+
"Workspace that owns the closeout memo"
|
|
2560
|
+
).requiredOption("--title <title>", "Closeout title").option(
|
|
2561
|
+
"--file <path>",
|
|
2562
|
+
"Read the closeout body from a file (default: stdin)"
|
|
2563
|
+
).option(
|
|
2564
|
+
"--decomposition <id>",
|
|
2565
|
+
"Managed-run selector \u2014 the sug_ decomposition the task belongs to. Locates the parked run so its matchTags/verdict contract are read from state, not assembled from args."
|
|
2566
|
+
).option(
|
|
2567
|
+
"--no-status-flip",
|
|
2568
|
+
"Skip the status flip on a BARE task. (Managed runs never flip here \u2014 the run engine reflects the verdict onto the task on resume.)"
|
|
2569
|
+
).option("--source <source>", "Source / lane stamp", "cli").addHelpText(
|
|
2570
|
+
"after",
|
|
2571
|
+
`
|
|
2572
|
+
Examples:
|
|
2573
|
+
# Managed run \u2014 reads matchTags from run state, stamps them verbatim, un-parks the run:
|
|
2574
|
+
$ echo "Shipped X. Tests green." | sechroom close --task mem_XXXX --decomposition sug_YYYY \\
|
|
2575
|
+
--verdict pass --workspace wsp_ZZZZ --title "w4_build closeout"
|
|
2576
|
+
|
|
2577
|
+
# Bare task:
|
|
2578
|
+
$ sechroom close --task mem_XXXX --verdict pass --workspace wsp_ZZZZ \\
|
|
2579
|
+
--title "done" --file ./closeout.md`
|
|
2580
|
+
).action(async (opts, cmd) => {
|
|
2581
|
+
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
2582
|
+
const json = cmd.optsWithGlobals().json;
|
|
2583
|
+
const verdict = String(opts.verdict);
|
|
2584
|
+
if (!VERDICTS.includes(verdict))
|
|
2585
|
+
fail(
|
|
2586
|
+
`--verdict must be one of ${VERDICTS.join(" | ")} \u2014 got '${opts.verdict}'`
|
|
2587
|
+
);
|
|
2588
|
+
let bodyText;
|
|
2589
|
+
try {
|
|
2590
|
+
bodyText = opts.file ? readFileSync7(opts.file, "utf8") : readFileSync7(0, "utf8");
|
|
2591
|
+
} catch {
|
|
2592
|
+
fail(
|
|
2593
|
+
opts.file ? `could not read --file ${opts.file}` : "no closeout body \u2014 pass --file <path> or pipe it on stdin"
|
|
2594
|
+
);
|
|
2595
|
+
}
|
|
2596
|
+
if (!bodyText.trim())
|
|
2597
|
+
fail(
|
|
2598
|
+
"closeout body is empty \u2014 pass --file <path> or pipe the body on stdin"
|
|
2599
|
+
);
|
|
2600
|
+
const client = await makeClient(cfg);
|
|
2601
|
+
let matchTags;
|
|
2602
|
+
if (opts.decomposition) {
|
|
2603
|
+
const run = await runApi(
|
|
2604
|
+
"Reading run contract",
|
|
2605
|
+
async () => client.GET("/decompositions/{id}/run", {
|
|
2606
|
+
params: { path: { id: opts.decomposition } }
|
|
2607
|
+
})
|
|
2608
|
+
);
|
|
2609
|
+
const await_ = run.awaitingCompletion;
|
|
2610
|
+
if (!await_ || !Array.isArray(await_.matchTags) || await_.matchTags.length === 0)
|
|
2611
|
+
fail(
|
|
2612
|
+
`decomposition ${opts.decomposition} has no parked run awaiting a completion \u2014 nothing to close (run outcome: ${run.outcome ?? "unknown"}). Idempotent no-op on an already-resumed/terminal run.`
|
|
2613
|
+
);
|
|
2614
|
+
if (run.awaitingTaskId && run.awaitingTaskId !== opts.task)
|
|
2615
|
+
fail(
|
|
2616
|
+
`run ${opts.decomposition} is awaiting task ${run.awaitingTaskId}, not ${opts.task} \u2014 refusing to mis-key the resume.`
|
|
2617
|
+
);
|
|
2618
|
+
matchTags = await_.matchTags;
|
|
2619
|
+
} else {
|
|
2620
|
+
matchTags = [`wlp-task:${opts.task}`];
|
|
2621
|
+
}
|
|
2622
|
+
const tags = [
|
|
2623
|
+
.../* @__PURE__ */ new Set([
|
|
2624
|
+
...matchTags,
|
|
2625
|
+
`wlp-task:${opts.task}`,
|
|
2626
|
+
`verdict:${verdict}`
|
|
2627
|
+
])
|
|
2628
|
+
];
|
|
2629
|
+
const closeout = await runApi(
|
|
2630
|
+
"Creating closeout",
|
|
2631
|
+
async () => client.POST("/memories", {
|
|
2632
|
+
body: {
|
|
2633
|
+
text: bodyText,
|
|
2634
|
+
type: "reference",
|
|
2635
|
+
content: "{}",
|
|
2636
|
+
confidence: 1,
|
|
2637
|
+
source: opts.source,
|
|
2638
|
+
archetype: "Document",
|
|
2639
|
+
title: opts.title,
|
|
2640
|
+
tags,
|
|
2641
|
+
owner: { type: "Workspace", id: opts.workspace }
|
|
2642
|
+
}
|
|
2643
|
+
})
|
|
2644
|
+
);
|
|
2645
|
+
const edge = await runApi(
|
|
2646
|
+
"Wiring Reference edge",
|
|
2647
|
+
async () => client.POST("/memories/{memoryId}/relationships", {
|
|
2648
|
+
params: { path: { memoryId: closeout.id } },
|
|
2649
|
+
body: { toMemoryId: opts.task, type: "Reference" }
|
|
2650
|
+
})
|
|
2651
|
+
);
|
|
2652
|
+
let taskStatus;
|
|
2653
|
+
if (opts.statusFlip !== false && !opts.decomposition) {
|
|
2654
|
+
const current = await runApi(
|
|
2655
|
+
"Reading task tags",
|
|
2656
|
+
async () => client.GET("/memories/{memoryId}", {
|
|
2657
|
+
params: { path: { memoryId: opts.task } }
|
|
2658
|
+
})
|
|
2659
|
+
);
|
|
2660
|
+
const currentTags = current?.item?.tags ?? current?.tags ?? [];
|
|
2661
|
+
const target = verdict === "blocked" ? "status:blocked" : "status:done";
|
|
2662
|
+
const nextTags = [
|
|
2663
|
+
...new Set(currentTags.filter((t) => !t.startsWith("status:")))
|
|
2664
|
+
].concat(target);
|
|
2665
|
+
await runApi(
|
|
2666
|
+
"Flipping task status",
|
|
2667
|
+
async () => client.PATCH("/memories/{memoryId}/metadata", {
|
|
2668
|
+
params: { path: { memoryId: opts.task } },
|
|
2669
|
+
body: {
|
|
2670
|
+
memoryId: opts.task,
|
|
2671
|
+
source: opts.source,
|
|
2672
|
+
tags: nextTags
|
|
2673
|
+
}
|
|
2674
|
+
})
|
|
2675
|
+
);
|
|
2676
|
+
taskStatus = target.slice("status:".length);
|
|
2677
|
+
}
|
|
2678
|
+
const view = resolveViewUrl(cfg.baseUrl, closeout.url);
|
|
2679
|
+
const result = {
|
|
2680
|
+
closeoutId: closeout.id,
|
|
2681
|
+
edgeId: edge.id,
|
|
2682
|
+
taskStatus: taskStatus ?? null,
|
|
2683
|
+
verdict,
|
|
2684
|
+
tags
|
|
2685
|
+
};
|
|
2686
|
+
emitAction(
|
|
2687
|
+
`closed ${style.bold(opts.task)} verdict:${style.bold(verdict)} \u2192 closeout ${style.bold(closeout.id)}${taskStatus ? ` ${style.dim(`(task ${taskStatus})`)}` : ""}${view ? ` ${style.dim("\u2192")} ${view}` : ""}`,
|
|
2688
|
+
result,
|
|
2689
|
+
json
|
|
2690
|
+
);
|
|
2691
|
+
});
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2536
2694
|
// src/commands/continuity.ts
|
|
2537
2695
|
function registerContinuity(program2) {
|
|
2538
2696
|
const continuity = program2.command("continuity").description("Continuity snapshots: checkpoint and resume work");
|
|
@@ -2693,6 +2851,90 @@ Examples:
|
|
|
2693
2851
|
});
|
|
2694
2852
|
}
|
|
2695
2853
|
|
|
2854
|
+
// src/commands/decomposition.ts
|
|
2855
|
+
function registerDecomposition(program2) {
|
|
2856
|
+
const decomposition = program2.command("decomposition").description(
|
|
2857
|
+
"Drive a WLP decomposition: decompose a brief, then execute / accept / reject"
|
|
2858
|
+
);
|
|
2859
|
+
decomposition.addHelpText(
|
|
2860
|
+
"after",
|
|
2861
|
+
`
|
|
2862
|
+
Examples:
|
|
2863
|
+
$ sechroom decomposition decompose mem_XXXX
|
|
2864
|
+
$ sechroom decomposition execute sug_XXXX
|
|
2865
|
+
$ sechroom decomposition accept sug_XXXX
|
|
2866
|
+
$ sechroom decomposition reject sug_XXXX --reason "wrong shape"`
|
|
2867
|
+
);
|
|
2868
|
+
decomposition.command("decompose <briefId>").description(
|
|
2869
|
+
"Decompose a work brief into a candidate Task graph (POST /work-briefs/{id}/decompose)"
|
|
2870
|
+
).action(async (briefId, _opts, cmd) => {
|
|
2871
|
+
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
2872
|
+
const data = await runApi("Queueing decomposition", async () => {
|
|
2873
|
+
const client = await makeClient(cfg);
|
|
2874
|
+
return client.POST("/work-briefs/{id}/decompose", {
|
|
2875
|
+
params: { path: { id: briefId } },
|
|
2876
|
+
body: { id: briefId }
|
|
2877
|
+
});
|
|
2878
|
+
});
|
|
2879
|
+
emitAction(
|
|
2880
|
+
`queued decomposition of ${style.bold(briefId)} \u2192 ${style.bold(data.suggestionId)}`,
|
|
2881
|
+
data,
|
|
2882
|
+
cmd.optsWithGlobals().json
|
|
2883
|
+
);
|
|
2884
|
+
});
|
|
2885
|
+
decomposition.command("execute <decompositionId>").description(
|
|
2886
|
+
"Execute a decomposition's Task graph (POST /decompositions/{id}/execute)"
|
|
2887
|
+
).action(async (decompositionId, _opts, cmd) => {
|
|
2888
|
+
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
2889
|
+
const data = await runApi("Executing decomposition", async () => {
|
|
2890
|
+
const client = await makeClient(cfg);
|
|
2891
|
+
return client.POST("/decompositions/{id}/execute", {
|
|
2892
|
+
params: { path: { id: decompositionId } },
|
|
2893
|
+
body: {}
|
|
2894
|
+
});
|
|
2895
|
+
});
|
|
2896
|
+
emitAction(
|
|
2897
|
+
`executed ${style.bold(decompositionId)} \u2192 run ${style.bold(data.runRecordId)} (${data.outcome})`,
|
|
2898
|
+
data,
|
|
2899
|
+
cmd.optsWithGlobals().json
|
|
2900
|
+
);
|
|
2901
|
+
});
|
|
2902
|
+
decomposition.command("accept <decompositionId>").description(
|
|
2903
|
+
"Accept a Pending decomposition \u2014 promote + ratify its Tasks (POST /decompositions/{id}/accept)"
|
|
2904
|
+
).action(async (decompositionId, _opts, cmd) => {
|
|
2905
|
+
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
2906
|
+
const data = await runApi("Accepting decomposition", async () => {
|
|
2907
|
+
const client = await makeClient(cfg);
|
|
2908
|
+
return client.POST("/decompositions/{id}/accept", {
|
|
2909
|
+
params: { path: { id: decompositionId } },
|
|
2910
|
+
body: {}
|
|
2911
|
+
});
|
|
2912
|
+
});
|
|
2913
|
+
emitAction(
|
|
2914
|
+
`accepted decomposition ${style.bold(decompositionId)}`,
|
|
2915
|
+
data,
|
|
2916
|
+
cmd.optsWithGlobals().json
|
|
2917
|
+
);
|
|
2918
|
+
});
|
|
2919
|
+
decomposition.command("reject <decompositionId>").description(
|
|
2920
|
+
"Reject a Pending decomposition \u2014 archive its Tasks, bounce the brief (POST /decompositions/{id}/reject)"
|
|
2921
|
+
).option("--reason <reason>", "Optional free-text rejection reason").action(async (decompositionId, opts, cmd) => {
|
|
2922
|
+
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
2923
|
+
const data = await runApi("Rejecting decomposition", async () => {
|
|
2924
|
+
const client = await makeClient(cfg);
|
|
2925
|
+
return client.POST("/decompositions/{id}/reject", {
|
|
2926
|
+
params: { path: { id: decompositionId } },
|
|
2927
|
+
body: { reasonText: opts.reason ?? null }
|
|
2928
|
+
});
|
|
2929
|
+
});
|
|
2930
|
+
emitAction(
|
|
2931
|
+
`rejected decomposition ${style.bold(decompositionId)}`,
|
|
2932
|
+
data,
|
|
2933
|
+
cmd.optsWithGlobals().json
|
|
2934
|
+
);
|
|
2935
|
+
});
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2696
2938
|
// src/commands/filing.ts
|
|
2697
2939
|
function registerFiling(program2) {
|
|
2698
2940
|
const filing = program2.command("filing").description("Review and act on filing suggestions");
|
|
@@ -3204,7 +3446,7 @@ Examples:
|
|
|
3204
3446
|
|
|
3205
3447
|
// src/setup/apply.ts
|
|
3206
3448
|
import { createHash as createHash3 } from "crypto";
|
|
3207
|
-
import { mkdirSync as mkdirSync9, readFileSync as
|
|
3449
|
+
import { mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync9, existsSync as existsSync9 } from "fs";
|
|
3208
3450
|
import { dirname as dirname8 } from "path";
|
|
3209
3451
|
var MARKER_BEGIN = "<!-- @sechroom/cli:begin";
|
|
3210
3452
|
var MARKER_END = "<!-- @sechroom/cli:end";
|
|
@@ -3262,7 +3504,7 @@ function ensureDir2(path) {
|
|
|
3262
3504
|
}
|
|
3263
3505
|
function readOr(path, fallback) {
|
|
3264
3506
|
try {
|
|
3265
|
-
return
|
|
3507
|
+
return readFileSync8(path, "utf8");
|
|
3266
3508
|
} catch {
|
|
3267
3509
|
return fallback;
|
|
3268
3510
|
}
|
|
@@ -3273,7 +3515,7 @@ function mergeMcpJson(path, snippet, dryRun) {
|
|
|
3273
3515
|
let current = {};
|
|
3274
3516
|
if (existed) {
|
|
3275
3517
|
try {
|
|
3276
|
-
current = JSON.parse(
|
|
3518
|
+
current = JSON.parse(readFileSync8(path, "utf8"));
|
|
3277
3519
|
} catch {
|
|
3278
3520
|
return { kind: "mcp", path, status: "skipped", note: "existing file isn't valid JSON \u2014 left untouched" };
|
|
3279
3521
|
}
|
|
@@ -3989,7 +4231,7 @@ import { basename as basename2, join as join13 } from "path";
|
|
|
3989
4231
|
|
|
3990
4232
|
// src/commands/fanout.ts
|
|
3991
4233
|
import { spawnSync } from "child_process";
|
|
3992
|
-
import { existsSync as existsSync10, readFileSync as
|
|
4234
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
3993
4235
|
import { isAbsolute, join as join12, resolve } from "path";
|
|
3994
4236
|
var ICON = {
|
|
3995
4237
|
refresh: "\u21BB",
|
|
@@ -4024,7 +4266,7 @@ function readManifest(path) {
|
|
|
4024
4266
|
if (!existsSync10(path)) return null;
|
|
4025
4267
|
let parsed;
|
|
4026
4268
|
try {
|
|
4027
|
-
parsed = JSON.parse(
|
|
4269
|
+
parsed = JSON.parse(readFileSync9(path, "utf8"));
|
|
4028
4270
|
} catch (err2) {
|
|
4029
4271
|
throw new Error(`couldn't parse ${path}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
4030
4272
|
}
|
|
@@ -4838,24 +5080,45 @@ Examples:
|
|
|
4838
5080
|
$ sechroom relationship suggestions --status Pending --memory mem_XXXX
|
|
4839
5081
|
$ sechroom relationship suggestion accept rsg_XXXX`
|
|
4840
5082
|
);
|
|
4841
|
-
relationship.command("create <fromMemoryId> <toMemoryId>").description("Create a relationship (POST /memories/{memoryId}/relationships)").option("--type <type>", "Relationship type (Reference, Related, Parent, Child, Follows, \u2026)", "Reference").
|
|
5083
|
+
relationship.command("create <fromMemoryId> <toMemoryId>").description("Create a relationship (POST /memories/{memoryId}/relationships)").option("--type <type>", "Relationship type (Reference, Related, Parent, Child, Follows, \u2026)", "Reference").option(
|
|
5084
|
+
"--to-version <number>",
|
|
5085
|
+
"Version of the target memory to pin the edge to (defaults to the target's current version)"
|
|
5086
|
+
).action(async (fromMemoryId, toMemoryId, opts, cmd) => {
|
|
4842
5087
|
const cfg = resolveConfig(cmd.optsWithGlobals());
|
|
4843
|
-
const
|
|
4844
|
-
|
|
4845
|
-
|
|
5088
|
+
const client = await makeClient(cfg);
|
|
5089
|
+
let toVersion;
|
|
5090
|
+
if (opts.toVersion !== void 0) {
|
|
5091
|
+
toVersion = Number(opts.toVersion);
|
|
5092
|
+
if (!Number.isInteger(toVersion) || toVersion < 1) {
|
|
5093
|
+
fail(`--to-version must be a positive integer (got '${opts.toVersion}').`);
|
|
5094
|
+
}
|
|
5095
|
+
} else {
|
|
5096
|
+
const target = await runApi(
|
|
5097
|
+
"Resolving target version",
|
|
5098
|
+
async () => client.GET("/memories/{memoryId}", { params: { path: { memoryId: toMemoryId } } })
|
|
5099
|
+
);
|
|
5100
|
+
if (typeof target.item?.currentVersion !== "number") {
|
|
5101
|
+
fail(`Could not resolve the current version of ${toMemoryId}; pass --to-version explicitly.`);
|
|
5102
|
+
}
|
|
5103
|
+
toVersion = target.item.currentVersion;
|
|
5104
|
+
}
|
|
5105
|
+
const data = await runApi(
|
|
5106
|
+
"Creating relationship",
|
|
5107
|
+
async () => client.POST("/memories/{memoryId}/relationships", {
|
|
4846
5108
|
params: { path: { memoryId: fromMemoryId } },
|
|
4847
5109
|
body: {
|
|
4848
5110
|
toMemoryId,
|
|
4849
|
-
type: opts.type
|
|
5111
|
+
type: opts.type,
|
|
5112
|
+
toVersion
|
|
4850
5113
|
}
|
|
4851
|
-
})
|
|
4852
|
-
|
|
5114
|
+
})
|
|
5115
|
+
);
|
|
4853
5116
|
const inversePart = data.inverseId ? ` ${style.dim(`(inverse ${data.inverseId})`)}` : "";
|
|
4854
5117
|
const view = resolveViewUrl(cfg.baseUrl, data.url);
|
|
4855
5118
|
const urlPart = view ? ` ${style.dim("\u2192")} ${view}` : "";
|
|
4856
5119
|
emitAction(
|
|
4857
|
-
`created relationship ${style.bold(data.id)} ${style.dim(`${fromMemoryId} \u2192 ${toMemoryId}`)}${inversePart}${urlPart}`,
|
|
4858
|
-
data,
|
|
5120
|
+
`created relationship ${style.bold(data.id)} ${style.dim(`${fromMemoryId} \u2192 ${toMemoryId} @v${toVersion}`)}${inversePart}${urlPart}`,
|
|
5121
|
+
{ ...data, toVersion },
|
|
4859
5122
|
cmd.optsWithGlobals().json
|
|
4860
5123
|
);
|
|
4861
5124
|
});
|
|
@@ -4979,7 +5242,7 @@ Examples:
|
|
|
4979
5242
|
// src/commands/reset.ts
|
|
4980
5243
|
import { homedir as homedir4 } from "os";
|
|
4981
5244
|
import { join as join14 } from "path";
|
|
4982
|
-
import { existsSync as existsSync12, readFileSync as
|
|
5245
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10, rmSync as rmSync3 } from "fs";
|
|
4983
5246
|
var SKILLS_LOCK2 = ".sechroom-skills.json";
|
|
4984
5247
|
var localSkillsDir = () => join14(process.cwd(), ".claude", "skills");
|
|
4985
5248
|
var globalSkillsDir = () => join14(homedir4(), ".claude", "skills");
|
|
@@ -4990,7 +5253,7 @@ function removeMaterialisedSkills(dir) {
|
|
|
4990
5253
|
const lockPath = join14(dir, SKILLS_LOCK2);
|
|
4991
5254
|
if (!existsSync12(lockPath)) return removed;
|
|
4992
5255
|
try {
|
|
4993
|
-
const lock = JSON.parse(
|
|
5256
|
+
const lock = JSON.parse(readFileSync10(lockPath, "utf8"));
|
|
4994
5257
|
for (const entry of Object.values(lock)) {
|
|
4995
5258
|
for (const name of entry.skills ?? []) {
|
|
4996
5259
|
const p = join14(dir, name);
|
|
@@ -5390,7 +5653,7 @@ Examples:
|
|
|
5390
5653
|
import {
|
|
5391
5654
|
existsSync as existsSync15,
|
|
5392
5655
|
mkdirSync as mkdirSync12,
|
|
5393
|
-
readFileSync as
|
|
5656
|
+
readFileSync as readFileSync11,
|
|
5394
5657
|
rmSync as rmSync4,
|
|
5395
5658
|
writeFileSync as writeFileSync12
|
|
5396
5659
|
} from "fs";
|
|
@@ -5605,7 +5868,7 @@ function findBinding(start) {
|
|
|
5605
5868
|
if (existsSync15(path)) {
|
|
5606
5869
|
try {
|
|
5607
5870
|
const b = JSON.parse(
|
|
5608
|
-
|
|
5871
|
+
readFileSync11(path, "utf8")
|
|
5609
5872
|
);
|
|
5610
5873
|
if (b.decompositionId && b.taskId)
|
|
5611
5874
|
return { decompositionId: b.decompositionId, taskId: b.taskId };
|
|
@@ -5624,7 +5887,7 @@ function parseTranscript(path) {
|
|
|
5624
5887
|
let tokensOut = 0;
|
|
5625
5888
|
let contextUsed = 0;
|
|
5626
5889
|
let model = "";
|
|
5627
|
-
for (const line of
|
|
5890
|
+
for (const line of readFileSync11(path, "utf8").split("\n")) {
|
|
5628
5891
|
if (!line.trim()) continue;
|
|
5629
5892
|
let obj;
|
|
5630
5893
|
try {
|
|
@@ -5882,7 +6145,7 @@ Examples:
|
|
|
5882
6145
|
function resolveVersion() {
|
|
5883
6146
|
try {
|
|
5884
6147
|
const pkg = JSON.parse(
|
|
5885
|
-
|
|
6148
|
+
readFileSync12(new URL("../package.json", import.meta.url), "utf8")
|
|
5886
6149
|
);
|
|
5887
6150
|
return pkg.version ?? "0.0.0";
|
|
5888
6151
|
} catch {
|
|
@@ -6040,6 +6303,8 @@ registerLookup(program);
|
|
|
6040
6303
|
registerRelationships(program);
|
|
6041
6304
|
registerWorkspace(program);
|
|
6042
6305
|
registerProject(program);
|
|
6306
|
+
registerDecomposition(program);
|
|
6307
|
+
registerClose(program);
|
|
6043
6308
|
registerFiling(program);
|
|
6044
6309
|
registerContinuity(program);
|
|
6045
6310
|
registerCheckpoint(program);
|
package/package.json
CHANGED