@anthropologies/claudestory 0.1.32 → 0.1.34
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 +131 -16
- package/dist/index.d.ts +40 -0
- package/dist/index.js +3 -1
- package/dist/mcp.js +122 -15
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -298,7 +298,9 @@ var init_config = __esm({
|
|
|
298
298
|
recipeOverrides: z7.object({
|
|
299
299
|
maxTicketsPerSession: z7.number().min(0).optional(),
|
|
300
300
|
compactThreshold: z7.string().optional(),
|
|
301
|
-
reviewBackends: z7.array(z7.string()).optional()
|
|
301
|
+
reviewBackends: z7.array(z7.string()).optional(),
|
|
302
|
+
handoverInterval: z7.number().min(0).optional(),
|
|
303
|
+
stages: z7.record(z7.record(z7.unknown())).optional()
|
|
302
304
|
}).optional()
|
|
303
305
|
}).passthrough();
|
|
304
306
|
}
|
|
@@ -5021,6 +5023,7 @@ var init_session_types = __esm({
|
|
|
5021
5023
|
"WRITE_TESTS",
|
|
5022
5024
|
"TEST",
|
|
5023
5025
|
"CODE_REVIEW",
|
|
5026
|
+
"BUILD",
|
|
5024
5027
|
"VERIFY",
|
|
5025
5028
|
"FINALIZE",
|
|
5026
5029
|
"COMPACT",
|
|
@@ -5046,6 +5049,7 @@ var init_session_types = __esm({
|
|
|
5046
5049
|
"WRITE_TESTS",
|
|
5047
5050
|
"TEST",
|
|
5048
5051
|
"CODE_REVIEW",
|
|
5052
|
+
"BUILD",
|
|
5049
5053
|
"VERIFY",
|
|
5050
5054
|
"FINALIZE",
|
|
5051
5055
|
"COMPACT",
|
|
@@ -5196,6 +5200,7 @@ var init_session_types = __esm({
|
|
|
5196
5200
|
}).nullable().default(null),
|
|
5197
5201
|
testRetryCount: z9.number().default(0),
|
|
5198
5202
|
writeTestsRetryCount: z9.number().default(0),
|
|
5203
|
+
buildRetryCount: z9.number().default(0),
|
|
5199
5204
|
verifyRetryCount: z9.number().default(0),
|
|
5200
5205
|
verifyAutoDetected: z9.boolean().default(false),
|
|
5201
5206
|
// T-128: Resolved recipe (frozen at session start, survives compact/resume)
|
|
@@ -5901,7 +5906,19 @@ function resolveRecipe(recipeName, projectOverrides) {
|
|
|
5901
5906
|
}
|
|
5902
5907
|
}
|
|
5903
5908
|
let pipeline = raw.pipeline ? [...raw.pipeline] : [...DEFAULT_PIPELINE];
|
|
5904
|
-
const
|
|
5909
|
+
const recipeStages = raw.stages ?? {};
|
|
5910
|
+
const stageOverrides = projectOverrides?.stages ?? {};
|
|
5911
|
+
const stages2 = {};
|
|
5912
|
+
for (const [key, value] of Object.entries(recipeStages)) {
|
|
5913
|
+
const override = stageOverrides[key];
|
|
5914
|
+
const safeOverride = override && typeof override === "object" && !Array.isArray(override) ? override : {};
|
|
5915
|
+
stages2[key] = { ...value, ...safeOverride };
|
|
5916
|
+
}
|
|
5917
|
+
for (const [key, value] of Object.entries(stageOverrides)) {
|
|
5918
|
+
if (!stages2[key] && value && typeof value === "object" && !Array.isArray(value)) {
|
|
5919
|
+
stages2[key] = { ...value };
|
|
5920
|
+
}
|
|
5921
|
+
}
|
|
5905
5922
|
if (stages2.WRITE_TESTS?.enabled) {
|
|
5906
5923
|
const implementIdx = pipeline.indexOf("IMPLEMENT");
|
|
5907
5924
|
if (implementIdx !== -1 && !pipeline.includes("WRITE_TESTS")) {
|
|
@@ -5914,6 +5931,12 @@ function resolveRecipe(recipeName, projectOverrides) {
|
|
|
5914
5931
|
pipeline.splice(codeReviewIdx + 1, 0, "VERIFY");
|
|
5915
5932
|
}
|
|
5916
5933
|
}
|
|
5934
|
+
if (stages2.BUILD?.enabled) {
|
|
5935
|
+
const finalizeIdx = pipeline.indexOf("FINALIZE");
|
|
5936
|
+
if (finalizeIdx !== -1 && !pipeline.includes("BUILD")) {
|
|
5937
|
+
pipeline.splice(finalizeIdx, 0, "BUILD");
|
|
5938
|
+
}
|
|
5939
|
+
}
|
|
5917
5940
|
if (stages2.TEST?.enabled) {
|
|
5918
5941
|
const implementIdx = pipeline.indexOf("IMPLEMENT");
|
|
5919
5942
|
if (implementIdx !== -1 && !pipeline.includes("TEST")) {
|
|
@@ -6526,7 +6549,8 @@ var init_implement = __esm({
|
|
|
6526
6549
|
].join("\n"),
|
|
6527
6550
|
reminders: [
|
|
6528
6551
|
"Follow the plan exactly. Do NOT deviate without re-planning.",
|
|
6529
|
-
"Do NOT ask the user for confirmation."
|
|
6552
|
+
"Do NOT ask the user for confirmation.",
|
|
6553
|
+
"If you discover pre-existing bugs, failing tests not caused by your changes, or other out-of-scope problems, file them as issues using claudestory_issue_create. Do not fix them inline."
|
|
6530
6554
|
],
|
|
6531
6555
|
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6532
6556
|
};
|
|
@@ -6804,12 +6828,16 @@ var init_code_review = __esm({
|
|
|
6804
6828
|
"",
|
|
6805
6829
|
`Capture the diff with: ${diffCommand}`,
|
|
6806
6830
|
"",
|
|
6807
|
-
"**IMPORTANT:** Pass the FULL unified diff
|
|
6831
|
+
"**IMPORTANT:** Pass the FULL unified diff to the reviewer. For diffs over ~500 lines, use file-scoped chunks (`git diff <mergebase> -- <filepath>`) across separate calls (pass the same session_id). Do NOT summarize or truncate any individual chunk.",
|
|
6808
6832
|
"",
|
|
6809
6833
|
`Run a code review using **${reviewer}**.`,
|
|
6810
6834
|
"When done, report verdict and findings."
|
|
6811
6835
|
].join("\n"),
|
|
6812
|
-
reminders: [
|
|
6836
|
+
reminders: [
|
|
6837
|
+
diffReminder,
|
|
6838
|
+
"Do NOT compress or summarize the diff.",
|
|
6839
|
+
"If the reviewer flags pre-existing issues unrelated to your changes, file them as issues using claudestory_issue_create with severity and impact. Do not fix them in this ticket."
|
|
6840
|
+
],
|
|
6813
6841
|
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6814
6842
|
};
|
|
6815
6843
|
}
|
|
@@ -6924,6 +6952,95 @@ var init_code_review = __esm({
|
|
|
6924
6952
|
}
|
|
6925
6953
|
});
|
|
6926
6954
|
|
|
6955
|
+
// src/autonomous/stages/build.ts
|
|
6956
|
+
var MAX_BUILD_RETRIES, BuildStage;
|
|
6957
|
+
var init_build = __esm({
|
|
6958
|
+
"src/autonomous/stages/build.ts"() {
|
|
6959
|
+
"use strict";
|
|
6960
|
+
init_esm_shims();
|
|
6961
|
+
MAX_BUILD_RETRIES = 2;
|
|
6962
|
+
BuildStage = class {
|
|
6963
|
+
id = "BUILD";
|
|
6964
|
+
skip(ctx) {
|
|
6965
|
+
const buildConfig = ctx.recipe.stages?.BUILD;
|
|
6966
|
+
return !buildConfig?.enabled;
|
|
6967
|
+
}
|
|
6968
|
+
async enter(ctx) {
|
|
6969
|
+
const buildConfig = ctx.recipe.stages?.BUILD;
|
|
6970
|
+
const command = buildConfig?.command ?? "npm run build";
|
|
6971
|
+
const retryCount = ctx.state.buildRetryCount ?? 0;
|
|
6972
|
+
return {
|
|
6973
|
+
instruction: [
|
|
6974
|
+
`# Build${retryCount > 0 ? ` (retry ${retryCount}/${MAX_BUILD_RETRIES})` : ""}`,
|
|
6975
|
+
"",
|
|
6976
|
+
`Run the build: \`${command}\``,
|
|
6977
|
+
"",
|
|
6978
|
+
"Report the results with:",
|
|
6979
|
+
"```json",
|
|
6980
|
+
`{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "build_done", "notes": "<exit code and summary>" } }`,
|
|
6981
|
+
"```",
|
|
6982
|
+
"",
|
|
6983
|
+
"Include the exit code (0 = pass, non-0 = fail) and any error output in notes."
|
|
6984
|
+
].join("\n"),
|
|
6985
|
+
reminders: ["Run the FULL build, not a partial or dev-mode build."],
|
|
6986
|
+
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6987
|
+
};
|
|
6988
|
+
}
|
|
6989
|
+
async report(ctx, report) {
|
|
6990
|
+
const notes = report.notes ?? "";
|
|
6991
|
+
const retryCount = ctx.state.buildRetryCount ?? 0;
|
|
6992
|
+
const exitCodeMatch = notes.match(/exit\s*(?:code[:\s]*)?\s*(\d+)/i);
|
|
6993
|
+
if (!exitCodeMatch) {
|
|
6994
|
+
const nextRetry = retryCount + 1;
|
|
6995
|
+
if (nextRetry > MAX_BUILD_RETRIES) {
|
|
6996
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6997
|
+
ctx.appendEvent("build_parse_exhausted", { retryCount: nextRetry });
|
|
6998
|
+
return {
|
|
6999
|
+
action: "advance",
|
|
7000
|
+
result: {
|
|
7001
|
+
instruction: `Could not parse build exit code after ${MAX_BUILD_RETRIES} retries. Proceeding, but build status is unknown.`,
|
|
7002
|
+
reminders: ["Mention unknown build status in the commit message."]
|
|
7003
|
+
}
|
|
7004
|
+
};
|
|
7005
|
+
}
|
|
7006
|
+
ctx.writeState({ buildRetryCount: nextRetry });
|
|
7007
|
+
return { action: "retry", instruction: 'Could not parse exit code from notes. Include "exit code: 0" (or non-zero) in your notes.' };
|
|
7008
|
+
}
|
|
7009
|
+
const exitCode = parseInt(exitCodeMatch[1], 10);
|
|
7010
|
+
if (exitCode === 0) {
|
|
7011
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
7012
|
+
ctx.appendEvent("build_passed", { retryCount, notes: notes.slice(0, 200) });
|
|
7013
|
+
return { action: "advance" };
|
|
7014
|
+
}
|
|
7015
|
+
if (retryCount < MAX_BUILD_RETRIES) {
|
|
7016
|
+
ctx.writeState({ buildRetryCount: retryCount + 1 });
|
|
7017
|
+
ctx.appendEvent("build_failed_retry", { retryCount: retryCount + 1, notes: notes.slice(0, 200) });
|
|
7018
|
+
return {
|
|
7019
|
+
action: "back",
|
|
7020
|
+
target: "IMPLEMENT",
|
|
7021
|
+
reason: `Build failed (attempt ${retryCount + 1}/${MAX_BUILD_RETRIES}). Fix the build errors.`
|
|
7022
|
+
};
|
|
7023
|
+
}
|
|
7024
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
7025
|
+
ctx.appendEvent("build_failed_exhausted", { retryCount, notes: notes.slice(0, 200) });
|
|
7026
|
+
return {
|
|
7027
|
+
action: "advance",
|
|
7028
|
+
result: {
|
|
7029
|
+
instruction: [
|
|
7030
|
+
"# Build Failed - Proceeding",
|
|
7031
|
+
"",
|
|
7032
|
+
`Build failed after ${MAX_BUILD_RETRIES} retries. Proceeding but build errors remain.`,
|
|
7033
|
+
"",
|
|
7034
|
+
"Document the build failure in the commit message."
|
|
7035
|
+
].join("\n"),
|
|
7036
|
+
reminders: ["Mention build failure in the commit message."]
|
|
7037
|
+
}
|
|
7038
|
+
};
|
|
7039
|
+
}
|
|
7040
|
+
};
|
|
7041
|
+
}
|
|
7042
|
+
});
|
|
7043
|
+
|
|
6927
7044
|
// src/autonomous/stages/verify.ts
|
|
6928
7045
|
function exhaustionAction2(ctx) {
|
|
6929
7046
|
ctx.writeState({ verifyRetryCount: 0 });
|
|
@@ -7733,6 +7850,7 @@ var init_stages = __esm({
|
|
|
7733
7850
|
init_write_tests();
|
|
7734
7851
|
init_test();
|
|
7735
7852
|
init_code_review();
|
|
7853
|
+
init_build();
|
|
7736
7854
|
init_verify();
|
|
7737
7855
|
init_finalize();
|
|
7738
7856
|
init_complete();
|
|
@@ -7746,6 +7864,7 @@ var init_stages = __esm({
|
|
|
7746
7864
|
registerStage(new WriteTestsStage());
|
|
7747
7865
|
registerStage(new TestStage());
|
|
7748
7866
|
registerStage(new CodeReviewStage());
|
|
7867
|
+
registerStage(new BuildStage());
|
|
7749
7868
|
registerStage(new VerifyStage());
|
|
7750
7869
|
registerStage(new FinalizeStage());
|
|
7751
7870
|
registerStage(new CompleteStage());
|
|
@@ -7954,6 +8073,9 @@ async function handleStart(root, args) {
|
|
|
7954
8073
|
if (typeof overrides.compactThreshold === "string") sessionConfig.compactThreshold = overrides.compactThreshold;
|
|
7955
8074
|
if (Array.isArray(overrides.reviewBackends)) sessionConfig.reviewBackends = overrides.reviewBackends;
|
|
7956
8075
|
if (typeof overrides.handoverInterval === "number") sessionConfig.handoverInterval = overrides.handoverInterval;
|
|
8076
|
+
if (overrides.stages && typeof overrides.stages === "object") {
|
|
8077
|
+
sessionConfig.stageOverrides = overrides.stages;
|
|
8078
|
+
}
|
|
7957
8079
|
}
|
|
7958
8080
|
} catch {
|
|
7959
8081
|
}
|
|
@@ -7963,7 +8085,8 @@ async function handleStart(root, args) {
|
|
|
7963
8085
|
const resolvedRecipe = resolveRecipe(recipe, {
|
|
7964
8086
|
maxTicketsPerSession: sessionConfig.maxTicketsPerSession,
|
|
7965
8087
|
compactThreshold: sessionConfig.compactThreshold,
|
|
7966
|
-
reviewBackends: sessionConfig.reviewBackends
|
|
8088
|
+
reviewBackends: sessionConfig.reviewBackends,
|
|
8089
|
+
stages: sessionConfig.stageOverrides
|
|
7967
8090
|
});
|
|
7968
8091
|
const session = createSession(root, recipe, wsId, sessionConfig);
|
|
7969
8092
|
const dir = sessionDir(root, session.sessionId);
|
|
@@ -8763,14 +8886,6 @@ async function handleCancel(root, args) {
|
|
|
8763
8886
|
if (info.state.state === "SESSION_END" || info.state.status === "completed") {
|
|
8764
8887
|
return guideError(new Error("Session already ended."));
|
|
8765
8888
|
}
|
|
8766
|
-
const CANCELLABLE_STATES = /* @__PURE__ */ new Set(["PICK_TICKET", "COMPLETE", "HANDOVER"]);
|
|
8767
|
-
if (info.state.recipe === "coding" && !CANCELLABLE_STATES.has(info.state.state)) {
|
|
8768
|
-
const sessionMode = info.state.mode ?? "auto";
|
|
8769
|
-
const modeGuidance = sessionMode === "plan" ? "Plan mode sessions end after plan review approval \u2014 continue to that step." : sessionMode === "review" ? "Review mode sessions end after code review approval \u2014 continue to that step." : sessionMode === "guided" ? "Guided mode sessions end after ticket completion \u2014 continue to FINALIZE." : "Complete the current ticket and write a handover to end the session.";
|
|
8770
|
-
return guideError(new Error(
|
|
8771
|
-
`Cannot cancel a coding session from ${info.state.state}. ${modeGuidance}`
|
|
8772
|
-
));
|
|
8773
|
-
}
|
|
8774
8889
|
await recoverPendingMutation(info.dir, info.state, root);
|
|
8775
8890
|
const cancelInfo = findSessionById(root, args.sessionId) ?? info;
|
|
8776
8891
|
let ticketReleased = false;
|
|
@@ -10258,7 +10373,7 @@ var init_mcp = __esm({
|
|
|
10258
10373
|
init_init();
|
|
10259
10374
|
ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
|
|
10260
10375
|
CONFIG_PATH2 = ".story/config.json";
|
|
10261
|
-
version = "0.1.
|
|
10376
|
+
version = "0.1.34";
|
|
10262
10377
|
main().catch((err) => {
|
|
10263
10378
|
process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}
|
|
10264
10379
|
`);
|
|
@@ -13542,7 +13657,7 @@ async function runCli() {
|
|
|
13542
13657
|
registerConfigCommand: registerConfigCommand2,
|
|
13543
13658
|
registerSessionCommand: registerSessionCommand2
|
|
13544
13659
|
} = await Promise.resolve().then(() => (init_register(), register_exports));
|
|
13545
|
-
const version2 = "0.1.
|
|
13660
|
+
const version2 = "0.1.34";
|
|
13546
13661
|
class HandledError extends Error {
|
|
13547
13662
|
constructor() {
|
|
13548
13663
|
super("HANDLED_ERROR");
|
package/dist/index.d.ts
CHANGED
|
@@ -348,14 +348,20 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
348
348
|
maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
|
|
349
349
|
compactThreshold: z.ZodOptional<z.ZodString>;
|
|
350
350
|
reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
351
|
+
handoverInterval: z.ZodOptional<z.ZodNumber>;
|
|
352
|
+
stages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
351
353
|
}, "strip", z.ZodTypeAny, {
|
|
352
354
|
maxTicketsPerSession?: number | undefined;
|
|
353
355
|
compactThreshold?: string | undefined;
|
|
354
356
|
reviewBackends?: string[] | undefined;
|
|
357
|
+
handoverInterval?: number | undefined;
|
|
358
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
355
359
|
}, {
|
|
356
360
|
maxTicketsPerSession?: number | undefined;
|
|
357
361
|
compactThreshold?: string | undefined;
|
|
358
362
|
reviewBackends?: string[] | undefined;
|
|
363
|
+
handoverInterval?: number | undefined;
|
|
364
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
359
365
|
}>>;
|
|
360
366
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
361
367
|
version: z.ZodNumber;
|
|
@@ -387,14 +393,20 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
387
393
|
maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
|
|
388
394
|
compactThreshold: z.ZodOptional<z.ZodString>;
|
|
389
395
|
reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
396
|
+
handoverInterval: z.ZodOptional<z.ZodNumber>;
|
|
397
|
+
stages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
390
398
|
}, "strip", z.ZodTypeAny, {
|
|
391
399
|
maxTicketsPerSession?: number | undefined;
|
|
392
400
|
compactThreshold?: string | undefined;
|
|
393
401
|
reviewBackends?: string[] | undefined;
|
|
402
|
+
handoverInterval?: number | undefined;
|
|
403
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
394
404
|
}, {
|
|
395
405
|
maxTicketsPerSession?: number | undefined;
|
|
396
406
|
compactThreshold?: string | undefined;
|
|
397
407
|
reviewBackends?: string[] | undefined;
|
|
408
|
+
handoverInterval?: number | undefined;
|
|
409
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
398
410
|
}>>;
|
|
399
411
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
400
412
|
version: z.ZodNumber;
|
|
@@ -426,14 +438,20 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
426
438
|
maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
|
|
427
439
|
compactThreshold: z.ZodOptional<z.ZodString>;
|
|
428
440
|
reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
441
|
+
handoverInterval: z.ZodOptional<z.ZodNumber>;
|
|
442
|
+
stages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
429
443
|
}, "strip", z.ZodTypeAny, {
|
|
430
444
|
maxTicketsPerSession?: number | undefined;
|
|
431
445
|
compactThreshold?: string | undefined;
|
|
432
446
|
reviewBackends?: string[] | undefined;
|
|
447
|
+
handoverInterval?: number | undefined;
|
|
448
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
433
449
|
}, {
|
|
434
450
|
maxTicketsPerSession?: number | undefined;
|
|
435
451
|
compactThreshold?: string | undefined;
|
|
436
452
|
reviewBackends?: string[] | undefined;
|
|
453
|
+
handoverInterval?: number | undefined;
|
|
454
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
437
455
|
}>>;
|
|
438
456
|
}, z.ZodTypeAny, "passthrough">>;
|
|
439
457
|
type Config = z.infer<typeof ConfigSchema>;
|
|
@@ -950,14 +968,20 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
950
968
|
maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
|
|
951
969
|
compactThreshold: z.ZodOptional<z.ZodString>;
|
|
952
970
|
reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
971
|
+
handoverInterval: z.ZodOptional<z.ZodNumber>;
|
|
972
|
+
stages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
953
973
|
}, "strip", z.ZodTypeAny, {
|
|
954
974
|
maxTicketsPerSession?: number | undefined;
|
|
955
975
|
compactThreshold?: string | undefined;
|
|
956
976
|
reviewBackends?: string[] | undefined;
|
|
977
|
+
handoverInterval?: number | undefined;
|
|
978
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
957
979
|
}, {
|
|
958
980
|
maxTicketsPerSession?: number | undefined;
|
|
959
981
|
compactThreshold?: string | undefined;
|
|
960
982
|
reviewBackends?: string[] | undefined;
|
|
983
|
+
handoverInterval?: number | undefined;
|
|
984
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
961
985
|
}>>;
|
|
962
986
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
963
987
|
version: z.ZodNumber;
|
|
@@ -989,14 +1013,20 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
989
1013
|
maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
|
|
990
1014
|
compactThreshold: z.ZodOptional<z.ZodString>;
|
|
991
1015
|
reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1016
|
+
handoverInterval: z.ZodOptional<z.ZodNumber>;
|
|
1017
|
+
stages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
992
1018
|
}, "strip", z.ZodTypeAny, {
|
|
993
1019
|
maxTicketsPerSession?: number | undefined;
|
|
994
1020
|
compactThreshold?: string | undefined;
|
|
995
1021
|
reviewBackends?: string[] | undefined;
|
|
1022
|
+
handoverInterval?: number | undefined;
|
|
1023
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
996
1024
|
}, {
|
|
997
1025
|
maxTicketsPerSession?: number | undefined;
|
|
998
1026
|
compactThreshold?: string | undefined;
|
|
999
1027
|
reviewBackends?: string[] | undefined;
|
|
1028
|
+
handoverInterval?: number | undefined;
|
|
1029
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
1000
1030
|
}>>;
|
|
1001
1031
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
1002
1032
|
version: z.ZodNumber;
|
|
@@ -1028,14 +1058,20 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1028
1058
|
maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
|
|
1029
1059
|
compactThreshold: z.ZodOptional<z.ZodString>;
|
|
1030
1060
|
reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1061
|
+
handoverInterval: z.ZodOptional<z.ZodNumber>;
|
|
1062
|
+
stages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1031
1063
|
}, "strip", z.ZodTypeAny, {
|
|
1032
1064
|
maxTicketsPerSession?: number | undefined;
|
|
1033
1065
|
compactThreshold?: string | undefined;
|
|
1034
1066
|
reviewBackends?: string[] | undefined;
|
|
1067
|
+
handoverInterval?: number | undefined;
|
|
1068
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
1035
1069
|
}, {
|
|
1036
1070
|
maxTicketsPerSession?: number | undefined;
|
|
1037
1071
|
compactThreshold?: string | undefined;
|
|
1038
1072
|
reviewBackends?: string[] | undefined;
|
|
1073
|
+
handoverInterval?: number | undefined;
|
|
1074
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
1039
1075
|
}>>;
|
|
1040
1076
|
}, z.ZodTypeAny, "passthrough">>;
|
|
1041
1077
|
roadmap: z.ZodObject<{
|
|
@@ -1444,6 +1480,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1444
1480
|
maxTicketsPerSession?: number | undefined;
|
|
1445
1481
|
compactThreshold?: string | undefined;
|
|
1446
1482
|
reviewBackends?: string[] | undefined;
|
|
1483
|
+
handoverInterval?: number | undefined;
|
|
1484
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
1447
1485
|
} | undefined;
|
|
1448
1486
|
} & {
|
|
1449
1487
|
[k: string]: unknown;
|
|
@@ -1533,6 +1571,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1533
1571
|
maxTicketsPerSession?: number | undefined;
|
|
1534
1572
|
compactThreshold?: string | undefined;
|
|
1535
1573
|
reviewBackends?: string[] | undefined;
|
|
1574
|
+
handoverInterval?: number | undefined;
|
|
1575
|
+
stages?: Record<string, Record<string, unknown>> | undefined;
|
|
1536
1576
|
} | undefined;
|
|
1537
1577
|
} & {
|
|
1538
1578
|
[k: string]: unknown;
|
package/dist/index.js
CHANGED
|
@@ -140,7 +140,9 @@ var ConfigSchema = z6.object({
|
|
|
140
140
|
recipeOverrides: z6.object({
|
|
141
141
|
maxTicketsPerSession: z6.number().min(0).optional(),
|
|
142
142
|
compactThreshold: z6.string().optional(),
|
|
143
|
-
reviewBackends: z6.array(z6.string()).optional()
|
|
143
|
+
reviewBackends: z6.array(z6.string()).optional(),
|
|
144
|
+
handoverInterval: z6.number().min(0).optional(),
|
|
145
|
+
stages: z6.record(z6.record(z6.unknown())).optional()
|
|
144
146
|
}).optional()
|
|
145
147
|
}).passthrough();
|
|
146
148
|
|
package/dist/mcp.js
CHANGED
|
@@ -240,7 +240,9 @@ var init_config = __esm({
|
|
|
240
240
|
recipeOverrides: z7.object({
|
|
241
241
|
maxTicketsPerSession: z7.number().min(0).optional(),
|
|
242
242
|
compactThreshold: z7.string().optional(),
|
|
243
|
-
reviewBackends: z7.array(z7.string()).optional()
|
|
243
|
+
reviewBackends: z7.array(z7.string()).optional(),
|
|
244
|
+
handoverInterval: z7.number().min(0).optional(),
|
|
245
|
+
stages: z7.record(z7.record(z7.unknown())).optional()
|
|
244
246
|
}).optional()
|
|
245
247
|
}).passthrough();
|
|
246
248
|
}
|
|
@@ -3488,6 +3490,7 @@ var init_session_types = __esm({
|
|
|
3488
3490
|
"WRITE_TESTS",
|
|
3489
3491
|
"TEST",
|
|
3490
3492
|
"CODE_REVIEW",
|
|
3493
|
+
"BUILD",
|
|
3491
3494
|
"VERIFY",
|
|
3492
3495
|
"FINALIZE",
|
|
3493
3496
|
"COMPACT",
|
|
@@ -3638,6 +3641,7 @@ var init_session_types = __esm({
|
|
|
3638
3641
|
}).nullable().default(null),
|
|
3639
3642
|
testRetryCount: z9.number().default(0),
|
|
3640
3643
|
writeTestsRetryCount: z9.number().default(0),
|
|
3644
|
+
buildRetryCount: z9.number().default(0),
|
|
3641
3645
|
verifyRetryCount: z9.number().default(0),
|
|
3642
3646
|
verifyAutoDetected: z9.boolean().default(false),
|
|
3643
3647
|
// T-128: Resolved recipe (frozen at session start, survives compact/resume)
|
|
@@ -5510,7 +5514,19 @@ function resolveRecipe(recipeName, projectOverrides) {
|
|
|
5510
5514
|
}
|
|
5511
5515
|
}
|
|
5512
5516
|
let pipeline = raw.pipeline ? [...raw.pipeline] : [...DEFAULT_PIPELINE];
|
|
5513
|
-
const
|
|
5517
|
+
const recipeStages = raw.stages ?? {};
|
|
5518
|
+
const stageOverrides = projectOverrides?.stages ?? {};
|
|
5519
|
+
const stages2 = {};
|
|
5520
|
+
for (const [key, value] of Object.entries(recipeStages)) {
|
|
5521
|
+
const override = stageOverrides[key];
|
|
5522
|
+
const safeOverride = override && typeof override === "object" && !Array.isArray(override) ? override : {};
|
|
5523
|
+
stages2[key] = { ...value, ...safeOverride };
|
|
5524
|
+
}
|
|
5525
|
+
for (const [key, value] of Object.entries(stageOverrides)) {
|
|
5526
|
+
if (!stages2[key] && value && typeof value === "object" && !Array.isArray(value)) {
|
|
5527
|
+
stages2[key] = { ...value };
|
|
5528
|
+
}
|
|
5529
|
+
}
|
|
5514
5530
|
if (stages2.WRITE_TESTS?.enabled) {
|
|
5515
5531
|
const implementIdx = pipeline.indexOf("IMPLEMENT");
|
|
5516
5532
|
if (implementIdx !== -1 && !pipeline.includes("WRITE_TESTS")) {
|
|
@@ -5523,6 +5539,12 @@ function resolveRecipe(recipeName, projectOverrides) {
|
|
|
5523
5539
|
pipeline.splice(codeReviewIdx + 1, 0, "VERIFY");
|
|
5524
5540
|
}
|
|
5525
5541
|
}
|
|
5542
|
+
if (stages2.BUILD?.enabled) {
|
|
5543
|
+
const finalizeIdx = pipeline.indexOf("FINALIZE");
|
|
5544
|
+
if (finalizeIdx !== -1 && !pipeline.includes("BUILD")) {
|
|
5545
|
+
pipeline.splice(finalizeIdx, 0, "BUILD");
|
|
5546
|
+
}
|
|
5547
|
+
}
|
|
5526
5548
|
if (stages2.TEST?.enabled) {
|
|
5527
5549
|
const implementIdx = pipeline.indexOf("IMPLEMENT");
|
|
5528
5550
|
if (implementIdx !== -1 && !pipeline.includes("TEST")) {
|
|
@@ -6079,7 +6101,8 @@ var ImplementStage = class {
|
|
|
6079
6101
|
].join("\n"),
|
|
6080
6102
|
reminders: [
|
|
6081
6103
|
"Follow the plan exactly. Do NOT deviate without re-planning.",
|
|
6082
|
-
"Do NOT ask the user for confirmation."
|
|
6104
|
+
"Do NOT ask the user for confirmation.",
|
|
6105
|
+
"If you discover pre-existing bugs, failing tests not caused by your changes, or other out-of-scope problems, file them as issues using claudestory_issue_create. Do not fix them inline."
|
|
6083
6106
|
],
|
|
6084
6107
|
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6085
6108
|
};
|
|
@@ -6338,12 +6361,16 @@ var CodeReviewStage = class {
|
|
|
6338
6361
|
"",
|
|
6339
6362
|
`Capture the diff with: ${diffCommand}`,
|
|
6340
6363
|
"",
|
|
6341
|
-
"**IMPORTANT:** Pass the FULL unified diff
|
|
6364
|
+
"**IMPORTANT:** Pass the FULL unified diff to the reviewer. For diffs over ~500 lines, use file-scoped chunks (`git diff <mergebase> -- <filepath>`) across separate calls (pass the same session_id). Do NOT summarize or truncate any individual chunk.",
|
|
6342
6365
|
"",
|
|
6343
6366
|
`Run a code review using **${reviewer}**.`,
|
|
6344
6367
|
"When done, report verdict and findings."
|
|
6345
6368
|
].join("\n"),
|
|
6346
|
-
reminders: [
|
|
6369
|
+
reminders: [
|
|
6370
|
+
diffReminder,
|
|
6371
|
+
"Do NOT compress or summarize the diff.",
|
|
6372
|
+
"If the reviewer flags pre-existing issues unrelated to your changes, file them as issues using claudestory_issue_create with severity and impact. Do not fix them in this ticket."
|
|
6373
|
+
],
|
|
6347
6374
|
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6348
6375
|
};
|
|
6349
6376
|
}
|
|
@@ -6456,6 +6483,89 @@ var CodeReviewStage = class {
|
|
|
6456
6483
|
}
|
|
6457
6484
|
};
|
|
6458
6485
|
|
|
6486
|
+
// src/autonomous/stages/build.ts
|
|
6487
|
+
init_esm_shims();
|
|
6488
|
+
var MAX_BUILD_RETRIES = 2;
|
|
6489
|
+
var BuildStage = class {
|
|
6490
|
+
id = "BUILD";
|
|
6491
|
+
skip(ctx) {
|
|
6492
|
+
const buildConfig = ctx.recipe.stages?.BUILD;
|
|
6493
|
+
return !buildConfig?.enabled;
|
|
6494
|
+
}
|
|
6495
|
+
async enter(ctx) {
|
|
6496
|
+
const buildConfig = ctx.recipe.stages?.BUILD;
|
|
6497
|
+
const command = buildConfig?.command ?? "npm run build";
|
|
6498
|
+
const retryCount = ctx.state.buildRetryCount ?? 0;
|
|
6499
|
+
return {
|
|
6500
|
+
instruction: [
|
|
6501
|
+
`# Build${retryCount > 0 ? ` (retry ${retryCount}/${MAX_BUILD_RETRIES})` : ""}`,
|
|
6502
|
+
"",
|
|
6503
|
+
`Run the build: \`${command}\``,
|
|
6504
|
+
"",
|
|
6505
|
+
"Report the results with:",
|
|
6506
|
+
"```json",
|
|
6507
|
+
`{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "build_done", "notes": "<exit code and summary>" } }`,
|
|
6508
|
+
"```",
|
|
6509
|
+
"",
|
|
6510
|
+
"Include the exit code (0 = pass, non-0 = fail) and any error output in notes."
|
|
6511
|
+
].join("\n"),
|
|
6512
|
+
reminders: ["Run the FULL build, not a partial or dev-mode build."],
|
|
6513
|
+
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6514
|
+
};
|
|
6515
|
+
}
|
|
6516
|
+
async report(ctx, report) {
|
|
6517
|
+
const notes = report.notes ?? "";
|
|
6518
|
+
const retryCount = ctx.state.buildRetryCount ?? 0;
|
|
6519
|
+
const exitCodeMatch = notes.match(/exit\s*(?:code[:\s]*)?\s*(\d+)/i);
|
|
6520
|
+
if (!exitCodeMatch) {
|
|
6521
|
+
const nextRetry = retryCount + 1;
|
|
6522
|
+
if (nextRetry > MAX_BUILD_RETRIES) {
|
|
6523
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6524
|
+
ctx.appendEvent("build_parse_exhausted", { retryCount: nextRetry });
|
|
6525
|
+
return {
|
|
6526
|
+
action: "advance",
|
|
6527
|
+
result: {
|
|
6528
|
+
instruction: `Could not parse build exit code after ${MAX_BUILD_RETRIES} retries. Proceeding, but build status is unknown.`,
|
|
6529
|
+
reminders: ["Mention unknown build status in the commit message."]
|
|
6530
|
+
}
|
|
6531
|
+
};
|
|
6532
|
+
}
|
|
6533
|
+
ctx.writeState({ buildRetryCount: nextRetry });
|
|
6534
|
+
return { action: "retry", instruction: 'Could not parse exit code from notes. Include "exit code: 0" (or non-zero) in your notes.' };
|
|
6535
|
+
}
|
|
6536
|
+
const exitCode = parseInt(exitCodeMatch[1], 10);
|
|
6537
|
+
if (exitCode === 0) {
|
|
6538
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6539
|
+
ctx.appendEvent("build_passed", { retryCount, notes: notes.slice(0, 200) });
|
|
6540
|
+
return { action: "advance" };
|
|
6541
|
+
}
|
|
6542
|
+
if (retryCount < MAX_BUILD_RETRIES) {
|
|
6543
|
+
ctx.writeState({ buildRetryCount: retryCount + 1 });
|
|
6544
|
+
ctx.appendEvent("build_failed_retry", { retryCount: retryCount + 1, notes: notes.slice(0, 200) });
|
|
6545
|
+
return {
|
|
6546
|
+
action: "back",
|
|
6547
|
+
target: "IMPLEMENT",
|
|
6548
|
+
reason: `Build failed (attempt ${retryCount + 1}/${MAX_BUILD_RETRIES}). Fix the build errors.`
|
|
6549
|
+
};
|
|
6550
|
+
}
|
|
6551
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6552
|
+
ctx.appendEvent("build_failed_exhausted", { retryCount, notes: notes.slice(0, 200) });
|
|
6553
|
+
return {
|
|
6554
|
+
action: "advance",
|
|
6555
|
+
result: {
|
|
6556
|
+
instruction: [
|
|
6557
|
+
"# Build Failed - Proceeding",
|
|
6558
|
+
"",
|
|
6559
|
+
`Build failed after ${MAX_BUILD_RETRIES} retries. Proceeding but build errors remain.`,
|
|
6560
|
+
"",
|
|
6561
|
+
"Document the build failure in the commit message."
|
|
6562
|
+
].join("\n"),
|
|
6563
|
+
reminders: ["Mention build failure in the commit message."]
|
|
6564
|
+
}
|
|
6565
|
+
};
|
|
6566
|
+
}
|
|
6567
|
+
};
|
|
6568
|
+
|
|
6459
6569
|
// src/autonomous/stages/verify.ts
|
|
6460
6570
|
init_esm_shims();
|
|
6461
6571
|
var MAX_VERIFY_RETRIES = 3;
|
|
@@ -7219,6 +7329,7 @@ registerStage(new ImplementStage());
|
|
|
7219
7329
|
registerStage(new WriteTestsStage());
|
|
7220
7330
|
registerStage(new TestStage());
|
|
7221
7331
|
registerStage(new CodeReviewStage());
|
|
7332
|
+
registerStage(new BuildStage());
|
|
7222
7333
|
registerStage(new VerifyStage());
|
|
7223
7334
|
registerStage(new FinalizeStage());
|
|
7224
7335
|
registerStage(new CompleteStage());
|
|
@@ -7434,6 +7545,9 @@ async function handleStart(root, args) {
|
|
|
7434
7545
|
if (typeof overrides.compactThreshold === "string") sessionConfig.compactThreshold = overrides.compactThreshold;
|
|
7435
7546
|
if (Array.isArray(overrides.reviewBackends)) sessionConfig.reviewBackends = overrides.reviewBackends;
|
|
7436
7547
|
if (typeof overrides.handoverInterval === "number") sessionConfig.handoverInterval = overrides.handoverInterval;
|
|
7548
|
+
if (overrides.stages && typeof overrides.stages === "object") {
|
|
7549
|
+
sessionConfig.stageOverrides = overrides.stages;
|
|
7550
|
+
}
|
|
7437
7551
|
}
|
|
7438
7552
|
} catch {
|
|
7439
7553
|
}
|
|
@@ -7443,7 +7557,8 @@ async function handleStart(root, args) {
|
|
|
7443
7557
|
const resolvedRecipe = resolveRecipe(recipe, {
|
|
7444
7558
|
maxTicketsPerSession: sessionConfig.maxTicketsPerSession,
|
|
7445
7559
|
compactThreshold: sessionConfig.compactThreshold,
|
|
7446
|
-
reviewBackends: sessionConfig.reviewBackends
|
|
7560
|
+
reviewBackends: sessionConfig.reviewBackends,
|
|
7561
|
+
stages: sessionConfig.stageOverrides
|
|
7447
7562
|
});
|
|
7448
7563
|
const session = createSession(root, recipe, wsId, sessionConfig);
|
|
7449
7564
|
const dir = sessionDir(root, session.sessionId);
|
|
@@ -8244,14 +8359,6 @@ async function handleCancel(root, args) {
|
|
|
8244
8359
|
if (info.state.state === "SESSION_END" || info.state.status === "completed") {
|
|
8245
8360
|
return guideError(new Error("Session already ended."));
|
|
8246
8361
|
}
|
|
8247
|
-
const CANCELLABLE_STATES = /* @__PURE__ */ new Set(["PICK_TICKET", "COMPLETE", "HANDOVER"]);
|
|
8248
|
-
if (info.state.recipe === "coding" && !CANCELLABLE_STATES.has(info.state.state)) {
|
|
8249
|
-
const sessionMode = info.state.mode ?? "auto";
|
|
8250
|
-
const modeGuidance = sessionMode === "plan" ? "Plan mode sessions end after plan review approval \u2014 continue to that step." : sessionMode === "review" ? "Review mode sessions end after code review approval \u2014 continue to that step." : sessionMode === "guided" ? "Guided mode sessions end after ticket completion \u2014 continue to FINALIZE." : "Complete the current ticket and write a handover to end the session.";
|
|
8251
|
-
return guideError(new Error(
|
|
8252
|
-
`Cannot cancel a coding session from ${info.state.state}. ${modeGuidance}`
|
|
8253
|
-
));
|
|
8254
|
-
}
|
|
8255
8362
|
await recoverPendingMutation(info.dir, info.state, root);
|
|
8256
8363
|
const cancelInfo = findSessionById(root, args.sessionId) ?? info;
|
|
8257
8364
|
let ticketReleased = false;
|
|
@@ -9414,7 +9521,7 @@ async function ensureGitignoreEntries(gitignorePath, entries) {
|
|
|
9414
9521
|
// src/mcp/index.ts
|
|
9415
9522
|
var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
|
|
9416
9523
|
var CONFIG_PATH2 = ".story/config.json";
|
|
9417
|
-
var version = "0.1.
|
|
9524
|
+
var version = "0.1.34";
|
|
9418
9525
|
function tryDiscoverRoot() {
|
|
9419
9526
|
const envRoot = process.env[ENV_VAR2];
|
|
9420
9527
|
if (envRoot) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anthropologies/claudestory",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
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": [
|