@anthropologies/claudestory 0.1.38 → 0.1.40

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.
Files changed (3) hide show
  1. package/dist/cli.js +35 -8
  2. package/dist/mcp.js +34 -7
  3. package/package.json +1 -1
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"],
@@ -6539,6 +6539,11 @@ ${ticket.description}` : "",
6539
6539
  if (issue.status !== "open") {
6540
6540
  return { action: "retry", instruction: `Issue ${issueId} is ${issue.status}. Pick an open issue.` };
6541
6541
  }
6542
+ try {
6543
+ const { handleIssueUpdate: handleIssueUpdate2 } = await Promise.resolve().then(() => (init_issue2(), issue_exports));
6544
+ await handleIssueUpdate2({ id: issueId, status: "inprogress" }, "json", ctx.root);
6545
+ } catch {
6546
+ }
6542
6547
  ctx.updateDraft({
6543
6548
  currentIssue: { id: issue.id, title: issue.title, severity: issue.severity },
6544
6549
  ticket: void 0,
@@ -6850,6 +6855,10 @@ var init_implement = __esm({
6850
6855
  };
6851
6856
  }
6852
6857
  async report(ctx, _report) {
6858
+ if (_report.completedAction === "no_implementation_needed") {
6859
+ ctx.appendEvent("implement", { result: "skipped", reason: "no_changes_needed" });
6860
+ return { action: "goto", target: "COMPLETE" };
6861
+ }
6853
6862
  let realizedRisk = ctx.state.ticket?.risk ?? "low";
6854
6863
  const mergeBase = ctx.state.git.mergeBase;
6855
6864
  if (mergeBase) {
@@ -6919,7 +6928,12 @@ var init_write_tests = __esm({
6919
6928
  `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "write_tests_done", "notes": "exit code: <N>, X passed, Y failed" } }`,
6920
6929
  "```",
6921
6930
  "",
6922
- "Include the exit code and pass/fail counts in your notes."
6931
+ "Include the exit code and pass/fail counts in your notes.",
6932
+ "",
6933
+ "**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:",
6934
+ "```json",
6935
+ `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "no_tests_needed", "notes": "No code changes needed \u2014 ticket resolved without implementation." } }`,
6936
+ "```"
6923
6937
  ].join("\n"),
6924
6938
  reminders: [
6925
6939
  "Tests MUST fail \u2014 they define unimplemented behavior.",
@@ -6930,6 +6944,11 @@ var init_write_tests = __esm({
6930
6944
  };
6931
6945
  }
6932
6946
  async report(ctx, report) {
6947
+ if (report.completedAction === "no_tests_needed") {
6948
+ ctx.writeState({ writeTestsRetryCount: 0 });
6949
+ ctx.appendEvent("write_tests", { result: "skipped", reason: "no_changes_needed" });
6950
+ return { action: "goto", target: "COMPLETE" };
6951
+ }
6933
6952
  const notes = report.notes ?? "";
6934
6953
  const retryCount = ctx.state.writeTestsRetryCount ?? 0;
6935
6954
  const exitMatch = notes.match(EXIT_CODE_REGEX);
@@ -7852,7 +7871,14 @@ var init_complete = __esm({
7852
7871
  const { state: projectState } = await ctx.loadProject();
7853
7872
  const nextResult = nextTickets(projectState, 1);
7854
7873
  if (nextResult.kind !== "found") {
7855
- nextTarget = "HANDOVER";
7874
+ const highIssues = projectState.issues.filter(
7875
+ (i) => i.status === "open" && (i.severity === "critical" || i.severity === "high")
7876
+ );
7877
+ if (highIssues.length > 0) {
7878
+ nextTarget = "PICK_TICKET";
7879
+ } else {
7880
+ nextTarget = "HANDOVER";
7881
+ }
7856
7882
  }
7857
7883
  if (nextTarget === "HANDOVER") {
7858
7884
  const postComplete = ctx.state.resolvedPostComplete ?? ctx.recipe.postComplete;
@@ -10564,6 +10590,7 @@ function registerAllTools(server, pinnedRoot) {
10564
10590
  report: z10.object({
10565
10591
  completedAction: z10.string().describe("What was completed"),
10566
10592
  ticketId: z10.string().optional().describe("Ticket ID (for ticket_picked)"),
10593
+ issueId: z10.string().optional().describe("Issue ID (for issue_picked) \u2014 T-153"),
10567
10594
  commitHash: z10.string().optional().describe("Git commit hash (for commit_done)"),
10568
10595
  handoverContent: z10.string().optional().describe("Handover markdown content"),
10569
10596
  verdict: z10.string().optional().describe("Review verdict: approve|revise|request_changes|reject"),
@@ -10849,7 +10876,7 @@ var init_mcp = __esm({
10849
10876
  init_init();
10850
10877
  ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
10851
10878
  CONFIG_PATH2 = ".story/config.json";
10852
- version = "0.1.38";
10879
+ version = "0.1.40";
10853
10880
  main().catch((err) => {
10854
10881
  process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}
10855
10882
  `);
@@ -14273,7 +14300,7 @@ async function runCli() {
14273
14300
  registerSessionCommand: registerSessionCommand2,
14274
14301
  registerRepairCommand: registerRepairCommand2
14275
14302
  } = await Promise.resolve().then(() => (init_register(), register_exports));
14276
- const version2 = "0.1.38";
14303
+ const version2 = "0.1.40";
14277
14304
  class HandledError extends Error {
14278
14305
  constructor() {
14279
14306
  super("HANDLED_ERROR");
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"],
@@ -6108,6 +6108,11 @@ ${ticket.description}` : "",
6108
6108
  if (issue.status !== "open") {
6109
6109
  return { action: "retry", instruction: `Issue ${issueId} is ${issue.status}. Pick an open issue.` };
6110
6110
  }
6111
+ try {
6112
+ const { handleIssueUpdate: handleIssueUpdate2 } = await Promise.resolve().then(() => (init_issue2(), issue_exports));
6113
+ await handleIssueUpdate2({ id: issueId, status: "inprogress" }, "json", ctx.root);
6114
+ } catch {
6115
+ }
6111
6116
  ctx.updateDraft({
6112
6117
  currentIssue: { id: issue.id, title: issue.title, severity: issue.severity },
6113
6118
  ticket: void 0,
@@ -6397,6 +6402,10 @@ var ImplementStage = class {
6397
6402
  };
6398
6403
  }
6399
6404
  async report(ctx, _report) {
6405
+ if (_report.completedAction === "no_implementation_needed") {
6406
+ ctx.appendEvent("implement", { result: "skipped", reason: "no_changes_needed" });
6407
+ return { action: "goto", target: "COMPLETE" };
6408
+ }
6400
6409
  let realizedRisk = ctx.state.ticket?.risk ?? "low";
6401
6410
  const mergeBase = ctx.state.git.mergeBase;
6402
6411
  if (mergeBase) {
@@ -6446,7 +6455,12 @@ var WriteTestsStage = class {
6446
6455
  `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "write_tests_done", "notes": "exit code: <N>, X passed, Y failed" } }`,
6447
6456
  "```",
6448
6457
  "",
6449
- "Include the exit code and pass/fail counts in your notes."
6458
+ "Include the exit code and pass/fail counts in your notes.",
6459
+ "",
6460
+ "**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:",
6461
+ "```json",
6462
+ `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "no_tests_needed", "notes": "No code changes needed \u2014 ticket resolved without implementation." } }`,
6463
+ "```"
6450
6464
  ].join("\n"),
6451
6465
  reminders: [
6452
6466
  "Tests MUST fail \u2014 they define unimplemented behavior.",
@@ -6457,6 +6471,11 @@ var WriteTestsStage = class {
6457
6471
  };
6458
6472
  }
6459
6473
  async report(ctx, report) {
6474
+ if (report.completedAction === "no_tests_needed") {
6475
+ ctx.writeState({ writeTestsRetryCount: 0 });
6476
+ ctx.appendEvent("write_tests", { result: "skipped", reason: "no_changes_needed" });
6477
+ return { action: "goto", target: "COMPLETE" };
6478
+ }
6460
6479
  const notes = report.notes ?? "";
6461
6480
  const retryCount = ctx.state.writeTestsRetryCount ?? 0;
6462
6481
  const exitMatch = notes.match(EXIT_CODE_REGEX);
@@ -7352,7 +7371,14 @@ var CompleteStage = class {
7352
7371
  const { state: projectState } = await ctx.loadProject();
7353
7372
  const nextResult = nextTickets(projectState, 1);
7354
7373
  if (nextResult.kind !== "found") {
7355
- nextTarget = "HANDOVER";
7374
+ const highIssues = projectState.issues.filter(
7375
+ (i) => i.status === "open" && (i.severity === "critical" || i.severity === "high")
7376
+ );
7377
+ if (highIssues.length > 0) {
7378
+ nextTarget = "PICK_TICKET";
7379
+ } else {
7380
+ nextTarget = "HANDOVER";
7381
+ }
7356
7382
  }
7357
7383
  if (nextTarget === "HANDOVER") {
7358
7384
  const postComplete = ctx.state.resolvedPostComplete ?? ctx.recipe.postComplete;
@@ -9857,6 +9883,7 @@ function registerAllTools(server, pinnedRoot) {
9857
9883
  report: z10.object({
9858
9884
  completedAction: z10.string().describe("What was completed"),
9859
9885
  ticketId: z10.string().optional().describe("Ticket ID (for ticket_picked)"),
9886
+ issueId: z10.string().optional().describe("Issue ID (for issue_picked) \u2014 T-153"),
9860
9887
  commitHash: z10.string().optional().describe("Git commit hash (for commit_done)"),
9861
9888
  handoverContent: z10.string().optional().describe("Handover markdown content"),
9862
9889
  verdict: z10.string().optional().describe("Review verdict: approve|revise|request_changes|reject"),
@@ -9985,7 +10012,7 @@ async function ensureGitignoreEntries(gitignorePath, entries) {
9985
10012
  // src/mcp/index.ts
9986
10013
  var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
9987
10014
  var CONFIG_PATH2 = ".story/config.json";
9988
- var version = "0.1.38";
10015
+ var version = "0.1.40";
9989
10016
  function tryDiscoverRoot() {
9990
10017
  const envRoot = process.env[ENV_VAR2];
9991
10018
  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.40",
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": [