@anthropologies/claudestory 0.1.31 → 0.1.33
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 -7
- package/dist/index.d.ts +40 -40
- package/dist/mcp.js +122 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5021,6 +5021,7 @@ var init_session_types = __esm({
|
|
|
5021
5021
|
"WRITE_TESTS",
|
|
5022
5022
|
"TEST",
|
|
5023
5023
|
"CODE_REVIEW",
|
|
5024
|
+
"BUILD",
|
|
5024
5025
|
"VERIFY",
|
|
5025
5026
|
"FINALIZE",
|
|
5026
5027
|
"COMPACT",
|
|
@@ -5046,6 +5047,7 @@ var init_session_types = __esm({
|
|
|
5046
5047
|
"WRITE_TESTS",
|
|
5047
5048
|
"TEST",
|
|
5048
5049
|
"CODE_REVIEW",
|
|
5050
|
+
"BUILD",
|
|
5049
5051
|
"VERIFY",
|
|
5050
5052
|
"FINALIZE",
|
|
5051
5053
|
"COMPACT",
|
|
@@ -5196,6 +5198,7 @@ var init_session_types = __esm({
|
|
|
5196
5198
|
}).nullable().default(null),
|
|
5197
5199
|
testRetryCount: z9.number().default(0),
|
|
5198
5200
|
writeTestsRetryCount: z9.number().default(0),
|
|
5201
|
+
buildRetryCount: z9.number().default(0),
|
|
5199
5202
|
verifyRetryCount: z9.number().default(0),
|
|
5200
5203
|
verifyAutoDetected: z9.boolean().default(false),
|
|
5201
5204
|
// T-128: Resolved recipe (frozen at session start, survives compact/resume)
|
|
@@ -5914,6 +5917,12 @@ function resolveRecipe(recipeName, projectOverrides) {
|
|
|
5914
5917
|
pipeline.splice(codeReviewIdx + 1, 0, "VERIFY");
|
|
5915
5918
|
}
|
|
5916
5919
|
}
|
|
5920
|
+
if (stages2.BUILD?.enabled) {
|
|
5921
|
+
const finalizeIdx = pipeline.indexOf("FINALIZE");
|
|
5922
|
+
if (finalizeIdx !== -1 && !pipeline.includes("BUILD")) {
|
|
5923
|
+
pipeline.splice(finalizeIdx, 0, "BUILD");
|
|
5924
|
+
}
|
|
5925
|
+
}
|
|
5917
5926
|
if (stages2.TEST?.enabled) {
|
|
5918
5927
|
const implementIdx = pipeline.indexOf("IMPLEMENT");
|
|
5919
5928
|
if (implementIdx !== -1 && !pipeline.includes("TEST")) {
|
|
@@ -6526,7 +6535,8 @@ var init_implement = __esm({
|
|
|
6526
6535
|
].join("\n"),
|
|
6527
6536
|
reminders: [
|
|
6528
6537
|
"Follow the plan exactly. Do NOT deviate without re-planning.",
|
|
6529
|
-
"Do NOT ask the user for confirmation."
|
|
6538
|
+
"Do NOT ask the user for confirmation.",
|
|
6539
|
+
"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
6540
|
],
|
|
6531
6541
|
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6532
6542
|
};
|
|
@@ -6804,12 +6814,16 @@ var init_code_review = __esm({
|
|
|
6804
6814
|
"",
|
|
6805
6815
|
`Capture the diff with: ${diffCommand}`,
|
|
6806
6816
|
"",
|
|
6807
|
-
"**IMPORTANT:** Pass the FULL unified diff
|
|
6817
|
+
"**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
6818
|
"",
|
|
6809
6819
|
`Run a code review using **${reviewer}**.`,
|
|
6810
6820
|
"When done, report verdict and findings."
|
|
6811
6821
|
].join("\n"),
|
|
6812
|
-
reminders: [
|
|
6822
|
+
reminders: [
|
|
6823
|
+
diffReminder,
|
|
6824
|
+
"Do NOT compress or summarize the diff.",
|
|
6825
|
+
"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."
|
|
6826
|
+
],
|
|
6813
6827
|
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6814
6828
|
};
|
|
6815
6829
|
}
|
|
@@ -6924,6 +6938,95 @@ var init_code_review = __esm({
|
|
|
6924
6938
|
}
|
|
6925
6939
|
});
|
|
6926
6940
|
|
|
6941
|
+
// src/autonomous/stages/build.ts
|
|
6942
|
+
var MAX_BUILD_RETRIES, BuildStage;
|
|
6943
|
+
var init_build = __esm({
|
|
6944
|
+
"src/autonomous/stages/build.ts"() {
|
|
6945
|
+
"use strict";
|
|
6946
|
+
init_esm_shims();
|
|
6947
|
+
MAX_BUILD_RETRIES = 2;
|
|
6948
|
+
BuildStage = class {
|
|
6949
|
+
id = "BUILD";
|
|
6950
|
+
skip(ctx) {
|
|
6951
|
+
const buildConfig = ctx.recipe.stages?.BUILD;
|
|
6952
|
+
return !buildConfig?.enabled;
|
|
6953
|
+
}
|
|
6954
|
+
async enter(ctx) {
|
|
6955
|
+
const buildConfig = ctx.recipe.stages?.BUILD;
|
|
6956
|
+
const command = buildConfig?.command ?? "npm run build";
|
|
6957
|
+
const retryCount = ctx.state.buildRetryCount ?? 0;
|
|
6958
|
+
return {
|
|
6959
|
+
instruction: [
|
|
6960
|
+
`# Build${retryCount > 0 ? ` (retry ${retryCount}/${MAX_BUILD_RETRIES})` : ""}`,
|
|
6961
|
+
"",
|
|
6962
|
+
`Run the build: \`${command}\``,
|
|
6963
|
+
"",
|
|
6964
|
+
"Report the results with:",
|
|
6965
|
+
"```json",
|
|
6966
|
+
`{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "build_done", "notes": "<exit code and summary>" } }`,
|
|
6967
|
+
"```",
|
|
6968
|
+
"",
|
|
6969
|
+
"Include the exit code (0 = pass, non-0 = fail) and any error output in notes."
|
|
6970
|
+
].join("\n"),
|
|
6971
|
+
reminders: ["Run the FULL build, not a partial or dev-mode build."],
|
|
6972
|
+
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6973
|
+
};
|
|
6974
|
+
}
|
|
6975
|
+
async report(ctx, report) {
|
|
6976
|
+
const notes = report.notes ?? "";
|
|
6977
|
+
const retryCount = ctx.state.buildRetryCount ?? 0;
|
|
6978
|
+
const exitCodeMatch = notes.match(/exit\s*(?:code[:\s]*)?\s*(\d+)/i);
|
|
6979
|
+
if (!exitCodeMatch) {
|
|
6980
|
+
const nextRetry = retryCount + 1;
|
|
6981
|
+
if (nextRetry > MAX_BUILD_RETRIES) {
|
|
6982
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6983
|
+
ctx.appendEvent("build_parse_exhausted", { retryCount: nextRetry });
|
|
6984
|
+
return {
|
|
6985
|
+
action: "advance",
|
|
6986
|
+
result: {
|
|
6987
|
+
instruction: `Could not parse build exit code after ${MAX_BUILD_RETRIES} retries. Proceeding, but build status is unknown.`,
|
|
6988
|
+
reminders: ["Mention unknown build status in the commit message."]
|
|
6989
|
+
}
|
|
6990
|
+
};
|
|
6991
|
+
}
|
|
6992
|
+
ctx.writeState({ buildRetryCount: nextRetry });
|
|
6993
|
+
return { action: "retry", instruction: 'Could not parse exit code from notes. Include "exit code: 0" (or non-zero) in your notes.' };
|
|
6994
|
+
}
|
|
6995
|
+
const exitCode = parseInt(exitCodeMatch[1], 10);
|
|
6996
|
+
if (exitCode === 0) {
|
|
6997
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6998
|
+
ctx.appendEvent("build_passed", { retryCount, notes: notes.slice(0, 200) });
|
|
6999
|
+
return { action: "advance" };
|
|
7000
|
+
}
|
|
7001
|
+
if (retryCount < MAX_BUILD_RETRIES) {
|
|
7002
|
+
ctx.writeState({ buildRetryCount: retryCount + 1 });
|
|
7003
|
+
ctx.appendEvent("build_failed_retry", { retryCount: retryCount + 1, notes: notes.slice(0, 200) });
|
|
7004
|
+
return {
|
|
7005
|
+
action: "back",
|
|
7006
|
+
target: "IMPLEMENT",
|
|
7007
|
+
reason: `Build failed (attempt ${retryCount + 1}/${MAX_BUILD_RETRIES}). Fix the build errors.`
|
|
7008
|
+
};
|
|
7009
|
+
}
|
|
7010
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
7011
|
+
ctx.appendEvent("build_failed_exhausted", { retryCount, notes: notes.slice(0, 200) });
|
|
7012
|
+
return {
|
|
7013
|
+
action: "advance",
|
|
7014
|
+
result: {
|
|
7015
|
+
instruction: [
|
|
7016
|
+
"# Build Failed - Proceeding",
|
|
7017
|
+
"",
|
|
7018
|
+
`Build failed after ${MAX_BUILD_RETRIES} retries. Proceeding but build errors remain.`,
|
|
7019
|
+
"",
|
|
7020
|
+
"Document the build failure in the commit message."
|
|
7021
|
+
].join("\n"),
|
|
7022
|
+
reminders: ["Mention build failure in the commit message."]
|
|
7023
|
+
}
|
|
7024
|
+
};
|
|
7025
|
+
}
|
|
7026
|
+
};
|
|
7027
|
+
}
|
|
7028
|
+
});
|
|
7029
|
+
|
|
6927
7030
|
// src/autonomous/stages/verify.ts
|
|
6928
7031
|
function exhaustionAction2(ctx) {
|
|
6929
7032
|
ctx.writeState({ verifyRetryCount: 0 });
|
|
@@ -7158,6 +7261,19 @@ var init_finalize = __esm({
|
|
|
7158
7261
|
};
|
|
7159
7262
|
}
|
|
7160
7263
|
async handleStage(ctx, report) {
|
|
7264
|
+
const checkpoint = ctx.state.finalizeCheckpoint;
|
|
7265
|
+
if (checkpoint === "staged" || checkpoint === "staged_override") {
|
|
7266
|
+
return {
|
|
7267
|
+
action: "retry",
|
|
7268
|
+
instruction: [
|
|
7269
|
+
"Files staged. Now run pre-commit checks.",
|
|
7270
|
+
"",
|
|
7271
|
+
'Run any pre-commit hooks or linting, then call me with completedAction: "precommit_passed".',
|
|
7272
|
+
'If pre-commit fails, fix the issues, re-stage, and call me with completedAction: "files_staged" again.'
|
|
7273
|
+
].join("\n"),
|
|
7274
|
+
reminders: ["Verify staged set is intact after pre-commit hooks."]
|
|
7275
|
+
};
|
|
7276
|
+
}
|
|
7161
7277
|
const stagedResult = await gitDiffCachedNames(ctx.root);
|
|
7162
7278
|
if (!stagedResult.ok || stagedResult.data.length === 0) {
|
|
7163
7279
|
const headResult = await gitHead(ctx.root);
|
|
@@ -7182,7 +7298,10 @@ var init_finalize = __esm({
|
|
|
7182
7298
|
const baselineUntracked = ctx.state.git.baseline?.untrackedPaths ?? [];
|
|
7183
7299
|
let overlapOverridden = false;
|
|
7184
7300
|
if (baselineUntracked.length > 0) {
|
|
7185
|
-
const
|
|
7301
|
+
const sessionTicketPath = ctx.state.ticket?.id ? `.story/tickets/${ctx.state.ticket.id}.json` : null;
|
|
7302
|
+
const overlap = stagedResult.data.filter(
|
|
7303
|
+
(f) => baselineUntracked.includes(f) && f !== sessionTicketPath
|
|
7304
|
+
);
|
|
7186
7305
|
if (overlap.length > 0) {
|
|
7187
7306
|
if (report.overrideOverlap) {
|
|
7188
7307
|
overlapOverridden = true;
|
|
@@ -7231,7 +7350,10 @@ var init_finalize = __esm({
|
|
|
7231
7350
|
if (checkpoint !== "staged_override") {
|
|
7232
7351
|
const baselineUntracked = ctx.state.git.baseline?.untrackedPaths ?? [];
|
|
7233
7352
|
if (baselineUntracked.length > 0) {
|
|
7234
|
-
const
|
|
7353
|
+
const sessionTicketPath = ctx.state.ticket?.id ? `.story/tickets/${ctx.state.ticket.id}.json` : null;
|
|
7354
|
+
const overlap = stagedResult.data.filter(
|
|
7355
|
+
(f) => baselineUntracked.includes(f) && f !== sessionTicketPath
|
|
7356
|
+
);
|
|
7235
7357
|
if (overlap.length > 0) {
|
|
7236
7358
|
ctx.writeState({ finalizeCheckpoint: null });
|
|
7237
7359
|
return { action: "retry", instruction: `Pre-commit hooks staged pre-existing untracked files: ${overlap.join(", ")}. Unstage them and re-stage, then call with completedAction: "files_staged".` };
|
|
@@ -7714,6 +7836,7 @@ var init_stages = __esm({
|
|
|
7714
7836
|
init_write_tests();
|
|
7715
7837
|
init_test();
|
|
7716
7838
|
init_code_review();
|
|
7839
|
+
init_build();
|
|
7717
7840
|
init_verify();
|
|
7718
7841
|
init_finalize();
|
|
7719
7842
|
init_complete();
|
|
@@ -7727,6 +7850,7 @@ var init_stages = __esm({
|
|
|
7727
7850
|
registerStage(new WriteTestsStage());
|
|
7728
7851
|
registerStage(new TestStage());
|
|
7729
7852
|
registerStage(new CodeReviewStage());
|
|
7853
|
+
registerStage(new BuildStage());
|
|
7730
7854
|
registerStage(new VerifyStage());
|
|
7731
7855
|
registerStage(new FinalizeStage());
|
|
7732
7856
|
registerStage(new CompleteStage());
|
|
@@ -10239,7 +10363,7 @@ var init_mcp = __esm({
|
|
|
10239
10363
|
init_init();
|
|
10240
10364
|
ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
|
|
10241
10365
|
CONFIG_PATH2 = ".story/config.json";
|
|
10242
|
-
version = "0.1.
|
|
10366
|
+
version = "0.1.33";
|
|
10243
10367
|
main().catch((err) => {
|
|
10244
10368
|
process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}
|
|
10245
10369
|
`);
|
|
@@ -13523,7 +13647,7 @@ async function runCli() {
|
|
|
13523
13647
|
registerConfigCommand: registerConfigCommand2,
|
|
13524
13648
|
registerSessionCommand: registerSessionCommand2
|
|
13525
13649
|
} = await Promise.resolve().then(() => (init_register(), register_exports));
|
|
13526
|
-
const version2 = "0.1.
|
|
13650
|
+
const version2 = "0.1.33";
|
|
13527
13651
|
class HandledError extends Error {
|
|
13528
13652
|
constructor() {
|
|
13529
13653
|
super("HANDLED_ERROR");
|
package/dist/index.d.ts
CHANGED
|
@@ -1334,15 +1334,40 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1334
1334
|
file: z.ZodString;
|
|
1335
1335
|
message: z.ZodString;
|
|
1336
1336
|
}, "strip", z.ZodTypeAny, {
|
|
1337
|
-
message: string;
|
|
1338
1337
|
type: string;
|
|
1338
|
+
message: string;
|
|
1339
1339
|
file: string;
|
|
1340
1340
|
}, {
|
|
1341
|
-
message: string;
|
|
1342
1341
|
type: string;
|
|
1342
|
+
message: string;
|
|
1343
1343
|
file: string;
|
|
1344
1344
|
}>, "many">>;
|
|
1345
1345
|
}, "strip", z.ZodTypeAny, {
|
|
1346
|
+
version: 1;
|
|
1347
|
+
config: {
|
|
1348
|
+
version: number;
|
|
1349
|
+
type: string;
|
|
1350
|
+
language: string;
|
|
1351
|
+
project: string;
|
|
1352
|
+
features: {
|
|
1353
|
+
issues: boolean;
|
|
1354
|
+
tickets: boolean;
|
|
1355
|
+
handovers: boolean;
|
|
1356
|
+
roadmap: boolean;
|
|
1357
|
+
reviews: boolean;
|
|
1358
|
+
} & {
|
|
1359
|
+
[k: string]: unknown;
|
|
1360
|
+
};
|
|
1361
|
+
schemaVersion?: number | undefined;
|
|
1362
|
+
recipe?: string | undefined;
|
|
1363
|
+
recipeOverrides?: {
|
|
1364
|
+
maxTicketsPerSession?: number | undefined;
|
|
1365
|
+
compactThreshold?: string | undefined;
|
|
1366
|
+
reviewBackends?: string[] | undefined;
|
|
1367
|
+
} | undefined;
|
|
1368
|
+
} & {
|
|
1369
|
+
[k: string]: unknown;
|
|
1370
|
+
};
|
|
1346
1371
|
issues: z.objectOutputType<{
|
|
1347
1372
|
id: z.ZodString;
|
|
1348
1373
|
title: z.ZodString;
|
|
@@ -1379,8 +1404,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1379
1404
|
claimedBySession: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1380
1405
|
}, z.ZodTypeAny, "passthrough">[];
|
|
1381
1406
|
roadmap: {
|
|
1382
|
-
title: string;
|
|
1383
1407
|
date: string;
|
|
1408
|
+
title: string;
|
|
1384
1409
|
phases: z.objectOutputType<{
|
|
1385
1410
|
id: z.ZodString;
|
|
1386
1411
|
label: z.ZodString;
|
|
@@ -1398,7 +1423,6 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1398
1423
|
} & {
|
|
1399
1424
|
[k: string]: unknown;
|
|
1400
1425
|
};
|
|
1401
|
-
version: 1;
|
|
1402
1426
|
project: string;
|
|
1403
1427
|
notes: z.objectOutputType<{
|
|
1404
1428
|
id: z.ZodString;
|
|
@@ -1424,11 +1448,19 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1424
1448
|
status: z.ZodEnum<["active", "deprecated", "superseded"]>;
|
|
1425
1449
|
}, z.ZodTypeAny, "passthrough">[];
|
|
1426
1450
|
createdAt: string;
|
|
1427
|
-
|
|
1451
|
+
handoverFilenames: string[];
|
|
1452
|
+
warnings?: {
|
|
1428
1453
|
type: string;
|
|
1454
|
+
message: string;
|
|
1455
|
+
file: string;
|
|
1456
|
+
}[] | undefined;
|
|
1457
|
+
}, {
|
|
1458
|
+
version: 1;
|
|
1459
|
+
config: {
|
|
1429
1460
|
version: number;
|
|
1430
|
-
|
|
1461
|
+
type: string;
|
|
1431
1462
|
language: string;
|
|
1463
|
+
project: string;
|
|
1432
1464
|
features: {
|
|
1433
1465
|
issues: boolean;
|
|
1434
1466
|
tickets: boolean;
|
|
@@ -1448,13 +1480,6 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1448
1480
|
} & {
|
|
1449
1481
|
[k: string]: unknown;
|
|
1450
1482
|
};
|
|
1451
|
-
handoverFilenames: string[];
|
|
1452
|
-
warnings?: {
|
|
1453
|
-
message: string;
|
|
1454
|
-
type: string;
|
|
1455
|
-
file: string;
|
|
1456
|
-
}[] | undefined;
|
|
1457
|
-
}, {
|
|
1458
1483
|
issues: z.objectInputType<{
|
|
1459
1484
|
id: z.ZodString;
|
|
1460
1485
|
title: z.ZodString;
|
|
@@ -1491,8 +1516,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1491
1516
|
claimedBySession: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1492
1517
|
}, z.ZodTypeAny, "passthrough">[];
|
|
1493
1518
|
roadmap: {
|
|
1494
|
-
title: string;
|
|
1495
1519
|
date: string;
|
|
1520
|
+
title: string;
|
|
1496
1521
|
phases: z.objectInputType<{
|
|
1497
1522
|
id: z.ZodString;
|
|
1498
1523
|
label: z.ZodString;
|
|
@@ -1510,33 +1535,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1510
1535
|
} & {
|
|
1511
1536
|
[k: string]: unknown;
|
|
1512
1537
|
};
|
|
1513
|
-
version: 1;
|
|
1514
1538
|
project: string;
|
|
1515
1539
|
createdAt: string;
|
|
1516
|
-
config: {
|
|
1517
|
-
type: string;
|
|
1518
|
-
version: number;
|
|
1519
|
-
project: string;
|
|
1520
|
-
language: string;
|
|
1521
|
-
features: {
|
|
1522
|
-
issues: boolean;
|
|
1523
|
-
tickets: boolean;
|
|
1524
|
-
handovers: boolean;
|
|
1525
|
-
roadmap: boolean;
|
|
1526
|
-
reviews: boolean;
|
|
1527
|
-
} & {
|
|
1528
|
-
[k: string]: unknown;
|
|
1529
|
-
};
|
|
1530
|
-
schemaVersion?: number | undefined;
|
|
1531
|
-
recipe?: string | undefined;
|
|
1532
|
-
recipeOverrides?: {
|
|
1533
|
-
maxTicketsPerSession?: number | undefined;
|
|
1534
|
-
compactThreshold?: string | undefined;
|
|
1535
|
-
reviewBackends?: string[] | undefined;
|
|
1536
|
-
} | undefined;
|
|
1537
|
-
} & {
|
|
1538
|
-
[k: string]: unknown;
|
|
1539
|
-
};
|
|
1540
1540
|
notes?: z.objectInputType<{
|
|
1541
1541
|
id: z.ZodString;
|
|
1542
1542
|
title: z.ZodNullable<z.ZodString>;
|
|
@@ -1561,8 +1561,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
|
|
|
1561
1561
|
status: z.ZodEnum<["active", "deprecated", "superseded"]>;
|
|
1562
1562
|
}, z.ZodTypeAny, "passthrough">[] | undefined;
|
|
1563
1563
|
warnings?: {
|
|
1564
|
-
message: string;
|
|
1565
1564
|
type: string;
|
|
1565
|
+
message: string;
|
|
1566
1566
|
file: string;
|
|
1567
1567
|
}[] | undefined;
|
|
1568
1568
|
handoverFilenames?: string[] | undefined;
|
package/dist/mcp.js
CHANGED
|
@@ -3488,6 +3488,7 @@ var init_session_types = __esm({
|
|
|
3488
3488
|
"WRITE_TESTS",
|
|
3489
3489
|
"TEST",
|
|
3490
3490
|
"CODE_REVIEW",
|
|
3491
|
+
"BUILD",
|
|
3491
3492
|
"VERIFY",
|
|
3492
3493
|
"FINALIZE",
|
|
3493
3494
|
"COMPACT",
|
|
@@ -3638,6 +3639,7 @@ var init_session_types = __esm({
|
|
|
3638
3639
|
}).nullable().default(null),
|
|
3639
3640
|
testRetryCount: z9.number().default(0),
|
|
3640
3641
|
writeTestsRetryCount: z9.number().default(0),
|
|
3642
|
+
buildRetryCount: z9.number().default(0),
|
|
3641
3643
|
verifyRetryCount: z9.number().default(0),
|
|
3642
3644
|
verifyAutoDetected: z9.boolean().default(false),
|
|
3643
3645
|
// T-128: Resolved recipe (frozen at session start, survives compact/resume)
|
|
@@ -5523,6 +5525,12 @@ function resolveRecipe(recipeName, projectOverrides) {
|
|
|
5523
5525
|
pipeline.splice(codeReviewIdx + 1, 0, "VERIFY");
|
|
5524
5526
|
}
|
|
5525
5527
|
}
|
|
5528
|
+
if (stages2.BUILD?.enabled) {
|
|
5529
|
+
const finalizeIdx = pipeline.indexOf("FINALIZE");
|
|
5530
|
+
if (finalizeIdx !== -1 && !pipeline.includes("BUILD")) {
|
|
5531
|
+
pipeline.splice(finalizeIdx, 0, "BUILD");
|
|
5532
|
+
}
|
|
5533
|
+
}
|
|
5526
5534
|
if (stages2.TEST?.enabled) {
|
|
5527
5535
|
const implementIdx = pipeline.indexOf("IMPLEMENT");
|
|
5528
5536
|
if (implementIdx !== -1 && !pipeline.includes("TEST")) {
|
|
@@ -6079,7 +6087,8 @@ var ImplementStage = class {
|
|
|
6079
6087
|
].join("\n"),
|
|
6080
6088
|
reminders: [
|
|
6081
6089
|
"Follow the plan exactly. Do NOT deviate without re-planning.",
|
|
6082
|
-
"Do NOT ask the user for confirmation."
|
|
6090
|
+
"Do NOT ask the user for confirmation.",
|
|
6091
|
+
"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
6092
|
],
|
|
6084
6093
|
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6085
6094
|
};
|
|
@@ -6338,12 +6347,16 @@ var CodeReviewStage = class {
|
|
|
6338
6347
|
"",
|
|
6339
6348
|
`Capture the diff with: ${diffCommand}`,
|
|
6340
6349
|
"",
|
|
6341
|
-
"**IMPORTANT:** Pass the FULL unified diff
|
|
6350
|
+
"**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
6351
|
"",
|
|
6343
6352
|
`Run a code review using **${reviewer}**.`,
|
|
6344
6353
|
"When done, report verdict and findings."
|
|
6345
6354
|
].join("\n"),
|
|
6346
|
-
reminders: [
|
|
6355
|
+
reminders: [
|
|
6356
|
+
diffReminder,
|
|
6357
|
+
"Do NOT compress or summarize the diff.",
|
|
6358
|
+
"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."
|
|
6359
|
+
],
|
|
6347
6360
|
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6348
6361
|
};
|
|
6349
6362
|
}
|
|
@@ -6456,6 +6469,89 @@ var CodeReviewStage = class {
|
|
|
6456
6469
|
}
|
|
6457
6470
|
};
|
|
6458
6471
|
|
|
6472
|
+
// src/autonomous/stages/build.ts
|
|
6473
|
+
init_esm_shims();
|
|
6474
|
+
var MAX_BUILD_RETRIES = 2;
|
|
6475
|
+
var BuildStage = class {
|
|
6476
|
+
id = "BUILD";
|
|
6477
|
+
skip(ctx) {
|
|
6478
|
+
const buildConfig = ctx.recipe.stages?.BUILD;
|
|
6479
|
+
return !buildConfig?.enabled;
|
|
6480
|
+
}
|
|
6481
|
+
async enter(ctx) {
|
|
6482
|
+
const buildConfig = ctx.recipe.stages?.BUILD;
|
|
6483
|
+
const command = buildConfig?.command ?? "npm run build";
|
|
6484
|
+
const retryCount = ctx.state.buildRetryCount ?? 0;
|
|
6485
|
+
return {
|
|
6486
|
+
instruction: [
|
|
6487
|
+
`# Build${retryCount > 0 ? ` (retry ${retryCount}/${MAX_BUILD_RETRIES})` : ""}`,
|
|
6488
|
+
"",
|
|
6489
|
+
`Run the build: \`${command}\``,
|
|
6490
|
+
"",
|
|
6491
|
+
"Report the results with:",
|
|
6492
|
+
"```json",
|
|
6493
|
+
`{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "build_done", "notes": "<exit code and summary>" } }`,
|
|
6494
|
+
"```",
|
|
6495
|
+
"",
|
|
6496
|
+
"Include the exit code (0 = pass, non-0 = fail) and any error output in notes."
|
|
6497
|
+
].join("\n"),
|
|
6498
|
+
reminders: ["Run the FULL build, not a partial or dev-mode build."],
|
|
6499
|
+
transitionedFrom: ctx.state.previousState ?? void 0
|
|
6500
|
+
};
|
|
6501
|
+
}
|
|
6502
|
+
async report(ctx, report) {
|
|
6503
|
+
const notes = report.notes ?? "";
|
|
6504
|
+
const retryCount = ctx.state.buildRetryCount ?? 0;
|
|
6505
|
+
const exitCodeMatch = notes.match(/exit\s*(?:code[:\s]*)?\s*(\d+)/i);
|
|
6506
|
+
if (!exitCodeMatch) {
|
|
6507
|
+
const nextRetry = retryCount + 1;
|
|
6508
|
+
if (nextRetry > MAX_BUILD_RETRIES) {
|
|
6509
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6510
|
+
ctx.appendEvent("build_parse_exhausted", { retryCount: nextRetry });
|
|
6511
|
+
return {
|
|
6512
|
+
action: "advance",
|
|
6513
|
+
result: {
|
|
6514
|
+
instruction: `Could not parse build exit code after ${MAX_BUILD_RETRIES} retries. Proceeding, but build status is unknown.`,
|
|
6515
|
+
reminders: ["Mention unknown build status in the commit message."]
|
|
6516
|
+
}
|
|
6517
|
+
};
|
|
6518
|
+
}
|
|
6519
|
+
ctx.writeState({ buildRetryCount: nextRetry });
|
|
6520
|
+
return { action: "retry", instruction: 'Could not parse exit code from notes. Include "exit code: 0" (or non-zero) in your notes.' };
|
|
6521
|
+
}
|
|
6522
|
+
const exitCode = parseInt(exitCodeMatch[1], 10);
|
|
6523
|
+
if (exitCode === 0) {
|
|
6524
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6525
|
+
ctx.appendEvent("build_passed", { retryCount, notes: notes.slice(0, 200) });
|
|
6526
|
+
return { action: "advance" };
|
|
6527
|
+
}
|
|
6528
|
+
if (retryCount < MAX_BUILD_RETRIES) {
|
|
6529
|
+
ctx.writeState({ buildRetryCount: retryCount + 1 });
|
|
6530
|
+
ctx.appendEvent("build_failed_retry", { retryCount: retryCount + 1, notes: notes.slice(0, 200) });
|
|
6531
|
+
return {
|
|
6532
|
+
action: "back",
|
|
6533
|
+
target: "IMPLEMENT",
|
|
6534
|
+
reason: `Build failed (attempt ${retryCount + 1}/${MAX_BUILD_RETRIES}). Fix the build errors.`
|
|
6535
|
+
};
|
|
6536
|
+
}
|
|
6537
|
+
ctx.writeState({ buildRetryCount: 0 });
|
|
6538
|
+
ctx.appendEvent("build_failed_exhausted", { retryCount, notes: notes.slice(0, 200) });
|
|
6539
|
+
return {
|
|
6540
|
+
action: "advance",
|
|
6541
|
+
result: {
|
|
6542
|
+
instruction: [
|
|
6543
|
+
"# Build Failed - Proceeding",
|
|
6544
|
+
"",
|
|
6545
|
+
`Build failed after ${MAX_BUILD_RETRIES} retries. Proceeding but build errors remain.`,
|
|
6546
|
+
"",
|
|
6547
|
+
"Document the build failure in the commit message."
|
|
6548
|
+
].join("\n"),
|
|
6549
|
+
reminders: ["Mention build failure in the commit message."]
|
|
6550
|
+
}
|
|
6551
|
+
};
|
|
6552
|
+
}
|
|
6553
|
+
};
|
|
6554
|
+
|
|
6459
6555
|
// src/autonomous/stages/verify.ts
|
|
6460
6556
|
init_esm_shims();
|
|
6461
6557
|
var MAX_VERIFY_RETRIES = 3;
|
|
@@ -6678,6 +6774,19 @@ var FinalizeStage = class {
|
|
|
6678
6774
|
};
|
|
6679
6775
|
}
|
|
6680
6776
|
async handleStage(ctx, report) {
|
|
6777
|
+
const checkpoint = ctx.state.finalizeCheckpoint;
|
|
6778
|
+
if (checkpoint === "staged" || checkpoint === "staged_override") {
|
|
6779
|
+
return {
|
|
6780
|
+
action: "retry",
|
|
6781
|
+
instruction: [
|
|
6782
|
+
"Files staged. Now run pre-commit checks.",
|
|
6783
|
+
"",
|
|
6784
|
+
'Run any pre-commit hooks or linting, then call me with completedAction: "precommit_passed".',
|
|
6785
|
+
'If pre-commit fails, fix the issues, re-stage, and call me with completedAction: "files_staged" again.'
|
|
6786
|
+
].join("\n"),
|
|
6787
|
+
reminders: ["Verify staged set is intact after pre-commit hooks."]
|
|
6788
|
+
};
|
|
6789
|
+
}
|
|
6681
6790
|
const stagedResult = await gitDiffCachedNames(ctx.root);
|
|
6682
6791
|
if (!stagedResult.ok || stagedResult.data.length === 0) {
|
|
6683
6792
|
const headResult = await gitHead(ctx.root);
|
|
@@ -6702,7 +6811,10 @@ var FinalizeStage = class {
|
|
|
6702
6811
|
const baselineUntracked = ctx.state.git.baseline?.untrackedPaths ?? [];
|
|
6703
6812
|
let overlapOverridden = false;
|
|
6704
6813
|
if (baselineUntracked.length > 0) {
|
|
6705
|
-
const
|
|
6814
|
+
const sessionTicketPath = ctx.state.ticket?.id ? `.story/tickets/${ctx.state.ticket.id}.json` : null;
|
|
6815
|
+
const overlap = stagedResult.data.filter(
|
|
6816
|
+
(f) => baselineUntracked.includes(f) && f !== sessionTicketPath
|
|
6817
|
+
);
|
|
6706
6818
|
if (overlap.length > 0) {
|
|
6707
6819
|
if (report.overrideOverlap) {
|
|
6708
6820
|
overlapOverridden = true;
|
|
@@ -6751,7 +6863,10 @@ var FinalizeStage = class {
|
|
|
6751
6863
|
if (checkpoint !== "staged_override") {
|
|
6752
6864
|
const baselineUntracked = ctx.state.git.baseline?.untrackedPaths ?? [];
|
|
6753
6865
|
if (baselineUntracked.length > 0) {
|
|
6754
|
-
const
|
|
6866
|
+
const sessionTicketPath = ctx.state.ticket?.id ? `.story/tickets/${ctx.state.ticket.id}.json` : null;
|
|
6867
|
+
const overlap = stagedResult.data.filter(
|
|
6868
|
+
(f) => baselineUntracked.includes(f) && f !== sessionTicketPath
|
|
6869
|
+
);
|
|
6755
6870
|
if (overlap.length > 0) {
|
|
6756
6871
|
ctx.writeState({ finalizeCheckpoint: null });
|
|
6757
6872
|
return { action: "retry", instruction: `Pre-commit hooks staged pre-existing untracked files: ${overlap.join(", ")}. Unstage them and re-stage, then call with completedAction: "files_staged".` };
|
|
@@ -7200,6 +7315,7 @@ registerStage(new ImplementStage());
|
|
|
7200
7315
|
registerStage(new WriteTestsStage());
|
|
7201
7316
|
registerStage(new TestStage());
|
|
7202
7317
|
registerStage(new CodeReviewStage());
|
|
7318
|
+
registerStage(new BuildStage());
|
|
7203
7319
|
registerStage(new VerifyStage());
|
|
7204
7320
|
registerStage(new FinalizeStage());
|
|
7205
7321
|
registerStage(new CompleteStage());
|
|
@@ -9395,7 +9511,7 @@ async function ensureGitignoreEntries(gitignorePath, entries) {
|
|
|
9395
9511
|
// src/mcp/index.ts
|
|
9396
9512
|
var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
|
|
9397
9513
|
var CONFIG_PATH2 = ".story/config.json";
|
|
9398
|
-
var version = "0.1.
|
|
9514
|
+
var version = "0.1.33";
|
|
9399
9515
|
function tryDiscoverRoot() {
|
|
9400
9516
|
const envRoot = process.env[ENV_VAR2];
|
|
9401
9517
|
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.33",
|
|
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": [
|