@anthropologies/claudestory 0.1.41 → 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 +107 -64
- package/dist/mcp.js +69 -30
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8327,24 +8327,64 @@ var init_stages = __esm({
|
|
|
8327
8327
|
}
|
|
8328
8328
|
});
|
|
8329
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
|
+
|
|
8330
8370
|
// src/autonomous/guide.ts
|
|
8331
|
-
import { readFileSync as
|
|
8332
|
-
import { join as
|
|
8371
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, readdirSync as readdirSync4 } from "fs";
|
|
8372
|
+
import { join as join14 } from "path";
|
|
8333
8373
|
function buildGuideRecommendOptions(root) {
|
|
8334
8374
|
const opts = {};
|
|
8335
8375
|
try {
|
|
8336
|
-
const handoversDir =
|
|
8376
|
+
const handoversDir = join14(root, ".story", "handovers");
|
|
8337
8377
|
const files = readdirSync4(handoversDir, "utf-8").filter((f) => f.endsWith(".md")).sort();
|
|
8338
8378
|
if (files.length > 0) {
|
|
8339
|
-
opts.latestHandoverContent =
|
|
8379
|
+
opts.latestHandoverContent = readFileSync7(join14(handoversDir, files[files.length - 1]), "utf-8");
|
|
8340
8380
|
}
|
|
8341
8381
|
} catch {
|
|
8342
8382
|
}
|
|
8343
8383
|
try {
|
|
8344
|
-
const snapshotsDir =
|
|
8384
|
+
const snapshotsDir = join14(root, ".story", "snapshots");
|
|
8345
8385
|
const snapFiles = readdirSync4(snapshotsDir, "utf-8").filter((f) => f.endsWith(".json")).sort();
|
|
8346
8386
|
if (snapFiles.length > 0) {
|
|
8347
|
-
const raw =
|
|
8387
|
+
const raw = readFileSync7(join14(snapshotsDir, snapFiles[snapFiles.length - 1]), "utf-8");
|
|
8348
8388
|
const snap = JSON.parse(raw);
|
|
8349
8389
|
if (snap.issues) {
|
|
8350
8390
|
opts.previousOpenIssueCount = snap.issues.filter((i) => i.status !== "resolved").length;
|
|
@@ -8531,6 +8571,7 @@ async function handleStart(root, args) {
|
|
|
8531
8571
|
for (const stale of staleSessions) {
|
|
8532
8572
|
writeSessionSync(stale.dir, { ...stale.state, status: "superseded" });
|
|
8533
8573
|
}
|
|
8574
|
+
const versionWarning = checkVersionMismatch(getRunningVersion(), getInstalledVersion());
|
|
8534
8575
|
const wsId = deriveWorkspaceId(root);
|
|
8535
8576
|
const mode = args.mode ?? "auto";
|
|
8536
8577
|
if (mode !== "auto" && !args.ticketId) {
|
|
@@ -8725,7 +8766,7 @@ Staged: ${stagedResult.data.join(", ")}`
|
|
|
8725
8766
|
}
|
|
8726
8767
|
}
|
|
8727
8768
|
const { state: projectState, warnings } = await loadProject(root);
|
|
8728
|
-
const handoversDir =
|
|
8769
|
+
const handoversDir = join14(root, ".story", "handovers");
|
|
8729
8770
|
const ctx = { state: projectState, warnings, root, handoversDir, format: "md" };
|
|
8730
8771
|
let handoverText = "";
|
|
8731
8772
|
try {
|
|
@@ -8742,7 +8783,7 @@ Staged: ${stagedResult.data.join(", ")}`
|
|
|
8742
8783
|
}
|
|
8743
8784
|
} catch {
|
|
8744
8785
|
}
|
|
8745
|
-
const rulesText = readFileSafe2(
|
|
8786
|
+
const rulesText = readFileSafe2(join14(root, "RULES.md"));
|
|
8746
8787
|
const lessonDigest = buildLessonDigest(projectState.lessons);
|
|
8747
8788
|
const digestParts = [
|
|
8748
8789
|
handoverText ? `## Recent Handovers
|
|
@@ -8758,7 +8799,7 @@ ${rulesText}` : "",
|
|
|
8758
8799
|
].filter(Boolean);
|
|
8759
8800
|
const digest = digestParts.join("\n\n---\n\n");
|
|
8760
8801
|
try {
|
|
8761
|
-
writeFileSync3(
|
|
8802
|
+
writeFileSync3(join14(dir, "context-digest.md"), digest, "utf-8");
|
|
8762
8803
|
} catch {
|
|
8763
8804
|
}
|
|
8764
8805
|
if (mode !== "auto" && args.ticketId) {
|
|
@@ -8950,7 +8991,8 @@ ${ticket.description}` : "",
|
|
|
8950
8991
|
"Do NOT use Claude Code's plan mode \u2014 write plans as markdown files.",
|
|
8951
8992
|
"Do NOT ask the user for confirmation or approval.",
|
|
8952
8993
|
"Do NOT stop or summarize between tickets \u2014 call autonomous_guide IMMEDIATELY.",
|
|
8953
|
-
"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}`] : []
|
|
8954
8996
|
],
|
|
8955
8997
|
transitionedFrom: "INIT"
|
|
8956
8998
|
});
|
|
@@ -9476,7 +9518,7 @@ function guideError(err) {
|
|
|
9476
9518
|
}
|
|
9477
9519
|
function readFileSafe2(path2) {
|
|
9478
9520
|
try {
|
|
9479
|
-
return
|
|
9521
|
+
return readFileSync7(path2, "utf-8");
|
|
9480
9522
|
} catch {
|
|
9481
9523
|
return "";
|
|
9482
9524
|
}
|
|
@@ -9502,6 +9544,7 @@ var init_guide = __esm({
|
|
|
9502
9544
|
init_snapshot();
|
|
9503
9545
|
init_queries();
|
|
9504
9546
|
init_recommend();
|
|
9547
|
+
init_version_check();
|
|
9505
9548
|
init_handover();
|
|
9506
9549
|
RECOVERY_MAPPING = {
|
|
9507
9550
|
PICK_TICKET: { state: "PICK_TICKET", resetPlan: false, resetCode: false },
|
|
@@ -9728,8 +9771,8 @@ var init_session_report_formatter = __esm({
|
|
|
9728
9771
|
});
|
|
9729
9772
|
|
|
9730
9773
|
// src/cli/commands/session-report.ts
|
|
9731
|
-
import { readFileSync as
|
|
9732
|
-
import { join as
|
|
9774
|
+
import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
|
|
9775
|
+
import { join as join15 } from "path";
|
|
9733
9776
|
async function handleSessionReport(sessionId, root, format = "md") {
|
|
9734
9777
|
if (!UUID_REGEX.test(sessionId)) {
|
|
9735
9778
|
return {
|
|
@@ -9748,7 +9791,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9748
9791
|
isError: true
|
|
9749
9792
|
};
|
|
9750
9793
|
}
|
|
9751
|
-
const statePath2 =
|
|
9794
|
+
const statePath2 = join15(dir, "state.json");
|
|
9752
9795
|
if (!existsSync10(statePath2)) {
|
|
9753
9796
|
return {
|
|
9754
9797
|
output: `Error: Session ${sessionId} corrupt \u2014 state.json missing.`,
|
|
@@ -9758,7 +9801,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9758
9801
|
};
|
|
9759
9802
|
}
|
|
9760
9803
|
try {
|
|
9761
|
-
const rawJson = JSON.parse(
|
|
9804
|
+
const rawJson = JSON.parse(readFileSync8(statePath2, "utf-8"));
|
|
9762
9805
|
if (rawJson && typeof rawJson === "object" && "schemaVersion" in rawJson && rawJson.schemaVersion !== CURRENT_SESSION_SCHEMA_VERSION) {
|
|
9763
9806
|
return {
|
|
9764
9807
|
output: `Error: Session ${sessionId} \u2014 unsupported session schema version ${rawJson.schemaVersion}.`,
|
|
@@ -9787,7 +9830,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9787
9830
|
const events = readEvents(dir);
|
|
9788
9831
|
let planContent = null;
|
|
9789
9832
|
try {
|
|
9790
|
-
planContent =
|
|
9833
|
+
planContent = readFileSync8(join15(dir, "plan.md"), "utf-8");
|
|
9791
9834
|
} catch {
|
|
9792
9835
|
}
|
|
9793
9836
|
let gitLog = null;
|
|
@@ -9816,7 +9859,7 @@ var init_session_report = __esm({
|
|
|
9816
9859
|
});
|
|
9817
9860
|
|
|
9818
9861
|
// src/cli/commands/phase.ts
|
|
9819
|
-
import { join as
|
|
9862
|
+
import { join as join16, resolve as resolve6 } from "path";
|
|
9820
9863
|
function validatePhaseId(id) {
|
|
9821
9864
|
if (id.length > PHASE_ID_MAX_LENGTH) {
|
|
9822
9865
|
throw new CliValidationError("invalid_input", `Phase ID "${id}" exceeds ${PHASE_ID_MAX_LENGTH} characters`);
|
|
@@ -10005,21 +10048,21 @@ async function handlePhaseDelete(id, reassign, format, root) {
|
|
|
10005
10048
|
const updated = { ...ticket, phase: reassign, order: maxOrder };
|
|
10006
10049
|
const parsed = TicketSchema.parse(updated);
|
|
10007
10050
|
const content = serializeJSON(parsed);
|
|
10008
|
-
const target =
|
|
10051
|
+
const target = join16(wrapDir, "tickets", `${parsed.id}.json`);
|
|
10009
10052
|
operations.push({ op: "write", target, content });
|
|
10010
10053
|
}
|
|
10011
10054
|
for (const issue of affectedIssues) {
|
|
10012
10055
|
const updated = { ...issue, phase: reassign };
|
|
10013
10056
|
const parsed = IssueSchema.parse(updated);
|
|
10014
10057
|
const content = serializeJSON(parsed);
|
|
10015
|
-
const target =
|
|
10058
|
+
const target = join16(wrapDir, "issues", `${parsed.id}.json`);
|
|
10016
10059
|
operations.push({ op: "write", target, content });
|
|
10017
10060
|
}
|
|
10018
10061
|
const newPhases = state.roadmap.phases.filter((p) => p.id !== id);
|
|
10019
10062
|
const newRoadmap = { ...state.roadmap, phases: newPhases };
|
|
10020
10063
|
const parsedRoadmap = RoadmapSchema.parse(newRoadmap);
|
|
10021
10064
|
const roadmapContent = serializeJSON(parsedRoadmap);
|
|
10022
|
-
const roadmapTarget =
|
|
10065
|
+
const roadmapTarget = join16(wrapDir, "roadmap.json");
|
|
10023
10066
|
operations.push({ op: "write", target: roadmapTarget, content: roadmapContent });
|
|
10024
10067
|
await runTransactionUnlocked(root, operations);
|
|
10025
10068
|
} else {
|
|
@@ -10052,14 +10095,14 @@ var init_phase = __esm({
|
|
|
10052
10095
|
|
|
10053
10096
|
// src/mcp/tools.ts
|
|
10054
10097
|
import { z as z10 } from "zod";
|
|
10055
|
-
import { join as
|
|
10098
|
+
import { join as join17 } from "path";
|
|
10056
10099
|
function formatMcpError(code, message) {
|
|
10057
10100
|
return `[${code}] ${message}`;
|
|
10058
10101
|
}
|
|
10059
10102
|
async function runMcpReadTool(pinnedRoot, handler) {
|
|
10060
10103
|
try {
|
|
10061
10104
|
const { state, warnings } = await loadProject(pinnedRoot);
|
|
10062
|
-
const handoversDir =
|
|
10105
|
+
const handoversDir = join17(pinnedRoot, ".story", "handovers");
|
|
10063
10106
|
const ctx = { state, warnings, root: pinnedRoot, handoversDir, format: "md" };
|
|
10064
10107
|
const result = await handler(ctx);
|
|
10065
10108
|
if (result.errorCode && INFRASTRUCTURE_ERROR_CODES.includes(result.errorCode)) {
|
|
@@ -10647,10 +10690,10 @@ var init_tools = __esm({
|
|
|
10647
10690
|
|
|
10648
10691
|
// src/core/init.ts
|
|
10649
10692
|
import { mkdir as mkdir4, stat as stat2, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
10650
|
-
import { join as
|
|
10693
|
+
import { join as join18, resolve as resolve7 } from "path";
|
|
10651
10694
|
async function initProject(root, options) {
|
|
10652
10695
|
const absRoot = resolve7(root);
|
|
10653
|
-
const wrapDir =
|
|
10696
|
+
const wrapDir = join18(absRoot, ".story");
|
|
10654
10697
|
let exists = false;
|
|
10655
10698
|
try {
|
|
10656
10699
|
const s = await stat2(wrapDir);
|
|
@@ -10670,11 +10713,11 @@ async function initProject(root, options) {
|
|
|
10670
10713
|
".story/ already exists. Use --force to overwrite config and roadmap."
|
|
10671
10714
|
);
|
|
10672
10715
|
}
|
|
10673
|
-
await mkdir4(
|
|
10674
|
-
await mkdir4(
|
|
10675
|
-
await mkdir4(
|
|
10676
|
-
await mkdir4(
|
|
10677
|
-
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 });
|
|
10678
10721
|
const created = [
|
|
10679
10722
|
".story/config.json",
|
|
10680
10723
|
".story/roadmap.json",
|
|
@@ -10714,7 +10757,7 @@ async function initProject(root, options) {
|
|
|
10714
10757
|
};
|
|
10715
10758
|
await writeConfig(config, absRoot);
|
|
10716
10759
|
await writeRoadmap(roadmap, absRoot);
|
|
10717
|
-
const gitignorePath =
|
|
10760
|
+
const gitignorePath = join18(wrapDir, ".gitignore");
|
|
10718
10761
|
await ensureGitignoreEntries(gitignorePath, STORY_GITIGNORE_ENTRIES);
|
|
10719
10762
|
const warnings = [];
|
|
10720
10763
|
if (options.force && exists) {
|
|
@@ -10762,7 +10805,7 @@ var init_init = __esm({
|
|
|
10762
10805
|
// src/mcp/index.ts
|
|
10763
10806
|
var mcp_exports = {};
|
|
10764
10807
|
import { realpathSync as realpathSync2, existsSync as existsSync11 } from "fs";
|
|
10765
|
-
import { resolve as resolve8, join as
|
|
10808
|
+
import { resolve as resolve8, join as join19, isAbsolute } from "path";
|
|
10766
10809
|
import { z as z11 } from "zod";
|
|
10767
10810
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10768
10811
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -10777,7 +10820,7 @@ function tryDiscoverRoot() {
|
|
|
10777
10820
|
const resolved = resolve8(envRoot);
|
|
10778
10821
|
try {
|
|
10779
10822
|
const canonical = realpathSync2(resolved);
|
|
10780
|
-
if (existsSync11(
|
|
10823
|
+
if (existsSync11(join19(canonical, CONFIG_PATH2))) {
|
|
10781
10824
|
return canonical;
|
|
10782
10825
|
}
|
|
10783
10826
|
process.stderr.write(`Warning: No .story/config.json at ${canonical}
|
|
@@ -10880,7 +10923,7 @@ var init_mcp = __esm({
|
|
|
10880
10923
|
init_init();
|
|
10881
10924
|
ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
|
|
10882
10925
|
CONFIG_PATH2 = ".story/config.json";
|
|
10883
|
-
version = "0.1.
|
|
10926
|
+
version = "0.1.42";
|
|
10884
10927
|
main().catch((err) => {
|
|
10885
10928
|
process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}
|
|
10886
10929
|
`);
|
|
@@ -10916,7 +10959,7 @@ __export(run_exports, {
|
|
|
10916
10959
|
runReadCommand: () => runReadCommand,
|
|
10917
10960
|
writeOutput: () => writeOutput
|
|
10918
10961
|
});
|
|
10919
|
-
import { join as
|
|
10962
|
+
import { join as join20 } from "path";
|
|
10920
10963
|
function writeOutput(text) {
|
|
10921
10964
|
try {
|
|
10922
10965
|
process.stdout.write(text + "\n");
|
|
@@ -10944,7 +10987,7 @@ async function runReadCommand(format, handler) {
|
|
|
10944
10987
|
return;
|
|
10945
10988
|
}
|
|
10946
10989
|
const { state, warnings } = await loadProject(root);
|
|
10947
|
-
const handoversDir =
|
|
10990
|
+
const handoversDir = join20(root, ".story", "handovers");
|
|
10948
10991
|
const result = await handler({ state, warnings, root, handoversDir, format });
|
|
10949
10992
|
writeOutput(result.output);
|
|
10950
10993
|
let exitCode = result.exitCode ?? ExitCode.OK;
|
|
@@ -10979,7 +11022,7 @@ async function runDeleteCommand(format, force, handler) {
|
|
|
10979
11022
|
return;
|
|
10980
11023
|
}
|
|
10981
11024
|
const { state, warnings } = await loadProject(root);
|
|
10982
|
-
const handoversDir =
|
|
11025
|
+
const handoversDir = join20(root, ".story", "handovers");
|
|
10983
11026
|
if (!force && hasIntegrityWarnings(warnings)) {
|
|
10984
11027
|
writeOutput(
|
|
10985
11028
|
formatError(
|
|
@@ -11493,19 +11536,19 @@ __export(setup_skill_exports, {
|
|
|
11493
11536
|
});
|
|
11494
11537
|
import { mkdir as mkdir5, writeFile as writeFile3, readFile as readFile5, rm, rename as rename2, unlink as unlink3 } from "fs/promises";
|
|
11495
11538
|
import { existsSync as existsSync12 } from "fs";
|
|
11496
|
-
import { join as
|
|
11539
|
+
import { join as join21, dirname as dirname5 } from "path";
|
|
11497
11540
|
import { homedir } from "os";
|
|
11498
11541
|
import { execFileSync } from "child_process";
|
|
11499
|
-
import { fileURLToPath as
|
|
11542
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
11500
11543
|
function log(msg) {
|
|
11501
11544
|
process.stdout.write(msg + "\n");
|
|
11502
11545
|
}
|
|
11503
11546
|
function resolveSkillSourceDir() {
|
|
11504
|
-
const thisDir =
|
|
11505
|
-
const bundledPath =
|
|
11506
|
-
if (existsSync12(
|
|
11507
|
-
const sourcePath =
|
|
11508
|
-
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;
|
|
11509
11552
|
throw new Error(
|
|
11510
11553
|
`Cannot find bundled skill files. Checked:
|
|
11511
11554
|
${bundledPath}
|
|
@@ -11518,7 +11561,7 @@ function isHookWithCommand(entry, command) {
|
|
|
11518
11561
|
return e.type === "command" && typeof e.command === "string" && e.command.trim() === command;
|
|
11519
11562
|
}
|
|
11520
11563
|
async function registerHook(hookType, hookEntry, settingsPath, matcher) {
|
|
11521
|
-
const path2 = settingsPath ??
|
|
11564
|
+
const path2 = settingsPath ?? join21(homedir(), ".claude", "settings.json");
|
|
11522
11565
|
let raw = "{}";
|
|
11523
11566
|
if (existsSync12(path2)) {
|
|
11524
11567
|
try {
|
|
@@ -11590,7 +11633,7 @@ async function registerHook(hookType, hookEntry, settingsPath, matcher) {
|
|
|
11590
11633
|
}
|
|
11591
11634
|
const tmpPath = `${path2}.${process.pid}.tmp`;
|
|
11592
11635
|
try {
|
|
11593
|
-
const dir =
|
|
11636
|
+
const dir = dirname5(path2);
|
|
11594
11637
|
await mkdir5(dir, { recursive: true });
|
|
11595
11638
|
await writeFile3(tmpPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
11596
11639
|
await rename2(tmpPath, path2);
|
|
@@ -11616,7 +11659,7 @@ async function registerStopHook(settingsPath) {
|
|
|
11616
11659
|
return registerHook("Stop", { type: "command", command: STOP_HOOK_COMMAND, async: true }, settingsPath);
|
|
11617
11660
|
}
|
|
11618
11661
|
async function removeHook(hookType, command, settingsPath) {
|
|
11619
|
-
const path2 = settingsPath ??
|
|
11662
|
+
const path2 = settingsPath ?? join21(homedir(), ".claude", "settings.json");
|
|
11620
11663
|
let raw = "{}";
|
|
11621
11664
|
if (existsSync12(path2)) {
|
|
11622
11665
|
try {
|
|
@@ -11648,7 +11691,7 @@ async function removeHook(hookType, command, settingsPath) {
|
|
|
11648
11691
|
if (!removed) return "not_found";
|
|
11649
11692
|
const tmpPath = `${path2}.${process.pid}.tmp`;
|
|
11650
11693
|
try {
|
|
11651
|
-
const dir =
|
|
11694
|
+
const dir = dirname5(path2);
|
|
11652
11695
|
await mkdir5(dir, { recursive: true });
|
|
11653
11696
|
await writeFile3(tmpPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
11654
11697
|
await rename2(tmpPath, path2);
|
|
@@ -11663,7 +11706,7 @@ async function removeHook(hookType, command, settingsPath) {
|
|
|
11663
11706
|
}
|
|
11664
11707
|
async function handleSetupSkill(options = {}) {
|
|
11665
11708
|
const { skipHooks = false } = options;
|
|
11666
|
-
const skillDir =
|
|
11709
|
+
const skillDir = join21(homedir(), ".claude", "skills", "story");
|
|
11667
11710
|
await mkdir5(skillDir, { recursive: true });
|
|
11668
11711
|
let srcSkillDir;
|
|
11669
11712
|
try {
|
|
@@ -11676,19 +11719,19 @@ async function handleSetupSkill(options = {}) {
|
|
|
11676
11719
|
process.exitCode = 1;
|
|
11677
11720
|
return;
|
|
11678
11721
|
}
|
|
11679
|
-
const oldPrimeDir =
|
|
11722
|
+
const oldPrimeDir = join21(homedir(), ".claude", "skills", "prime");
|
|
11680
11723
|
if (existsSync12(oldPrimeDir)) {
|
|
11681
11724
|
await rm(oldPrimeDir, { recursive: true, force: true });
|
|
11682
11725
|
log("Removed old /prime skill (migrated to /story)");
|
|
11683
11726
|
}
|
|
11684
|
-
const existed = existsSync12(
|
|
11685
|
-
const skillContent = await readFile5(
|
|
11686
|
-
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");
|
|
11687
11730
|
let referenceWritten = false;
|
|
11688
|
-
const refSrcPath =
|
|
11731
|
+
const refSrcPath = join21(srcSkillDir, "reference.md");
|
|
11689
11732
|
if (existsSync12(refSrcPath)) {
|
|
11690
11733
|
const refContent = await readFile5(refSrcPath, "utf-8");
|
|
11691
|
-
await writeFile3(
|
|
11734
|
+
await writeFile3(join21(skillDir, "reference.md"), refContent, "utf-8");
|
|
11692
11735
|
referenceWritten = true;
|
|
11693
11736
|
}
|
|
11694
11737
|
log(`${existed ? "Updated" : "Installed"} /story skill at ${skillDir}/`);
|
|
@@ -11802,8 +11845,8 @@ var hook_status_exports = {};
|
|
|
11802
11845
|
__export(hook_status_exports, {
|
|
11803
11846
|
handleHookStatus: () => handleHookStatus
|
|
11804
11847
|
});
|
|
11805
|
-
import { readFileSync as
|
|
11806
|
-
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";
|
|
11807
11850
|
async function readStdinSilent() {
|
|
11808
11851
|
try {
|
|
11809
11852
|
const chunks = [];
|
|
@@ -11853,10 +11896,10 @@ function activePayload(session) {
|
|
|
11853
11896
|
};
|
|
11854
11897
|
}
|
|
11855
11898
|
function ensureGitignore(root) {
|
|
11856
|
-
const gitignorePath =
|
|
11899
|
+
const gitignorePath = join22(root, ".story", ".gitignore");
|
|
11857
11900
|
let existing = "";
|
|
11858
11901
|
try {
|
|
11859
|
-
existing =
|
|
11902
|
+
existing = readFileSync9(gitignorePath, "utf-8");
|
|
11860
11903
|
} catch {
|
|
11861
11904
|
}
|
|
11862
11905
|
const lines = existing.split("\n").map((l) => l.trim());
|
|
@@ -11872,7 +11915,7 @@ function ensureGitignore(root) {
|
|
|
11872
11915
|
}
|
|
11873
11916
|
function writeStatus(root, payload) {
|
|
11874
11917
|
ensureGitignore(root);
|
|
11875
|
-
const statusPath =
|
|
11918
|
+
const statusPath = join22(root, ".story", "status.json");
|
|
11876
11919
|
const content = JSON.stringify(payload, null, 2) + "\n";
|
|
11877
11920
|
atomicWriteSync(statusPath, content);
|
|
11878
11921
|
}
|
|
@@ -11931,8 +11974,8 @@ var config_update_exports = {};
|
|
|
11931
11974
|
__export(config_update_exports, {
|
|
11932
11975
|
handleConfigSetOverrides: () => handleConfigSetOverrides
|
|
11933
11976
|
});
|
|
11934
|
-
import { readFileSync as
|
|
11935
|
-
import { join as
|
|
11977
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
11978
|
+
import { join as join23 } from "path";
|
|
11936
11979
|
async function handleConfigSetOverrides(root, format, options) {
|
|
11937
11980
|
const { json: jsonArg, clear } = options;
|
|
11938
11981
|
if (!clear && !jsonArg) {
|
|
@@ -11960,8 +12003,8 @@ async function handleConfigSetOverrides(root, format, options) {
|
|
|
11960
12003
|
}
|
|
11961
12004
|
let resultOverrides = null;
|
|
11962
12005
|
await withProjectLock(root, { strict: false }, async () => {
|
|
11963
|
-
const configPath =
|
|
11964
|
-
const rawContent =
|
|
12006
|
+
const configPath = join23(root, ".story", "config.json");
|
|
12007
|
+
const rawContent = readFileSync10(configPath, "utf-8");
|
|
11965
12008
|
const raw = JSON.parse(rawContent);
|
|
11966
12009
|
if (clear) {
|
|
11967
12010
|
delete raw.recipeOverrides;
|
|
@@ -14304,7 +14347,7 @@ async function runCli() {
|
|
|
14304
14347
|
registerSessionCommand: registerSessionCommand2,
|
|
14305
14348
|
registerRepairCommand: registerRepairCommand2
|
|
14306
14349
|
} = await Promise.resolve().then(() => (init_register(), register_exports));
|
|
14307
|
-
const version2 = "0.1.
|
|
14350
|
+
const version2 = "0.1.42";
|
|
14308
14351
|
class HandledError extends Error {
|
|
14309
14352
|
constructor() {
|
|
14310
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();
|
|
@@ -7783,6 +7783,43 @@ init_project_loader();
|
|
|
7783
7783
|
init_snapshot();
|
|
7784
7784
|
init_snapshot();
|
|
7785
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
|
|
7786
7823
|
init_handover();
|
|
7787
7824
|
var RECOVERY_MAPPING = {
|
|
7788
7825
|
PICK_TICKET: { state: "PICK_TICKET", resetPlan: false, resetCode: false },
|
|
@@ -7804,18 +7841,18 @@ var RECOVERY_MAPPING = {
|
|
|
7804
7841
|
function buildGuideRecommendOptions(root) {
|
|
7805
7842
|
const opts = {};
|
|
7806
7843
|
try {
|
|
7807
|
-
const handoversDir =
|
|
7844
|
+
const handoversDir = join14(root, ".story", "handovers");
|
|
7808
7845
|
const files = readdirSync4(handoversDir, "utf-8").filter((f) => f.endsWith(".md")).sort();
|
|
7809
7846
|
if (files.length > 0) {
|
|
7810
|
-
opts.latestHandoverContent =
|
|
7847
|
+
opts.latestHandoverContent = readFileSync7(join14(handoversDir, files[files.length - 1]), "utf-8");
|
|
7811
7848
|
}
|
|
7812
7849
|
} catch {
|
|
7813
7850
|
}
|
|
7814
7851
|
try {
|
|
7815
|
-
const snapshotsDir =
|
|
7852
|
+
const snapshotsDir = join14(root, ".story", "snapshots");
|
|
7816
7853
|
const snapFiles = readdirSync4(snapshotsDir, "utf-8").filter((f) => f.endsWith(".json")).sort();
|
|
7817
7854
|
if (snapFiles.length > 0) {
|
|
7818
|
-
const raw =
|
|
7855
|
+
const raw = readFileSync7(join14(snapshotsDir, snapFiles[snapFiles.length - 1]), "utf-8");
|
|
7819
7856
|
const snap = JSON.parse(raw);
|
|
7820
7857
|
if (snap.issues) {
|
|
7821
7858
|
opts.previousOpenIssueCount = snap.issues.filter((i) => i.status !== "resolved").length;
|
|
@@ -8008,6 +8045,7 @@ async function handleStart(root, args) {
|
|
|
8008
8045
|
for (const stale of staleSessions) {
|
|
8009
8046
|
writeSessionSync(stale.dir, { ...stale.state, status: "superseded" });
|
|
8010
8047
|
}
|
|
8048
|
+
const versionWarning = checkVersionMismatch(getRunningVersion(), getInstalledVersion());
|
|
8011
8049
|
const wsId = deriveWorkspaceId(root);
|
|
8012
8050
|
const mode = args.mode ?? "auto";
|
|
8013
8051
|
if (mode !== "auto" && !args.ticketId) {
|
|
@@ -8202,7 +8240,7 @@ Staged: ${stagedResult.data.join(", ")}`
|
|
|
8202
8240
|
}
|
|
8203
8241
|
}
|
|
8204
8242
|
const { state: projectState, warnings } = await loadProject(root);
|
|
8205
|
-
const handoversDir =
|
|
8243
|
+
const handoversDir = join14(root, ".story", "handovers");
|
|
8206
8244
|
const ctx = { state: projectState, warnings, root, handoversDir, format: "md" };
|
|
8207
8245
|
let handoverText = "";
|
|
8208
8246
|
try {
|
|
@@ -8219,7 +8257,7 @@ Staged: ${stagedResult.data.join(", ")}`
|
|
|
8219
8257
|
}
|
|
8220
8258
|
} catch {
|
|
8221
8259
|
}
|
|
8222
|
-
const rulesText = readFileSafe2(
|
|
8260
|
+
const rulesText = readFileSafe2(join14(root, "RULES.md"));
|
|
8223
8261
|
const lessonDigest = buildLessonDigest(projectState.lessons);
|
|
8224
8262
|
const digestParts = [
|
|
8225
8263
|
handoverText ? `## Recent Handovers
|
|
@@ -8235,7 +8273,7 @@ ${rulesText}` : "",
|
|
|
8235
8273
|
].filter(Boolean);
|
|
8236
8274
|
const digest = digestParts.join("\n\n---\n\n");
|
|
8237
8275
|
try {
|
|
8238
|
-
writeFileSync3(
|
|
8276
|
+
writeFileSync3(join14(dir, "context-digest.md"), digest, "utf-8");
|
|
8239
8277
|
} catch {
|
|
8240
8278
|
}
|
|
8241
8279
|
if (mode !== "auto" && args.ticketId) {
|
|
@@ -8427,7 +8465,8 @@ ${ticket.description}` : "",
|
|
|
8427
8465
|
"Do NOT use Claude Code's plan mode \u2014 write plans as markdown files.",
|
|
8428
8466
|
"Do NOT ask the user for confirmation or approval.",
|
|
8429
8467
|
"Do NOT stop or summarize between tickets \u2014 call autonomous_guide IMMEDIATELY.",
|
|
8430
|
-
"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}`] : []
|
|
8431
8470
|
],
|
|
8432
8471
|
transitionedFrom: "INIT"
|
|
8433
8472
|
});
|
|
@@ -8954,7 +8993,7 @@ function guideError(err) {
|
|
|
8954
8993
|
}
|
|
8955
8994
|
function readFileSafe2(path2) {
|
|
8956
8995
|
try {
|
|
8957
|
-
return
|
|
8996
|
+
return readFileSync7(path2, "utf-8");
|
|
8958
8997
|
} catch {
|
|
8959
8998
|
return "";
|
|
8960
8999
|
}
|
|
@@ -8964,8 +9003,8 @@ function readFileSafe2(path2) {
|
|
|
8964
9003
|
init_esm_shims();
|
|
8965
9004
|
init_session();
|
|
8966
9005
|
init_session_types();
|
|
8967
|
-
import { readFileSync as
|
|
8968
|
-
import { join as
|
|
9006
|
+
import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
|
|
9007
|
+
import { join as join15 } from "path";
|
|
8969
9008
|
|
|
8970
9009
|
// src/core/session-report-formatter.ts
|
|
8971
9010
|
init_esm_shims();
|
|
@@ -9179,7 +9218,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9179
9218
|
isError: true
|
|
9180
9219
|
};
|
|
9181
9220
|
}
|
|
9182
|
-
const statePath2 =
|
|
9221
|
+
const statePath2 = join15(dir, "state.json");
|
|
9183
9222
|
if (!existsSync10(statePath2)) {
|
|
9184
9223
|
return {
|
|
9185
9224
|
output: `Error: Session ${sessionId} corrupt \u2014 state.json missing.`,
|
|
@@ -9189,7 +9228,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9189
9228
|
};
|
|
9190
9229
|
}
|
|
9191
9230
|
try {
|
|
9192
|
-
const rawJson = JSON.parse(
|
|
9231
|
+
const rawJson = JSON.parse(readFileSync8(statePath2, "utf-8"));
|
|
9193
9232
|
if (rawJson && typeof rawJson === "object" && "schemaVersion" in rawJson && rawJson.schemaVersion !== CURRENT_SESSION_SCHEMA_VERSION) {
|
|
9194
9233
|
return {
|
|
9195
9234
|
output: `Error: Session ${sessionId} \u2014 unsupported session schema version ${rawJson.schemaVersion}.`,
|
|
@@ -9218,7 +9257,7 @@ async function handleSessionReport(sessionId, root, format = "md") {
|
|
|
9218
9257
|
const events = readEvents(dir);
|
|
9219
9258
|
let planContent = null;
|
|
9220
9259
|
try {
|
|
9221
|
-
planContent =
|
|
9260
|
+
planContent = readFileSync8(join15(dir, "plan.md"), "utf-8");
|
|
9222
9261
|
} catch {
|
|
9223
9262
|
}
|
|
9224
9263
|
let gitLog = null;
|
|
@@ -9243,7 +9282,7 @@ init_issue();
|
|
|
9243
9282
|
init_roadmap();
|
|
9244
9283
|
init_output_formatter();
|
|
9245
9284
|
init_helpers();
|
|
9246
|
-
import { join as
|
|
9285
|
+
import { join as join16, resolve as resolve6 } from "path";
|
|
9247
9286
|
var PHASE_ID_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
9248
9287
|
var PHASE_ID_MAX_LENGTH = 40;
|
|
9249
9288
|
function validatePhaseId(id) {
|
|
@@ -9352,7 +9391,7 @@ function formatMcpError(code, message) {
|
|
|
9352
9391
|
async function runMcpReadTool(pinnedRoot, handler) {
|
|
9353
9392
|
try {
|
|
9354
9393
|
const { state, warnings } = await loadProject(pinnedRoot);
|
|
9355
|
-
const handoversDir =
|
|
9394
|
+
const handoversDir = join17(pinnedRoot, ".story", "handovers");
|
|
9356
9395
|
const ctx = { state, warnings, root: pinnedRoot, handoversDir, format: "md" };
|
|
9357
9396
|
const result = await handler(ctx);
|
|
9358
9397
|
if (result.errorCode && INFRASTRUCTURE_ERROR_CODES.includes(result.errorCode)) {
|
|
@@ -9910,10 +9949,10 @@ init_esm_shims();
|
|
|
9910
9949
|
init_project_loader();
|
|
9911
9950
|
init_errors();
|
|
9912
9951
|
import { mkdir as mkdir4, stat as stat2, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
9913
|
-
import { join as
|
|
9952
|
+
import { join as join18, resolve as resolve7 } from "path";
|
|
9914
9953
|
async function initProject(root, options) {
|
|
9915
9954
|
const absRoot = resolve7(root);
|
|
9916
|
-
const wrapDir =
|
|
9955
|
+
const wrapDir = join18(absRoot, ".story");
|
|
9917
9956
|
let exists = false;
|
|
9918
9957
|
try {
|
|
9919
9958
|
const s = await stat2(wrapDir);
|
|
@@ -9933,11 +9972,11 @@ async function initProject(root, options) {
|
|
|
9933
9972
|
".story/ already exists. Use --force to overwrite config and roadmap."
|
|
9934
9973
|
);
|
|
9935
9974
|
}
|
|
9936
|
-
await mkdir4(
|
|
9937
|
-
await mkdir4(
|
|
9938
|
-
await mkdir4(
|
|
9939
|
-
await mkdir4(
|
|
9940
|
-
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 });
|
|
9941
9980
|
const created = [
|
|
9942
9981
|
".story/config.json",
|
|
9943
9982
|
".story/roadmap.json",
|
|
@@ -9977,7 +10016,7 @@ async function initProject(root, options) {
|
|
|
9977
10016
|
};
|
|
9978
10017
|
await writeConfig(config, absRoot);
|
|
9979
10018
|
await writeRoadmap(roadmap, absRoot);
|
|
9980
|
-
const gitignorePath =
|
|
10019
|
+
const gitignorePath = join18(wrapDir, ".gitignore");
|
|
9981
10020
|
await ensureGitignoreEntries(gitignorePath, STORY_GITIGNORE_ENTRIES);
|
|
9982
10021
|
const warnings = [];
|
|
9983
10022
|
if (options.force && exists) {
|
|
@@ -10016,7 +10055,7 @@ async function ensureGitignoreEntries(gitignorePath, entries) {
|
|
|
10016
10055
|
// src/mcp/index.ts
|
|
10017
10056
|
var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
|
|
10018
10057
|
var CONFIG_PATH2 = ".story/config.json";
|
|
10019
|
-
var version = "0.1.
|
|
10058
|
+
var version = "0.1.42";
|
|
10020
10059
|
function tryDiscoverRoot() {
|
|
10021
10060
|
const envRoot = process.env[ENV_VAR2];
|
|
10022
10061
|
if (envRoot) {
|
|
@@ -10028,7 +10067,7 @@ function tryDiscoverRoot() {
|
|
|
10028
10067
|
const resolved = resolve8(envRoot);
|
|
10029
10068
|
try {
|
|
10030
10069
|
const canonical = realpathSync2(resolved);
|
|
10031
|
-
if (existsSync11(
|
|
10070
|
+
if (existsSync11(join19(canonical, CONFIG_PATH2))) {
|
|
10032
10071
|
return canonical;
|
|
10033
10072
|
}
|
|
10034
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": [
|