@anthropologies/claudestory 0.1.40 → 0.1.42
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/cli.js +114 -67
- package/dist/mcp.js +76 -33
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5855,7 +5855,8 @@ var init_state_machine = __esm({
|
|
|
5855
5855
|
// start does INIT + LOAD_CONTEXT internally
|
|
5856
5856
|
LOAD_CONTEXT: ["PICK_TICKET"],
|
|
5857
5857
|
// internal (never seen by Claude)
|
|
5858
|
-
PICK_TICKET: ["PLAN", "ISSUE_FIX", "SESSION_END"],
|
|
5858
|
+
PICK_TICKET: ["PLAN", "ISSUE_FIX", "COMPLETE", "SESSION_END"],
|
|
5859
|
+
// COMPLETE for ISS-075 (nothing left to do)
|
|
5859
5860
|
PLAN: ["PLAN_REVIEW"],
|
|
5860
5861
|
PLAN_REVIEW: ["IMPLEMENT", "WRITE_TESTS", "PLAN", "PLAN_REVIEW", "SESSION_END"],
|
|
5861
5862
|
// approve → IMPLEMENT/WRITE_TESTS, reject → PLAN, stay for next round; SESSION_END for tiered exit
|
|
@@ -6444,6 +6445,9 @@ var init_pick_ticket = __esm({
|
|
|
6444
6445
|
}
|
|
6445
6446
|
const topCandidate = candidates.kind === "found" ? candidates.candidates[0] : null;
|
|
6446
6447
|
const hasIssues = highIssues.length > 0;
|
|
6448
|
+
if (!topCandidate && candidates.kind !== "found" && !hasIssues) {
|
|
6449
|
+
return { action: "goto", target: "COMPLETE" };
|
|
6450
|
+
}
|
|
6447
6451
|
return {
|
|
6448
6452
|
instruction: [
|
|
6449
6453
|
"# Pick a Ticket or Issue",
|
|
@@ -6730,7 +6734,7 @@ var init_plan_review = __esm({
|
|
|
6730
6734
|
const risk = ctx.state.ticket?.risk ?? "low";
|
|
6731
6735
|
const minRounds = requiredRounds(risk);
|
|
6732
6736
|
const hasCriticalOrMajor = findings.some(
|
|
6733
|
-
(f) => f.severity === "critical" || f.severity === "major"
|
|
6737
|
+
(f) => (f.severity === "critical" || f.severity === "major") && f.disposition !== "addressed" && f.disposition !== "deferred"
|
|
6734
6738
|
);
|
|
6735
6739
|
if (verdict === "approve" && hasCriticalOrMajor) {
|
|
6736
6740
|
return { action: "retry", instruction: "Contradictory review payload: verdict is 'approve' but critical/major findings are present. Re-run the review or correct the verdict." };
|
|
@@ -7178,7 +7182,7 @@ var init_code_review = __esm({
|
|
|
7178
7182
|
const risk = ctx.state.ticket?.realizedRisk ?? ctx.state.ticket?.risk ?? "low";
|
|
7179
7183
|
const minRounds = requiredRounds(risk);
|
|
7180
7184
|
const hasCriticalOrMajor = findings.some(
|
|
7181
|
-
(f) => f.severity === "critical" || f.severity === "major"
|
|
7185
|
+
(f) => (f.severity === "critical" || f.severity === "major") && f.disposition !== "addressed" && f.disposition !== "deferred"
|
|
7182
7186
|
);
|
|
7183
7187
|
const planRedirect = findings.some((f) => f.recommendedNextState === "PLAN");
|
|
7184
7188
|
if (verdict === "approve" && hasCriticalOrMajor) {
|
|
@@ -8323,24 +8327,64 @@ var init_stages = __esm({
|
|
|
8323
8327
|
}
|
|
8324
8328
|
});
|
|
8325
8329
|
|
|
8330
|
+
// src/autonomous/version-check.ts
|
|
8331
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
8332
|
+
import { join as join13, dirname as dirname4 } from "path";
|
|
8333
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
8334
|
+
function checkVersionMismatch(runningVersion, installedVersion) {
|
|
8335
|
+
if (!installedVersion) return null;
|
|
8336
|
+
if (runningVersion === "0.0.0-dev") return null;
|
|
8337
|
+
if (runningVersion === installedVersion) return null;
|
|
8338
|
+
return `claudestory MCP server is running v${runningVersion} but v${installedVersion} is installed. Restart Claude Code to load the updated version.`;
|
|
8339
|
+
}
|
|
8340
|
+
function getInstalledVersion() {
|
|
8341
|
+
try {
|
|
8342
|
+
const thisFile = fileURLToPath3(import.meta.url);
|
|
8343
|
+
const candidates = [
|
|
8344
|
+
join13(dirname4(thisFile), "..", "..", "package.json"),
|
|
8345
|
+
join13(dirname4(thisFile), "..", "package.json")
|
|
8346
|
+
];
|
|
8347
|
+
for (const candidate of candidates) {
|
|
8348
|
+
try {
|
|
8349
|
+
const raw = readFileSync6(candidate, "utf-8");
|
|
8350
|
+
const pkg = JSON.parse(raw);
|
|
8351
|
+
if (pkg.version) return pkg.version;
|
|
8352
|
+
} catch {
|
|
8353
|
+
}
|
|
8354
|
+
}
|
|
8355
|
+
return null;
|
|
8356
|
+
} catch {
|
|
8357
|
+
return null;
|
|
8358
|
+
}
|
|
8359
|
+
}
|
|
8360
|
+
function getRunningVersion() {
|
|
8361
|
+
return "0.1.42";
|
|
8362
|
+
}
|
|
8363
|
+
var init_version_check = __esm({
|
|
8364
|
+
"src/autonomous/version-check.ts"() {
|
|
8365
|
+
"use strict";
|
|
8366
|
+
init_esm_shims();
|
|
8367
|
+
}
|
|
8368
|
+
});
|
|
8369
|
+
|
|
8326
8370
|
// src/autonomous/guide.ts
|
|
8327
|
-
import { readFileSync as
|
|
8328
|
-
import { join as
|
|
8371
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, readdirSync as readdirSync4 } from "fs";
|
|
8372
|
+
import { join as join14 } from "path";
|
|
8329
8373
|
function buildGuideRecommendOptions(root) {
|
|
8330
8374
|
const opts = {};
|
|
8331
8375
|
try {
|
|
8332
|
-
const handoversDir =
|
|
8376
|
+
const handoversDir = join14(root, ".story", "handovers");
|
|
8333
8377
|
const files = readdirSync4(handoversDir, "utf-8").filter((f) => f.endsWith(".md")).sort();
|
|
8334
8378
|
if (files.length > 0) {
|
|
8335
|
-
opts.latestHandoverContent =
|
|
8379
|
+
opts.latestHandoverContent = readFileSync7(join14(handoversDir, files[files.length - 1]), "utf-8");
|
|
8336
8380
|
}
|
|
8337
8381
|
} catch {
|
|
8338
8382
|
}
|
|
8339
8383
|
try {
|
|
8340
|
-
const snapshotsDir =
|
|
8384
|
+
const snapshotsDir = join14(root, ".story", "snapshots");
|
|
8341
8385
|
const snapFiles = readdirSync4(snapshotsDir, "utf-8").filter((f) => f.endsWith(".json")).sort();
|
|
8342
8386
|
if (snapFiles.length > 0) {
|
|
8343
|
-
const raw =
|
|
8387
|
+
const raw = readFileSync7(join14(snapshotsDir, snapFiles[snapFiles.length - 1]), "utf-8");
|
|
8344
8388
|
const snap = JSON.parse(raw);
|
|
8345
8389
|
if (snap.issues) {
|
|
8346
8390
|
opts.previousOpenIssueCount = snap.issues.filter((i) => i.status !== "resolved").length;
|
|
@@ -8527,6 +8571,7 @@ async function handleStart(root, args) {
|
|
|
8527
8571
|
for (const stale of staleSessions) {
|
|
8528
8572
|
writeSessionSync(stale.dir, { ...stale.state, status: "superseded" });
|
|
8529
8573
|
}
|
|
8574
|
+
const versionWarning = checkVersionMismatch(getRunningVersion(), getInstalledVersion());
|
|
8530
8575
|
const wsId = deriveWorkspaceId(root);
|
|
8531
8576
|
const mode = args.mode ?? "auto";
|
|
8532
8577
|
if (mode !== "auto" && !args.ticketId) {
|
|
@@ -8721,7 +8766,7 @@ Staged: ${stagedResult.data.join(", ")}`
|
|
|
8721
8766
|
}
|
|
8722
8767
|
}
|
|
8723
8768
|
const { state: projectState, warnings } = await loadProject(root);
|
|
8724
|
-
const handoversDir =
|
|
8769
|
+
const handoversDir = join14(root, ".story", "handovers");
|
|
8725
8770
|
const ctx = { state: projectState, warnings, root, handoversDir, format: "md" };
|
|
8726
8771
|
let handoverText = "";
|
|
8727
8772
|
try {
|
|
@@ -8738,7 +8783,7 @@ Staged: ${stagedResult.data.join(", ")}`
|
|
|
8738
8783
|
}
|
|
8739
8784
|
} catch {
|
|
8740
8785
|
}
|
|
8741
|
-
const rulesText = readFileSafe2(
|
|
8786
|
+
const rulesText = readFileSafe2(join14(root, "RULES.md"));
|
|
8742
8787
|
const lessonDigest = buildLessonDigest(projectState.lessons);
|
|
8743
8788
|
const digestParts = [
|
|
8744
8789
|
handoverText ? `## Recent Handovers
|
|
@@ -8754,7 +8799,7 @@ ${rulesText}` : "",
|
|
|
8754
8799
|
].filter(Boolean);
|
|
8755
8800
|
const digest = digestParts.join("\n\n---\n\n");
|
|
8756
8801
|
try {
|
|
8757
|
-
writeFileSync3(
|
|
8802
|
+
writeFileSync3(join14(dir, "context-digest.md"), digest, "utf-8");
|
|
8758
8803
|
} catch {
|
|
8759
8804
|
}
|
|
8760
8805
|
if (mode !== "auto" && args.ticketId) {
|
|
@@ -8946,7 +8991,8 @@ ${ticket.description}` : "",
|
|
|
8946
8991
|
"Do NOT use Claude Code's plan mode \u2014 write plans as markdown files.",
|
|
8947
8992
|
"Do NOT ask the user for confirmation or approval.",
|
|
8948
8993
|
"Do NOT stop or summarize between tickets \u2014 call autonomous_guide IMMEDIATELY.",
|
|
8949
|
-
"You are in autonomous mode \u2014 continue working until done."
|
|
8994
|
+
"You are in autonomous mode \u2014 continue working until done.",
|
|
8995
|
+
...versionWarning ? [`**Warning:** ${versionWarning}`] : []
|
|
8950
8996
|
],
|
|
8951
8997
|
transitionedFrom: "INIT"
|
|
8952
8998
|
});
|
|
@@ -9472,7 +9518,7 @@ function guideError(err) {
|
|
|
9472
9518
|
}
|
|
9473
9519
|
function readFileSafe2(path2) {
|
|
9474
9520
|
try {
|
|
9475
|
-
return
|
|
9521
|
+
return readFileSync7(path2, "utf-8");
|
|
9476
9522
|
} catch {
|
|
9477
9523
|
return "";
|
|
9478
9524
|
}
|
|
@@ -9498,6 +9544,7 @@ var init_guide = __esm({
|
|
|
9498
9544
|
init_snapshot();
|
|
9499
9545
|
init_queries();
|
|
9500
9546
|
init_recommend();
|
|
9547
|
+
init_version_check();
|
|
9501
9548
|
init_handover();
|
|
9502
9549
|
RECOVERY_MAPPING = {
|
|
9503
9550
|
PICK_TICKET: { state: "PICK_TICKET", resetPlan: false, resetCode: false },
|
|
@@ -9724,8 +9771,8 @@ var init_session_report_formatter = __esm({
|
|
|
9724
9771
|
});
|
|
9725
9772
|
|
|
9726
9773
|
// src/cli/commands/session-report.ts
|
|
9727
|
-
import { readFileSync as
|
|
9728
|
-
import { join as
|
|
9774
|
+
import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
|
|
9775
|
+
import { join as join15 } from "path";
|
|
9729
9776
|
async function handleSessionReport(sessionId, root, format = "md") {
|
|
9730
9777
|
if (!UUID_REGEX.test(sessionId)) {
|
|
9731
9778
|
return {
|
|
@@ -9744,7 +9791,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9744
9791
|
isError: true
|
|
9745
9792
|
};
|
|
9746
9793
|
}
|
|
9747
|
-
const statePath2 =
|
|
9794
|
+
const statePath2 = join15(dir, "state.json");
|
|
9748
9795
|
if (!existsSync10(statePath2)) {
|
|
9749
9796
|
return {
|
|
9750
9797
|
output: `Error: Session ${sessionId} corrupt \u2014 state.json missing.`,
|
|
@@ -9754,7 +9801,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9754
9801
|
};
|
|
9755
9802
|
}
|
|
9756
9803
|
try {
|
|
9757
|
-
const rawJson = JSON.parse(
|
|
9804
|
+
const rawJson = JSON.parse(readFileSync8(statePath2, "utf-8"));
|
|
9758
9805
|
if (rawJson && typeof rawJson === "object" && "schemaVersion" in rawJson && rawJson.schemaVersion !== CURRENT_SESSION_SCHEMA_VERSION) {
|
|
9759
9806
|
return {
|
|
9760
9807
|
output: `Error: Session ${sessionId} \u2014 unsupported session schema version ${rawJson.schemaVersion}.`,
|
|
@@ -9783,7 +9830,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9783
9830
|
const events = readEvents(dir);
|
|
9784
9831
|
let planContent = null;
|
|
9785
9832
|
try {
|
|
9786
|
-
planContent =
|
|
9833
|
+
planContent = readFileSync8(join15(dir, "plan.md"), "utf-8");
|
|
9787
9834
|
} catch {
|
|
9788
9835
|
}
|
|
9789
9836
|
let gitLog = null;
|
|
@@ -9812,7 +9859,7 @@ var init_session_report = __esm({
|
|
|
9812
9859
|
});
|
|
9813
9860
|
|
|
9814
9861
|
// src/cli/commands/phase.ts
|
|
9815
|
-
import { join as
|
|
9862
|
+
import { join as join16, resolve as resolve6 } from "path";
|
|
9816
9863
|
function validatePhaseId(id) {
|
|
9817
9864
|
if (id.length > PHASE_ID_MAX_LENGTH) {
|
|
9818
9865
|
throw new CliValidationError("invalid_input", `Phase ID "${id}" exceeds ${PHASE_ID_MAX_LENGTH} characters`);
|
|
@@ -10001,21 +10048,21 @@ async function handlePhaseDelete(id, reassign, format, root) {
|
|
|
10001
10048
|
const updated = { ...ticket, phase: reassign, order: maxOrder };
|
|
10002
10049
|
const parsed = TicketSchema.parse(updated);
|
|
10003
10050
|
const content = serializeJSON(parsed);
|
|
10004
|
-
const target =
|
|
10051
|
+
const target = join16(wrapDir, "tickets", `${parsed.id}.json`);
|
|
10005
10052
|
operations.push({ op: "write", target, content });
|
|
10006
10053
|
}
|
|
10007
10054
|
for (const issue of affectedIssues) {
|
|
10008
10055
|
const updated = { ...issue, phase: reassign };
|
|
10009
10056
|
const parsed = IssueSchema.parse(updated);
|
|
10010
10057
|
const content = serializeJSON(parsed);
|
|
10011
|
-
const target =
|
|
10058
|
+
const target = join16(wrapDir, "issues", `${parsed.id}.json`);
|
|
10012
10059
|
operations.push({ op: "write", target, content });
|
|
10013
10060
|
}
|
|
10014
10061
|
const newPhases = state.roadmap.phases.filter((p) => p.id !== id);
|
|
10015
10062
|
const newRoadmap = { ...state.roadmap, phases: newPhases };
|
|
10016
10063
|
const parsedRoadmap = RoadmapSchema.parse(newRoadmap);
|
|
10017
10064
|
const roadmapContent = serializeJSON(parsedRoadmap);
|
|
10018
|
-
const roadmapTarget =
|
|
10065
|
+
const roadmapTarget = join16(wrapDir, "roadmap.json");
|
|
10019
10066
|
operations.push({ op: "write", target: roadmapTarget, content: roadmapContent });
|
|
10020
10067
|
await runTransactionUnlocked(root, operations);
|
|
10021
10068
|
} else {
|
|
@@ -10048,14 +10095,14 @@ var init_phase = __esm({
|
|
|
10048
10095
|
|
|
10049
10096
|
// src/mcp/tools.ts
|
|
10050
10097
|
import { z as z10 } from "zod";
|
|
10051
|
-
import { join as
|
|
10098
|
+
import { join as join17 } from "path";
|
|
10052
10099
|
function formatMcpError(code, message) {
|
|
10053
10100
|
return `[${code}] ${message}`;
|
|
10054
10101
|
}
|
|
10055
10102
|
async function runMcpReadTool(pinnedRoot, handler) {
|
|
10056
10103
|
try {
|
|
10057
10104
|
const { state, warnings } = await loadProject(pinnedRoot);
|
|
10058
|
-
const handoversDir =
|
|
10105
|
+
const handoversDir = join17(pinnedRoot, ".story", "handovers");
|
|
10059
10106
|
const ctx = { state, warnings, root: pinnedRoot, handoversDir, format: "md" };
|
|
10060
10107
|
const result = await handler(ctx);
|
|
10061
10108
|
if (result.errorCode && INFRASTRUCTURE_ERROR_CODES.includes(result.errorCode)) {
|
|
@@ -10643,10 +10690,10 @@ var init_tools = __esm({
|
|
|
10643
10690
|
|
|
10644
10691
|
// src/core/init.ts
|
|
10645
10692
|
import { mkdir as mkdir4, stat as stat2, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
10646
|
-
import { join as
|
|
10693
|
+
import { join as join18, resolve as resolve7 } from "path";
|
|
10647
10694
|
async function initProject(root, options) {
|
|
10648
10695
|
const absRoot = resolve7(root);
|
|
10649
|
-
const wrapDir =
|
|
10696
|
+
const wrapDir = join18(absRoot, ".story");
|
|
10650
10697
|
let exists = false;
|
|
10651
10698
|
try {
|
|
10652
10699
|
const s = await stat2(wrapDir);
|
|
@@ -10666,11 +10713,11 @@ async function initProject(root, options) {
|
|
|
10666
10713
|
".story/ already exists. Use --force to overwrite config and roadmap."
|
|
10667
10714
|
);
|
|
10668
10715
|
}
|
|
10669
|
-
await mkdir4(
|
|
10670
|
-
await mkdir4(
|
|
10671
|
-
await mkdir4(
|
|
10672
|
-
await mkdir4(
|
|
10673
|
-
await mkdir4(
|
|
10716
|
+
await mkdir4(join18(wrapDir, "tickets"), { recursive: true });
|
|
10717
|
+
await mkdir4(join18(wrapDir, "issues"), { recursive: true });
|
|
10718
|
+
await mkdir4(join18(wrapDir, "handovers"), { recursive: true });
|
|
10719
|
+
await mkdir4(join18(wrapDir, "notes"), { recursive: true });
|
|
10720
|
+
await mkdir4(join18(wrapDir, "lessons"), { recursive: true });
|
|
10674
10721
|
const created = [
|
|
10675
10722
|
".story/config.json",
|
|
10676
10723
|
".story/roadmap.json",
|
|
@@ -10710,7 +10757,7 @@ async function initProject(root, options) {
|
|
|
10710
10757
|
};
|
|
10711
10758
|
await writeConfig(config, absRoot);
|
|
10712
10759
|
await writeRoadmap(roadmap, absRoot);
|
|
10713
|
-
const gitignorePath =
|
|
10760
|
+
const gitignorePath = join18(wrapDir, ".gitignore");
|
|
10714
10761
|
await ensureGitignoreEntries(gitignorePath, STORY_GITIGNORE_ENTRIES);
|
|
10715
10762
|
const warnings = [];
|
|
10716
10763
|
if (options.force && exists) {
|
|
@@ -10758,7 +10805,7 @@ var init_init = __esm({
|
|
|
10758
10805
|
// src/mcp/index.ts
|
|
10759
10806
|
var mcp_exports = {};
|
|
10760
10807
|
import { realpathSync as realpathSync2, existsSync as existsSync11 } from "fs";
|
|
10761
|
-
import { resolve as resolve8, join as
|
|
10808
|
+
import { resolve as resolve8, join as join19, isAbsolute } from "path";
|
|
10762
10809
|
import { z as z11 } from "zod";
|
|
10763
10810
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10764
10811
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -10773,7 +10820,7 @@ function tryDiscoverRoot() {
|
|
|
10773
10820
|
const resolved = resolve8(envRoot);
|
|
10774
10821
|
try {
|
|
10775
10822
|
const canonical = realpathSync2(resolved);
|
|
10776
|
-
if (existsSync11(
|
|
10823
|
+
if (existsSync11(join19(canonical, CONFIG_PATH2))) {
|
|
10777
10824
|
return canonical;
|
|
10778
10825
|
}
|
|
10779
10826
|
process.stderr.write(`Warning: No .story/config.json at ${canonical}
|
|
@@ -10876,7 +10923,7 @@ var init_mcp = __esm({
|
|
|
10876
10923
|
init_init();
|
|
10877
10924
|
ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
|
|
10878
10925
|
CONFIG_PATH2 = ".story/config.json";
|
|
10879
|
-
version = "0.1.
|
|
10926
|
+
version = "0.1.42";
|
|
10880
10927
|
main().catch((err) => {
|
|
10881
10928
|
process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}
|
|
10882
10929
|
`);
|
|
@@ -10912,7 +10959,7 @@ __export(run_exports, {
|
|
|
10912
10959
|
runReadCommand: () => runReadCommand,
|
|
10913
10960
|
writeOutput: () => writeOutput
|
|
10914
10961
|
});
|
|
10915
|
-
import { join as
|
|
10962
|
+
import { join as join20 } from "path";
|
|
10916
10963
|
function writeOutput(text) {
|
|
10917
10964
|
try {
|
|
10918
10965
|
process.stdout.write(text + "\n");
|
|
@@ -10940,7 +10987,7 @@ async function runReadCommand(format, handler) {
|
|
|
10940
10987
|
return;
|
|
10941
10988
|
}
|
|
10942
10989
|
const { state, warnings } = await loadProject(root);
|
|
10943
|
-
const handoversDir =
|
|
10990
|
+
const handoversDir = join20(root, ".story", "handovers");
|
|
10944
10991
|
const result = await handler({ state, warnings, root, handoversDir, format });
|
|
10945
10992
|
writeOutput(result.output);
|
|
10946
10993
|
let exitCode = result.exitCode ?? ExitCode.OK;
|
|
@@ -10975,7 +11022,7 @@ async function runDeleteCommand(format, force, handler) {
|
|
|
10975
11022
|
return;
|
|
10976
11023
|
}
|
|
10977
11024
|
const { state, warnings } = await loadProject(root);
|
|
10978
|
-
const handoversDir =
|
|
11025
|
+
const handoversDir = join20(root, ".story", "handovers");
|
|
10979
11026
|
if (!force && hasIntegrityWarnings(warnings)) {
|
|
10980
11027
|
writeOutput(
|
|
10981
11028
|
formatError(
|
|
@@ -11489,19 +11536,19 @@ __export(setup_skill_exports, {
|
|
|
11489
11536
|
});
|
|
11490
11537
|
import { mkdir as mkdir5, writeFile as writeFile3, readFile as readFile5, rm, rename as rename2, unlink as unlink3 } from "fs/promises";
|
|
11491
11538
|
import { existsSync as existsSync12 } from "fs";
|
|
11492
|
-
import { join as
|
|
11539
|
+
import { join as join21, dirname as dirname5 } from "path";
|
|
11493
11540
|
import { homedir } from "os";
|
|
11494
11541
|
import { execFileSync } from "child_process";
|
|
11495
|
-
import { fileURLToPath as
|
|
11542
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
11496
11543
|
function log(msg) {
|
|
11497
11544
|
process.stdout.write(msg + "\n");
|
|
11498
11545
|
}
|
|
11499
11546
|
function resolveSkillSourceDir() {
|
|
11500
|
-
const thisDir =
|
|
11501
|
-
const bundledPath =
|
|
11502
|
-
if (existsSync12(
|
|
11503
|
-
const sourcePath =
|
|
11504
|
-
if (existsSync12(
|
|
11547
|
+
const thisDir = dirname5(fileURLToPath4(import.meta.url));
|
|
11548
|
+
const bundledPath = join21(thisDir, "..", "src", "skill");
|
|
11549
|
+
if (existsSync12(join21(bundledPath, "SKILL.md"))) return bundledPath;
|
|
11550
|
+
const sourcePath = join21(thisDir, "..", "..", "skill");
|
|
11551
|
+
if (existsSync12(join21(sourcePath, "SKILL.md"))) return sourcePath;
|
|
11505
11552
|
throw new Error(
|
|
11506
11553
|
`Cannot find bundled skill files. Checked:
|
|
11507
11554
|
${bundledPath}
|
|
@@ -11514,7 +11561,7 @@ function isHookWithCommand(entry, command) {
|
|
|
11514
11561
|
return e.type === "command" && typeof e.command === "string" && e.command.trim() === command;
|
|
11515
11562
|
}
|
|
11516
11563
|
async function registerHook(hookType, hookEntry, settingsPath, matcher) {
|
|
11517
|
-
const path2 = settingsPath ??
|
|
11564
|
+
const path2 = settingsPath ?? join21(homedir(), ".claude", "settings.json");
|
|
11518
11565
|
let raw = "{}";
|
|
11519
11566
|
if (existsSync12(path2)) {
|
|
11520
11567
|
try {
|
|
@@ -11586,7 +11633,7 @@ async function registerHook(hookType, hookEntry, settingsPath, matcher) {
|
|
|
11586
11633
|
}
|
|
11587
11634
|
const tmpPath = `${path2}.${process.pid}.tmp`;
|
|
11588
11635
|
try {
|
|
11589
|
-
const dir =
|
|
11636
|
+
const dir = dirname5(path2);
|
|
11590
11637
|
await mkdir5(dir, { recursive: true });
|
|
11591
11638
|
await writeFile3(tmpPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
11592
11639
|
await rename2(tmpPath, path2);
|
|
@@ -11612,7 +11659,7 @@ async function registerStopHook(settingsPath) {
|
|
|
11612
11659
|
return registerHook("Stop", { type: "command", command: STOP_HOOK_COMMAND, async: true }, settingsPath);
|
|
11613
11660
|
}
|
|
11614
11661
|
async function removeHook(hookType, command, settingsPath) {
|
|
11615
|
-
const path2 = settingsPath ??
|
|
11662
|
+
const path2 = settingsPath ?? join21(homedir(), ".claude", "settings.json");
|
|
11616
11663
|
let raw = "{}";
|
|
11617
11664
|
if (existsSync12(path2)) {
|
|
11618
11665
|
try {
|
|
@@ -11644,7 +11691,7 @@ async function removeHook(hookType, command, settingsPath) {
|
|
|
11644
11691
|
if (!removed) return "not_found";
|
|
11645
11692
|
const tmpPath = `${path2}.${process.pid}.tmp`;
|
|
11646
11693
|
try {
|
|
11647
|
-
const dir =
|
|
11694
|
+
const dir = dirname5(path2);
|
|
11648
11695
|
await mkdir5(dir, { recursive: true });
|
|
11649
11696
|
await writeFile3(tmpPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
11650
11697
|
await rename2(tmpPath, path2);
|
|
@@ -11659,7 +11706,7 @@ async function removeHook(hookType, command, settingsPath) {
|
|
|
11659
11706
|
}
|
|
11660
11707
|
async function handleSetupSkill(options = {}) {
|
|
11661
11708
|
const { skipHooks = false } = options;
|
|
11662
|
-
const skillDir =
|
|
11709
|
+
const skillDir = join21(homedir(), ".claude", "skills", "story");
|
|
11663
11710
|
await mkdir5(skillDir, { recursive: true });
|
|
11664
11711
|
let srcSkillDir;
|
|
11665
11712
|
try {
|
|
@@ -11672,19 +11719,19 @@ async function handleSetupSkill(options = {}) {
|
|
|
11672
11719
|
process.exitCode = 1;
|
|
11673
11720
|
return;
|
|
11674
11721
|
}
|
|
11675
|
-
const oldPrimeDir =
|
|
11722
|
+
const oldPrimeDir = join21(homedir(), ".claude", "skills", "prime");
|
|
11676
11723
|
if (existsSync12(oldPrimeDir)) {
|
|
11677
11724
|
await rm(oldPrimeDir, { recursive: true, force: true });
|
|
11678
11725
|
log("Removed old /prime skill (migrated to /story)");
|
|
11679
11726
|
}
|
|
11680
|
-
const existed = existsSync12(
|
|
11681
|
-
const skillContent = await readFile5(
|
|
11682
|
-
await writeFile3(
|
|
11727
|
+
const existed = existsSync12(join21(skillDir, "SKILL.md"));
|
|
11728
|
+
const skillContent = await readFile5(join21(srcSkillDir, "SKILL.md"), "utf-8");
|
|
11729
|
+
await writeFile3(join21(skillDir, "SKILL.md"), skillContent, "utf-8");
|
|
11683
11730
|
let referenceWritten = false;
|
|
11684
|
-
const refSrcPath =
|
|
11731
|
+
const refSrcPath = join21(srcSkillDir, "reference.md");
|
|
11685
11732
|
if (existsSync12(refSrcPath)) {
|
|
11686
11733
|
const refContent = await readFile5(refSrcPath, "utf-8");
|
|
11687
|
-
await writeFile3(
|
|
11734
|
+
await writeFile3(join21(skillDir, "reference.md"), refContent, "utf-8");
|
|
11688
11735
|
referenceWritten = true;
|
|
11689
11736
|
}
|
|
11690
11737
|
log(`${existed ? "Updated" : "Installed"} /story skill at ${skillDir}/`);
|
|
@@ -11798,8 +11845,8 @@ var hook_status_exports = {};
|
|
|
11798
11845
|
__export(hook_status_exports, {
|
|
11799
11846
|
handleHookStatus: () => handleHookStatus
|
|
11800
11847
|
});
|
|
11801
|
-
import { readFileSync as
|
|
11802
|
-
import { join as
|
|
11848
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync4, renameSync as renameSync2, unlinkSync as unlinkSync4 } from "fs";
|
|
11849
|
+
import { join as join22 } from "path";
|
|
11803
11850
|
async function readStdinSilent() {
|
|
11804
11851
|
try {
|
|
11805
11852
|
const chunks = [];
|
|
@@ -11849,10 +11896,10 @@ function activePayload(session) {
|
|
|
11849
11896
|
};
|
|
11850
11897
|
}
|
|
11851
11898
|
function ensureGitignore(root) {
|
|
11852
|
-
const gitignorePath =
|
|
11899
|
+
const gitignorePath = join22(root, ".story", ".gitignore");
|
|
11853
11900
|
let existing = "";
|
|
11854
11901
|
try {
|
|
11855
|
-
existing =
|
|
11902
|
+
existing = readFileSync9(gitignorePath, "utf-8");
|
|
11856
11903
|
} catch {
|
|
11857
11904
|
}
|
|
11858
11905
|
const lines = existing.split("\n").map((l) => l.trim());
|
|
@@ -11868,7 +11915,7 @@ function ensureGitignore(root) {
|
|
|
11868
11915
|
}
|
|
11869
11916
|
function writeStatus(root, payload) {
|
|
11870
11917
|
ensureGitignore(root);
|
|
11871
|
-
const statusPath =
|
|
11918
|
+
const statusPath = join22(root, ".story", "status.json");
|
|
11872
11919
|
const content = JSON.stringify(payload, null, 2) + "\n";
|
|
11873
11920
|
atomicWriteSync(statusPath, content);
|
|
11874
11921
|
}
|
|
@@ -11927,8 +11974,8 @@ var config_update_exports = {};
|
|
|
11927
11974
|
__export(config_update_exports, {
|
|
11928
11975
|
handleConfigSetOverrides: () => handleConfigSetOverrides
|
|
11929
11976
|
});
|
|
11930
|
-
import { readFileSync as
|
|
11931
|
-
import { join as
|
|
11977
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
11978
|
+
import { join as join23 } from "path";
|
|
11932
11979
|
async function handleConfigSetOverrides(root, format, options) {
|
|
11933
11980
|
const { json: jsonArg, clear } = options;
|
|
11934
11981
|
if (!clear && !jsonArg) {
|
|
@@ -11956,8 +12003,8 @@ async function handleConfigSetOverrides(root, format, options) {
|
|
|
11956
12003
|
}
|
|
11957
12004
|
let resultOverrides = null;
|
|
11958
12005
|
await withProjectLock(root, { strict: false }, async () => {
|
|
11959
|
-
const configPath =
|
|
11960
|
-
const rawContent =
|
|
12006
|
+
const configPath = join23(root, ".story", "config.json");
|
|
12007
|
+
const rawContent = readFileSync10(configPath, "utf-8");
|
|
11961
12008
|
const raw = JSON.parse(rawContent);
|
|
11962
12009
|
if (clear) {
|
|
11963
12010
|
delete raw.recipeOverrides;
|
|
@@ -14300,7 +14347,7 @@ async function runCli() {
|
|
|
14300
14347
|
registerSessionCommand: registerSessionCommand2,
|
|
14301
14348
|
registerRepairCommand: registerRepairCommand2
|
|
14302
14349
|
} = await Promise.resolve().then(() => (init_register(), register_exports));
|
|
14303
|
-
const version2 = "0.1.
|
|
14350
|
+
const version2 = "0.1.42";
|
|
14304
14351
|
class HandledError extends Error {
|
|
14305
14352
|
constructor() {
|
|
14306
14353
|
super("HANDLED_ERROR");
|
package/dist/mcp.js
CHANGED
|
@@ -4096,7 +4096,7 @@ var init_session = __esm({
|
|
|
4096
4096
|
// src/mcp/index.ts
|
|
4097
4097
|
init_esm_shims();
|
|
4098
4098
|
import { realpathSync as realpathSync2, existsSync as existsSync11 } from "fs";
|
|
4099
|
-
import { resolve as resolve8, join as
|
|
4099
|
+
import { resolve as resolve8, join as join19, isAbsolute } from "path";
|
|
4100
4100
|
import { z as z11 } from "zod";
|
|
4101
4101
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4102
4102
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -4149,7 +4149,7 @@ init_errors();
|
|
|
4149
4149
|
init_helpers();
|
|
4150
4150
|
init_types();
|
|
4151
4151
|
import { z as z10 } from "zod";
|
|
4152
|
-
import { join as
|
|
4152
|
+
import { join as join17 } from "path";
|
|
4153
4153
|
|
|
4154
4154
|
// src/cli/commands/status.ts
|
|
4155
4155
|
init_esm_shims();
|
|
@@ -5443,8 +5443,8 @@ init_handover();
|
|
|
5443
5443
|
init_esm_shims();
|
|
5444
5444
|
init_session_types();
|
|
5445
5445
|
init_session();
|
|
5446
|
-
import { readFileSync as
|
|
5447
|
-
import { join as
|
|
5446
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, readdirSync as readdirSync4 } from "fs";
|
|
5447
|
+
import { join as join14 } from "path";
|
|
5448
5448
|
|
|
5449
5449
|
// src/autonomous/state-machine.ts
|
|
5450
5450
|
init_esm_shims();
|
|
@@ -5453,7 +5453,8 @@ var TRANSITIONS = {
|
|
|
5453
5453
|
// start does INIT + LOAD_CONTEXT internally
|
|
5454
5454
|
LOAD_CONTEXT: ["PICK_TICKET"],
|
|
5455
5455
|
// internal (never seen by Claude)
|
|
5456
|
-
PICK_TICKET: ["PLAN", "ISSUE_FIX", "SESSION_END"],
|
|
5456
|
+
PICK_TICKET: ["PLAN", "ISSUE_FIX", "COMPLETE", "SESSION_END"],
|
|
5457
|
+
// COMPLETE for ISS-075 (nothing left to do)
|
|
5457
5458
|
PLAN: ["PLAN_REVIEW"],
|
|
5458
5459
|
PLAN_REVIEW: ["IMPLEMENT", "WRITE_TESTS", "PLAN", "PLAN_REVIEW", "SESSION_END"],
|
|
5459
5460
|
// approve → IMPLEMENT/WRITE_TESTS, reject → PLAN, stay for next round; SESSION_END for tiered exit
|
|
@@ -6013,6 +6014,9 @@ var PickTicketStage = class {
|
|
|
6013
6014
|
}
|
|
6014
6015
|
const topCandidate = candidates.kind === "found" ? candidates.candidates[0] : null;
|
|
6015
6016
|
const hasIssues = highIssues.length > 0;
|
|
6017
|
+
if (!topCandidate && candidates.kind !== "found" && !hasIssues) {
|
|
6018
|
+
return { action: "goto", target: "COMPLETE" };
|
|
6019
|
+
}
|
|
6016
6020
|
return {
|
|
6017
6021
|
instruction: [
|
|
6018
6022
|
"# Pick a Ticket or Issue",
|
|
@@ -6285,7 +6289,7 @@ var PlanReviewStage = class {
|
|
|
6285
6289
|
const risk = ctx.state.ticket?.risk ?? "low";
|
|
6286
6290
|
const minRounds = requiredRounds(risk);
|
|
6287
6291
|
const hasCriticalOrMajor = findings.some(
|
|
6288
|
-
(f) => f.severity === "critical" || f.severity === "major"
|
|
6292
|
+
(f) => (f.severity === "critical" || f.severity === "major") && f.disposition !== "addressed" && f.disposition !== "deferred"
|
|
6289
6293
|
);
|
|
6290
6294
|
if (verdict === "approve" && hasCriticalOrMajor) {
|
|
6291
6295
|
return { action: "retry", instruction: "Contradictory review payload: verdict is 'approve' but critical/major findings are present. Re-run the review or correct the verdict." };
|
|
@@ -6706,7 +6710,7 @@ var CodeReviewStage = class {
|
|
|
6706
6710
|
const risk = ctx.state.ticket?.realizedRisk ?? ctx.state.ticket?.risk ?? "low";
|
|
6707
6711
|
const minRounds = requiredRounds(risk);
|
|
6708
6712
|
const hasCriticalOrMajor = findings.some(
|
|
6709
|
-
(f) => f.severity === "critical" || f.severity === "major"
|
|
6713
|
+
(f) => (f.severity === "critical" || f.severity === "major") && f.disposition !== "addressed" && f.disposition !== "deferred"
|
|
6710
6714
|
);
|
|
6711
6715
|
const planRedirect = findings.some((f) => f.recommendedNextState === "PLAN");
|
|
6712
6716
|
if (verdict === "approve" && hasCriticalOrMajor) {
|
|
@@ -7779,6 +7783,43 @@ init_project_loader();
|
|
|
7779
7783
|
init_snapshot();
|
|
7780
7784
|
init_snapshot();
|
|
7781
7785
|
init_queries();
|
|
7786
|
+
|
|
7787
|
+
// src/autonomous/version-check.ts
|
|
7788
|
+
init_esm_shims();
|
|
7789
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
7790
|
+
import { join as join13, dirname as dirname4 } from "path";
|
|
7791
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7792
|
+
function checkVersionMismatch(runningVersion, installedVersion) {
|
|
7793
|
+
if (!installedVersion) return null;
|
|
7794
|
+
if (runningVersion === "0.0.0-dev") return null;
|
|
7795
|
+
if (runningVersion === installedVersion) return null;
|
|
7796
|
+
return `claudestory MCP server is running v${runningVersion} but v${installedVersion} is installed. Restart Claude Code to load the updated version.`;
|
|
7797
|
+
}
|
|
7798
|
+
function getInstalledVersion() {
|
|
7799
|
+
try {
|
|
7800
|
+
const thisFile = fileURLToPath3(import.meta.url);
|
|
7801
|
+
const candidates = [
|
|
7802
|
+
join13(dirname4(thisFile), "..", "..", "package.json"),
|
|
7803
|
+
join13(dirname4(thisFile), "..", "package.json")
|
|
7804
|
+
];
|
|
7805
|
+
for (const candidate of candidates) {
|
|
7806
|
+
try {
|
|
7807
|
+
const raw = readFileSync6(candidate, "utf-8");
|
|
7808
|
+
const pkg = JSON.parse(raw);
|
|
7809
|
+
if (pkg.version) return pkg.version;
|
|
7810
|
+
} catch {
|
|
7811
|
+
}
|
|
7812
|
+
}
|
|
7813
|
+
return null;
|
|
7814
|
+
} catch {
|
|
7815
|
+
return null;
|
|
7816
|
+
}
|
|
7817
|
+
}
|
|
7818
|
+
function getRunningVersion() {
|
|
7819
|
+
return "0.1.42";
|
|
7820
|
+
}
|
|
7821
|
+
|
|
7822
|
+
// src/autonomous/guide.ts
|
|
7782
7823
|
init_handover();
|
|
7783
7824
|
var RECOVERY_MAPPING = {
|
|
7784
7825
|
PICK_TICKET: { state: "PICK_TICKET", resetPlan: false, resetCode: false },
|
|
@@ -7800,18 +7841,18 @@ var RECOVERY_MAPPING = {
|
|
|
7800
7841
|
function buildGuideRecommendOptions(root) {
|
|
7801
7842
|
const opts = {};
|
|
7802
7843
|
try {
|
|
7803
|
-
const handoversDir =
|
|
7844
|
+
const handoversDir = join14(root, ".story", "handovers");
|
|
7804
7845
|
const files = readdirSync4(handoversDir, "utf-8").filter((f) => f.endsWith(".md")).sort();
|
|
7805
7846
|
if (files.length > 0) {
|
|
7806
|
-
opts.latestHandoverContent =
|
|
7847
|
+
opts.latestHandoverContent = readFileSync7(join14(handoversDir, files[files.length - 1]), "utf-8");
|
|
7807
7848
|
}
|
|
7808
7849
|
} catch {
|
|
7809
7850
|
}
|
|
7810
7851
|
try {
|
|
7811
|
-
const snapshotsDir =
|
|
7852
|
+
const snapshotsDir = join14(root, ".story", "snapshots");
|
|
7812
7853
|
const snapFiles = readdirSync4(snapshotsDir, "utf-8").filter((f) => f.endsWith(".json")).sort();
|
|
7813
7854
|
if (snapFiles.length > 0) {
|
|
7814
|
-
const raw =
|
|
7855
|
+
const raw = readFileSync7(join14(snapshotsDir, snapFiles[snapFiles.length - 1]), "utf-8");
|
|
7815
7856
|
const snap = JSON.parse(raw);
|
|
7816
7857
|
if (snap.issues) {
|
|
7817
7858
|
opts.previousOpenIssueCount = snap.issues.filter((i) => i.status !== "resolved").length;
|
|
@@ -8004,6 +8045,7 @@ async function handleStart(root, args) {
|
|
|
8004
8045
|
for (const stale of staleSessions) {
|
|
8005
8046
|
writeSessionSync(stale.dir, { ...stale.state, status: "superseded" });
|
|
8006
8047
|
}
|
|
8048
|
+
const versionWarning = checkVersionMismatch(getRunningVersion(), getInstalledVersion());
|
|
8007
8049
|
const wsId = deriveWorkspaceId(root);
|
|
8008
8050
|
const mode = args.mode ?? "auto";
|
|
8009
8051
|
if (mode !== "auto" && !args.ticketId) {
|
|
@@ -8198,7 +8240,7 @@ Staged: ${stagedResult.data.join(", ")}`
|
|
|
8198
8240
|
}
|
|
8199
8241
|
}
|
|
8200
8242
|
const { state: projectState, warnings } = await loadProject(root);
|
|
8201
|
-
const handoversDir =
|
|
8243
|
+
const handoversDir = join14(root, ".story", "handovers");
|
|
8202
8244
|
const ctx = { state: projectState, warnings, root, handoversDir, format: "md" };
|
|
8203
8245
|
let handoverText = "";
|
|
8204
8246
|
try {
|
|
@@ -8215,7 +8257,7 @@ Staged: ${stagedResult.data.join(", ")}`
|
|
|
8215
8257
|
}
|
|
8216
8258
|
} catch {
|
|
8217
8259
|
}
|
|
8218
|
-
const rulesText = readFileSafe2(
|
|
8260
|
+
const rulesText = readFileSafe2(join14(root, "RULES.md"));
|
|
8219
8261
|
const lessonDigest = buildLessonDigest(projectState.lessons);
|
|
8220
8262
|
const digestParts = [
|
|
8221
8263
|
handoverText ? `## Recent Handovers
|
|
@@ -8231,7 +8273,7 @@ ${rulesText}` : "",
|
|
|
8231
8273
|
].filter(Boolean);
|
|
8232
8274
|
const digest = digestParts.join("\n\n---\n\n");
|
|
8233
8275
|
try {
|
|
8234
|
-
writeFileSync3(
|
|
8276
|
+
writeFileSync3(join14(dir, "context-digest.md"), digest, "utf-8");
|
|
8235
8277
|
} catch {
|
|
8236
8278
|
}
|
|
8237
8279
|
if (mode !== "auto" && args.ticketId) {
|
|
@@ -8423,7 +8465,8 @@ ${ticket.description}` : "",
|
|
|
8423
8465
|
"Do NOT use Claude Code's plan mode \u2014 write plans as markdown files.",
|
|
8424
8466
|
"Do NOT ask the user for confirmation or approval.",
|
|
8425
8467
|
"Do NOT stop or summarize between tickets \u2014 call autonomous_guide IMMEDIATELY.",
|
|
8426
|
-
"You are in autonomous mode \u2014 continue working until done."
|
|
8468
|
+
"You are in autonomous mode \u2014 continue working until done.",
|
|
8469
|
+
...versionWarning ? [`**Warning:** ${versionWarning}`] : []
|
|
8427
8470
|
],
|
|
8428
8471
|
transitionedFrom: "INIT"
|
|
8429
8472
|
});
|
|
@@ -8950,7 +8993,7 @@ function guideError(err) {
|
|
|
8950
8993
|
}
|
|
8951
8994
|
function readFileSafe2(path2) {
|
|
8952
8995
|
try {
|
|
8953
|
-
return
|
|
8996
|
+
return readFileSync7(path2, "utf-8");
|
|
8954
8997
|
} catch {
|
|
8955
8998
|
return "";
|
|
8956
8999
|
}
|
|
@@ -8960,8 +9003,8 @@ function readFileSafe2(path2) {
|
|
|
8960
9003
|
init_esm_shims();
|
|
8961
9004
|
init_session();
|
|
8962
9005
|
init_session_types();
|
|
8963
|
-
import { readFileSync as
|
|
8964
|
-
import { join as
|
|
9006
|
+
import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
|
|
9007
|
+
import { join as join15 } from "path";
|
|
8965
9008
|
|
|
8966
9009
|
// src/core/session-report-formatter.ts
|
|
8967
9010
|
init_esm_shims();
|
|
@@ -9175,7 +9218,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9175
9218
|
isError: true
|
|
9176
9219
|
};
|
|
9177
9220
|
}
|
|
9178
|
-
const statePath2 =
|
|
9221
|
+
const statePath2 = join15(dir, "state.json");
|
|
9179
9222
|
if (!existsSync10(statePath2)) {
|
|
9180
9223
|
return {
|
|
9181
9224
|
output: `Error: Session ${sessionId} corrupt \u2014 state.json missing.`,
|
|
@@ -9185,7 +9228,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9185
9228
|
};
|
|
9186
9229
|
}
|
|
9187
9230
|
try {
|
|
9188
|
-
const rawJson = JSON.parse(
|
|
9231
|
+
const rawJson = JSON.parse(readFileSync8(statePath2, "utf-8"));
|
|
9189
9232
|
if (rawJson && typeof rawJson === "object" && "schemaVersion" in rawJson && rawJson.schemaVersion !== CURRENT_SESSION_SCHEMA_VERSION) {
|
|
9190
9233
|
return {
|
|
9191
9234
|
output: `Error: Session ${sessionId} \u2014 unsupported session schema version ${rawJson.schemaVersion}.`,
|
|
@@ -9214,7 +9257,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9214
9257
|
const events = readEvents(dir);
|
|
9215
9258
|
let planContent = null;
|
|
9216
9259
|
try {
|
|
9217
|
-
planContent =
|
|
9260
|
+
planContent = readFileSync8(join15(dir, "plan.md"), "utf-8");
|
|
9218
9261
|
} catch {
|
|
9219
9262
|
}
|
|
9220
9263
|
let gitLog = null;
|
|
@@ -9239,7 +9282,7 @@ init_issue();
|
|
|
9239
9282
|
init_roadmap();
|
|
9240
9283
|
init_output_formatter();
|
|
9241
9284
|
init_helpers();
|
|
9242
|
-
import { join as
|
|
9285
|
+
import { join as join16, resolve as resolve6 } from "path";
|
|
9243
9286
|
var PHASE_ID_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
9244
9287
|
var PHASE_ID_MAX_LENGTH = 40;
|
|
9245
9288
|
function validatePhaseId(id) {
|
|
@@ -9348,7 +9391,7 @@ function formatMcpError(code, message) {
|
|
|
9348
9391
|
async function runMcpReadTool(pinnedRoot, handler) {
|
|
9349
9392
|
try {
|
|
9350
9393
|
const { state, warnings } = await loadProject(pinnedRoot);
|
|
9351
|
-
const handoversDir =
|
|
9394
|
+
const handoversDir = join17(pinnedRoot, ".story", "handovers");
|
|
9352
9395
|
const ctx = { state, warnings, root: pinnedRoot, handoversDir, format: "md" };
|
|
9353
9396
|
const result = await handler(ctx);
|
|
9354
9397
|
if (result.errorCode && INFRASTRUCTURE_ERROR_CODES.includes(result.errorCode)) {
|
|
@@ -9906,10 +9949,10 @@ init_esm_shims();
|
|
|
9906
9949
|
init_project_loader();
|
|
9907
9950
|
init_errors();
|
|
9908
9951
|
import { mkdir as mkdir4, stat as stat2, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
9909
|
-
import { join as
|
|
9952
|
+
import { join as join18, resolve as resolve7 } from "path";
|
|
9910
9953
|
async function initProject(root, options) {
|
|
9911
9954
|
const absRoot = resolve7(root);
|
|
9912
|
-
const wrapDir =
|
|
9955
|
+
const wrapDir = join18(absRoot, ".story");
|
|
9913
9956
|
let exists = false;
|
|
9914
9957
|
try {
|
|
9915
9958
|
const s = await stat2(wrapDir);
|
|
@@ -9929,11 +9972,11 @@ async function initProject(root, options) {
|
|
|
9929
9972
|
".story/ already exists. Use --force to overwrite config and roadmap."
|
|
9930
9973
|
);
|
|
9931
9974
|
}
|
|
9932
|
-
await mkdir4(
|
|
9933
|
-
await mkdir4(
|
|
9934
|
-
await mkdir4(
|
|
9935
|
-
await mkdir4(
|
|
9936
|
-
await mkdir4(
|
|
9975
|
+
await mkdir4(join18(wrapDir, "tickets"), { recursive: true });
|
|
9976
|
+
await mkdir4(join18(wrapDir, "issues"), { recursive: true });
|
|
9977
|
+
await mkdir4(join18(wrapDir, "handovers"), { recursive: true });
|
|
9978
|
+
await mkdir4(join18(wrapDir, "notes"), { recursive: true });
|
|
9979
|
+
await mkdir4(join18(wrapDir, "lessons"), { recursive: true });
|
|
9937
9980
|
const created = [
|
|
9938
9981
|
".story/config.json",
|
|
9939
9982
|
".story/roadmap.json",
|
|
@@ -9973,7 +10016,7 @@ async function initProject(root, options) {
|
|
|
9973
10016
|
};
|
|
9974
10017
|
await writeConfig(config, absRoot);
|
|
9975
10018
|
await writeRoadmap(roadmap, absRoot);
|
|
9976
|
-
const gitignorePath =
|
|
10019
|
+
const gitignorePath = join18(wrapDir, ".gitignore");
|
|
9977
10020
|
await ensureGitignoreEntries(gitignorePath, STORY_GITIGNORE_ENTRIES);
|
|
9978
10021
|
const warnings = [];
|
|
9979
10022
|
if (options.force && exists) {
|
|
@@ -10012,7 +10055,7 @@ async function ensureGitignoreEntries(gitignorePath, entries) {
|
|
|
10012
10055
|
// src/mcp/index.ts
|
|
10013
10056
|
var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
|
|
10014
10057
|
var CONFIG_PATH2 = ".story/config.json";
|
|
10015
|
-
var version = "0.1.
|
|
10058
|
+
var version = "0.1.42";
|
|
10016
10059
|
function tryDiscoverRoot() {
|
|
10017
10060
|
const envRoot = process.env[ENV_VAR2];
|
|
10018
10061
|
if (envRoot) {
|
|
@@ -10024,7 +10067,7 @@ function tryDiscoverRoot() {
|
|
|
10024
10067
|
const resolved = resolve8(envRoot);
|
|
10025
10068
|
try {
|
|
10026
10069
|
const canonical = realpathSync2(resolved);
|
|
10027
|
-
if (existsSync11(
|
|
10070
|
+
if (existsSync11(join19(canonical, CONFIG_PATH2))) {
|
|
10028
10071
|
return canonical;
|
|
10029
10072
|
}
|
|
10030
10073
|
process.stderr.write(`Warning: No .story/config.json at ${canonical}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anthropologies/claudestory",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.42",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"description": "Cross-session context persistence for AI coding projects. Tracks tickets, issues, roadmap, and handovers so every session builds on the last.",
|
|
6
6
|
"keywords": [
|