@anthropologies/claudestory 0.1.38 → 0.1.39

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 CHANGED
@@ -5859,10 +5859,10 @@ var init_state_machine = __esm({
5859
5859
  PLAN: ["PLAN_REVIEW"],
5860
5860
  PLAN_REVIEW: ["IMPLEMENT", "WRITE_TESTS", "PLAN", "PLAN_REVIEW", "SESSION_END"],
5861
5861
  // approve → IMPLEMENT/WRITE_TESTS, reject → PLAN, stay for next round; SESSION_END for tiered exit
5862
- IMPLEMENT: ["CODE_REVIEW", "TEST"],
5863
- // TEST when test stage enabled
5864
- WRITE_TESTS: ["IMPLEMENT", "WRITE_TESTS", "PLAN"],
5865
- // advance → IMPLEMENT, retry stays, exhaustion → PLAN
5862
+ IMPLEMENT: ["CODE_REVIEW", "TEST", "COMPLETE"],
5863
+ // TEST when test stage enabled, COMPLETE for no-op tickets (ISS-069)
5864
+ WRITE_TESTS: ["IMPLEMENT", "WRITE_TESTS", "PLAN", "COMPLETE"],
5865
+ // advance → IMPLEMENT, retry stays, exhaustion → PLAN, no-op → COMPLETE (ISS-069)
5866
5866
  TEST: ["CODE_REVIEW", "IMPLEMENT", "TEST"],
5867
5867
  // pass → CODE_REVIEW, fail → IMPLEMENT, retry
5868
5868
  CODE_REVIEW: ["VERIFY", "FINALIZE", "IMPLEMENT", "PLAN", "CODE_REVIEW", "SESSION_END"],
@@ -6850,6 +6850,10 @@ var init_implement = __esm({
6850
6850
  };
6851
6851
  }
6852
6852
  async report(ctx, _report) {
6853
+ if (_report.completedAction === "no_implementation_needed") {
6854
+ ctx.appendEvent("implement", { result: "skipped", reason: "no_changes_needed" });
6855
+ return { action: "goto", target: "COMPLETE" };
6856
+ }
6853
6857
  let realizedRisk = ctx.state.ticket?.risk ?? "low";
6854
6858
  const mergeBase = ctx.state.git.mergeBase;
6855
6859
  if (mergeBase) {
@@ -6919,7 +6923,12 @@ var init_write_tests = __esm({
6919
6923
  `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "write_tests_done", "notes": "exit code: <N>, X passed, Y failed" } }`,
6920
6924
  "```",
6921
6925
  "",
6922
- "Include the exit code and pass/fail counts in your notes."
6926
+ "Include the exit code and pass/fail counts in your notes.",
6927
+ "",
6928
+ "**If your approved plan requires no code changes** (e.g., the bug is already fixed), update the ticket status to complete in .story/ and report:",
6929
+ "```json",
6930
+ `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "no_tests_needed", "notes": "No code changes needed \u2014 ticket resolved without implementation." } }`,
6931
+ "```"
6923
6932
  ].join("\n"),
6924
6933
  reminders: [
6925
6934
  "Tests MUST fail \u2014 they define unimplemented behavior.",
@@ -6930,6 +6939,11 @@ var init_write_tests = __esm({
6930
6939
  };
6931
6940
  }
6932
6941
  async report(ctx, report) {
6942
+ if (report.completedAction === "no_tests_needed") {
6943
+ ctx.writeState({ writeTestsRetryCount: 0 });
6944
+ ctx.appendEvent("write_tests", { result: "skipped", reason: "no_changes_needed" });
6945
+ return { action: "goto", target: "COMPLETE" };
6946
+ }
6933
6947
  const notes = report.notes ?? "";
6934
6948
  const retryCount = ctx.state.writeTestsRetryCount ?? 0;
6935
6949
  const exitMatch = notes.match(EXIT_CODE_REGEX);
@@ -7852,7 +7866,14 @@ var init_complete = __esm({
7852
7866
  const { state: projectState } = await ctx.loadProject();
7853
7867
  const nextResult = nextTickets(projectState, 1);
7854
7868
  if (nextResult.kind !== "found") {
7855
- nextTarget = "HANDOVER";
7869
+ const highIssues = projectState.issues.filter(
7870
+ (i) => i.status === "open" && (i.severity === "critical" || i.severity === "high")
7871
+ );
7872
+ if (highIssues.length > 0) {
7873
+ nextTarget = "PICK_TICKET";
7874
+ } else {
7875
+ nextTarget = "HANDOVER";
7876
+ }
7856
7877
  }
7857
7878
  if (nextTarget === "HANDOVER") {
7858
7879
  const postComplete = ctx.state.resolvedPostComplete ?? ctx.recipe.postComplete;
@@ -10564,6 +10585,7 @@ function registerAllTools(server, pinnedRoot) {
10564
10585
  report: z10.object({
10565
10586
  completedAction: z10.string().describe("What was completed"),
10566
10587
  ticketId: z10.string().optional().describe("Ticket ID (for ticket_picked)"),
10588
+ issueId: z10.string().optional().describe("Issue ID (for issue_picked) \u2014 T-153"),
10567
10589
  commitHash: z10.string().optional().describe("Git commit hash (for commit_done)"),
10568
10590
  handoverContent: z10.string().optional().describe("Handover markdown content"),
10569
10591
  verdict: z10.string().optional().describe("Review verdict: approve|revise|request_changes|reject"),
@@ -10849,7 +10871,7 @@ var init_mcp = __esm({
10849
10871
  init_init();
10850
10872
  ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
10851
10873
  CONFIG_PATH2 = ".story/config.json";
10852
- version = "0.1.38";
10874
+ version = "0.1.39";
10853
10875
  main().catch((err) => {
10854
10876
  process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}
10855
10877
  `);
@@ -14273,7 +14295,7 @@ async function runCli() {
14273
14295
  registerSessionCommand: registerSessionCommand2,
14274
14296
  registerRepairCommand: registerRepairCommand2
14275
14297
  } = await Promise.resolve().then(() => (init_register(), register_exports));
14276
- const version2 = "0.1.38";
14298
+ const version2 = "0.1.39";
14277
14299
  class HandledError extends Error {
14278
14300
  constructor() {
14279
14301
  super("HANDLED_ERROR");
package/dist/index.d.ts CHANGED
@@ -1377,15 +1377,42 @@ declare const SnapshotV1Schema: z.ZodObject<{
1377
1377
  file: z.ZodString;
1378
1378
  message: z.ZodString;
1379
1379
  }, "strip", z.ZodTypeAny, {
1380
- message: string;
1381
1380
  type: string;
1381
+ message: string;
1382
1382
  file: string;
1383
1383
  }, {
1384
- message: string;
1385
1384
  type: string;
1385
+ message: string;
1386
1386
  file: string;
1387
1387
  }>, "many">>;
1388
1388
  }, "strip", z.ZodTypeAny, {
1389
+ version: 1;
1390
+ config: {
1391
+ version: number;
1392
+ type: string;
1393
+ language: string;
1394
+ project: string;
1395
+ features: {
1396
+ issues: boolean;
1397
+ tickets: boolean;
1398
+ handovers: boolean;
1399
+ roadmap: boolean;
1400
+ reviews: boolean;
1401
+ } & {
1402
+ [k: string]: unknown;
1403
+ };
1404
+ schemaVersion?: number | undefined;
1405
+ recipe?: string | undefined;
1406
+ recipeOverrides?: {
1407
+ maxTicketsPerSession?: number | undefined;
1408
+ compactThreshold?: string | undefined;
1409
+ reviewBackends?: string[] | undefined;
1410
+ handoverInterval?: number | undefined;
1411
+ stages?: Record<string, Record<string, unknown>> | undefined;
1412
+ } | undefined;
1413
+ } & {
1414
+ [k: string]: unknown;
1415
+ };
1389
1416
  issues: z.objectOutputType<{
1390
1417
  id: z.ZodString;
1391
1418
  title: z.ZodString;
@@ -1422,8 +1449,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1422
1449
  claimedBySession: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1423
1450
  }, z.ZodTypeAny, "passthrough">[];
1424
1451
  roadmap: {
1425
- title: string;
1426
1452
  date: string;
1453
+ title: string;
1427
1454
  phases: z.objectOutputType<{
1428
1455
  id: z.ZodString;
1429
1456
  label: z.ZodString;
@@ -1441,7 +1468,6 @@ declare const SnapshotV1Schema: z.ZodObject<{
1441
1468
  } & {
1442
1469
  [k: string]: unknown;
1443
1470
  };
1444
- version: 1;
1445
1471
  project: string;
1446
1472
  notes: z.objectOutputType<{
1447
1473
  id: z.ZodString;
@@ -1467,11 +1493,19 @@ declare const SnapshotV1Schema: z.ZodObject<{
1467
1493
  status: z.ZodEnum<["active", "deprecated", "superseded"]>;
1468
1494
  }, z.ZodTypeAny, "passthrough">[];
1469
1495
  createdAt: string;
1470
- config: {
1496
+ handoverFilenames: string[];
1497
+ warnings?: {
1471
1498
  type: string;
1499
+ message: string;
1500
+ file: string;
1501
+ }[] | undefined;
1502
+ }, {
1503
+ version: 1;
1504
+ config: {
1472
1505
  version: number;
1473
- project: string;
1506
+ type: string;
1474
1507
  language: string;
1508
+ project: string;
1475
1509
  features: {
1476
1510
  issues: boolean;
1477
1511
  tickets: boolean;
@@ -1493,13 +1527,6 @@ declare const SnapshotV1Schema: z.ZodObject<{
1493
1527
  } & {
1494
1528
  [k: string]: unknown;
1495
1529
  };
1496
- handoverFilenames: string[];
1497
- warnings?: {
1498
- message: string;
1499
- type: string;
1500
- file: string;
1501
- }[] | undefined;
1502
- }, {
1503
1530
  issues: z.objectInputType<{
1504
1531
  id: z.ZodString;
1505
1532
  title: z.ZodString;
@@ -1536,8 +1563,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1536
1563
  claimedBySession: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1537
1564
  }, z.ZodTypeAny, "passthrough">[];
1538
1565
  roadmap: {
1539
- title: string;
1540
1566
  date: string;
1567
+ title: string;
1541
1568
  phases: z.objectInputType<{
1542
1569
  id: z.ZodString;
1543
1570
  label: z.ZodString;
@@ -1555,35 +1582,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1555
1582
  } & {
1556
1583
  [k: string]: unknown;
1557
1584
  };
1558
- version: 1;
1559
1585
  project: string;
1560
1586
  createdAt: string;
1561
- config: {
1562
- type: string;
1563
- version: number;
1564
- project: string;
1565
- language: string;
1566
- features: {
1567
- issues: boolean;
1568
- tickets: boolean;
1569
- handovers: boolean;
1570
- roadmap: boolean;
1571
- reviews: boolean;
1572
- } & {
1573
- [k: string]: unknown;
1574
- };
1575
- schemaVersion?: number | undefined;
1576
- recipe?: string | undefined;
1577
- recipeOverrides?: {
1578
- maxTicketsPerSession?: number | undefined;
1579
- compactThreshold?: string | undefined;
1580
- reviewBackends?: string[] | undefined;
1581
- handoverInterval?: number | undefined;
1582
- stages?: Record<string, Record<string, unknown>> | undefined;
1583
- } | undefined;
1584
- } & {
1585
- [k: string]: unknown;
1586
- };
1587
1587
  notes?: z.objectInputType<{
1588
1588
  id: z.ZodString;
1589
1589
  title: z.ZodNullable<z.ZodString>;
@@ -1608,8 +1608,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1608
1608
  status: z.ZodEnum<["active", "deprecated", "superseded"]>;
1609
1609
  }, z.ZodTypeAny, "passthrough">[] | undefined;
1610
1610
  warnings?: {
1611
- message: string;
1612
1611
  type: string;
1612
+ message: string;
1613
1613
  file: string;
1614
1614
  }[] | undefined;
1615
1615
  handoverFilenames?: string[] | undefined;
package/dist/mcp.js CHANGED
@@ -5457,10 +5457,10 @@ var TRANSITIONS = {
5457
5457
  PLAN: ["PLAN_REVIEW"],
5458
5458
  PLAN_REVIEW: ["IMPLEMENT", "WRITE_TESTS", "PLAN", "PLAN_REVIEW", "SESSION_END"],
5459
5459
  // approve → IMPLEMENT/WRITE_TESTS, reject → PLAN, stay for next round; SESSION_END for tiered exit
5460
- IMPLEMENT: ["CODE_REVIEW", "TEST"],
5461
- // TEST when test stage enabled
5462
- WRITE_TESTS: ["IMPLEMENT", "WRITE_TESTS", "PLAN"],
5463
- // advance → IMPLEMENT, retry stays, exhaustion → PLAN
5460
+ IMPLEMENT: ["CODE_REVIEW", "TEST", "COMPLETE"],
5461
+ // TEST when test stage enabled, COMPLETE for no-op tickets (ISS-069)
5462
+ WRITE_TESTS: ["IMPLEMENT", "WRITE_TESTS", "PLAN", "COMPLETE"],
5463
+ // advance → IMPLEMENT, retry stays, exhaustion → PLAN, no-op → COMPLETE (ISS-069)
5464
5464
  TEST: ["CODE_REVIEW", "IMPLEMENT", "TEST"],
5465
5465
  // pass → CODE_REVIEW, fail → IMPLEMENT, retry
5466
5466
  CODE_REVIEW: ["VERIFY", "FINALIZE", "IMPLEMENT", "PLAN", "CODE_REVIEW", "SESSION_END"],
@@ -6397,6 +6397,10 @@ var ImplementStage = class {
6397
6397
  };
6398
6398
  }
6399
6399
  async report(ctx, _report) {
6400
+ if (_report.completedAction === "no_implementation_needed") {
6401
+ ctx.appendEvent("implement", { result: "skipped", reason: "no_changes_needed" });
6402
+ return { action: "goto", target: "COMPLETE" };
6403
+ }
6400
6404
  let realizedRisk = ctx.state.ticket?.risk ?? "low";
6401
6405
  const mergeBase = ctx.state.git.mergeBase;
6402
6406
  if (mergeBase) {
@@ -6446,7 +6450,12 @@ var WriteTestsStage = class {
6446
6450
  `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "write_tests_done", "notes": "exit code: <N>, X passed, Y failed" } }`,
6447
6451
  "```",
6448
6452
  "",
6449
- "Include the exit code and pass/fail counts in your notes."
6453
+ "Include the exit code and pass/fail counts in your notes.",
6454
+ "",
6455
+ "**If your approved plan requires no code changes** (e.g., the bug is already fixed), update the ticket status to complete in .story/ and report:",
6456
+ "```json",
6457
+ `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "no_tests_needed", "notes": "No code changes needed \u2014 ticket resolved without implementation." } }`,
6458
+ "```"
6450
6459
  ].join("\n"),
6451
6460
  reminders: [
6452
6461
  "Tests MUST fail \u2014 they define unimplemented behavior.",
@@ -6457,6 +6466,11 @@ var WriteTestsStage = class {
6457
6466
  };
6458
6467
  }
6459
6468
  async report(ctx, report) {
6469
+ if (report.completedAction === "no_tests_needed") {
6470
+ ctx.writeState({ writeTestsRetryCount: 0 });
6471
+ ctx.appendEvent("write_tests", { result: "skipped", reason: "no_changes_needed" });
6472
+ return { action: "goto", target: "COMPLETE" };
6473
+ }
6460
6474
  const notes = report.notes ?? "";
6461
6475
  const retryCount = ctx.state.writeTestsRetryCount ?? 0;
6462
6476
  const exitMatch = notes.match(EXIT_CODE_REGEX);
@@ -7352,7 +7366,14 @@ var CompleteStage = class {
7352
7366
  const { state: projectState } = await ctx.loadProject();
7353
7367
  const nextResult = nextTickets(projectState, 1);
7354
7368
  if (nextResult.kind !== "found") {
7355
- nextTarget = "HANDOVER";
7369
+ const highIssues = projectState.issues.filter(
7370
+ (i) => i.status === "open" && (i.severity === "critical" || i.severity === "high")
7371
+ );
7372
+ if (highIssues.length > 0) {
7373
+ nextTarget = "PICK_TICKET";
7374
+ } else {
7375
+ nextTarget = "HANDOVER";
7376
+ }
7356
7377
  }
7357
7378
  if (nextTarget === "HANDOVER") {
7358
7379
  const postComplete = ctx.state.resolvedPostComplete ?? ctx.recipe.postComplete;
@@ -9857,6 +9878,7 @@ function registerAllTools(server, pinnedRoot) {
9857
9878
  report: z10.object({
9858
9879
  completedAction: z10.string().describe("What was completed"),
9859
9880
  ticketId: z10.string().optional().describe("Ticket ID (for ticket_picked)"),
9881
+ issueId: z10.string().optional().describe("Issue ID (for issue_picked) \u2014 T-153"),
9860
9882
  commitHash: z10.string().optional().describe("Git commit hash (for commit_done)"),
9861
9883
  handoverContent: z10.string().optional().describe("Handover markdown content"),
9862
9884
  verdict: z10.string().optional().describe("Review verdict: approve|revise|request_changes|reject"),
@@ -9985,7 +10007,7 @@ async function ensureGitignoreEntries(gitignorePath, entries) {
9985
10007
  // src/mcp/index.ts
9986
10008
  var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
9987
10009
  var CONFIG_PATH2 = ".story/config.json";
9988
- var version = "0.1.38";
10010
+ var version = "0.1.39";
9989
10011
  function tryDiscoverRoot() {
9990
10012
  const envRoot = process.env[ENV_VAR2];
9991
10013
  if (envRoot) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anthropologies/claudestory",
3
- "version": "0.1.38",
3
+ "version": "0.1.39",
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": [