@anthropologies/claudestory 0.1.26 → 0.1.28

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 +119 -3
  2. package/dist/mcp.js +110 -2
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -5002,6 +5002,7 @@ var init_session_types = __esm({
5002
5002
  "VERIFY",
5003
5003
  "FINALIZE",
5004
5004
  "COMPACT",
5005
+ "LESSON_CAPTURE",
5005
5006
  "ISSUE_SWEEP"
5006
5007
  ]);
5007
5008
  IDLE_STATES = /* @__PURE__ */ new Set([
@@ -5028,6 +5029,7 @@ var init_session_types = __esm({
5028
5029
  "COMPACT",
5029
5030
  "HANDOVER",
5030
5031
  "COMPLETE",
5032
+ "LESSON_CAPTURE",
5031
5033
  "ISSUE_SWEEP",
5032
5034
  "SESSION_END"
5033
5035
  ];
@@ -5594,6 +5596,8 @@ var init_state_machine = __esm({
5594
5596
  // pass → FINALIZE, fail → IMPLEMENT, retry
5595
5597
  FINALIZE: ["COMPLETE"],
5596
5598
  COMPLETE: ["PICK_TICKET", "HANDOVER", "ISSUE_SWEEP", "SESSION_END"],
5599
+ LESSON_CAPTURE: ["ISSUE_SWEEP", "HANDOVER", "LESSON_CAPTURE"],
5600
+ // advance → ISSUE_SWEEP, retry self, done → HANDOVER
5597
5601
  ISSUE_SWEEP: ["ISSUE_SWEEP", "HANDOVER", "PICK_TICKET"],
5598
5602
  // retry (next issue), done → HANDOVER, loop → PICK_TICKET
5599
5603
  HANDOVER: ["COMPACT", "SESSION_END", "PICK_TICKET"],
@@ -5967,6 +5971,18 @@ function findFirstPostComplete(postComplete, ctx) {
5967
5971
  }
5968
5972
  return { kind: "exhausted" };
5969
5973
  }
5974
+ function findNextPostComplete(postComplete, currentId, ctx) {
5975
+ const currentIndex = postComplete.indexOf(currentId);
5976
+ const startIndex = currentIndex >= 0 ? currentIndex + 1 : 0;
5977
+ for (let i = startIndex; i < postComplete.length; i++) {
5978
+ const id = postComplete[i];
5979
+ const stage = stages.get(id);
5980
+ if (!stage) return { kind: "unregistered", id };
5981
+ if (stage.skip?.(ctx)) continue;
5982
+ return { kind: "found", stage };
5983
+ }
5984
+ return { kind: "exhausted" };
5985
+ }
5970
5986
  var stages;
5971
5987
  var init_registry = __esm({
5972
5988
  "src/autonomous/stages/registry.ts"() {
@@ -7403,6 +7419,74 @@ var init_complete = __esm({
7403
7419
  }
7404
7420
  });
7405
7421
 
7422
+ // src/autonomous/stages/lesson-capture.ts
7423
+ var LessonCaptureStage;
7424
+ var init_lesson_capture = __esm({
7425
+ "src/autonomous/stages/lesson-capture.ts"() {
7426
+ "use strict";
7427
+ init_esm_shims();
7428
+ LessonCaptureStage = class {
7429
+ id = "LESSON_CAPTURE";
7430
+ skip(ctx) {
7431
+ const config = ctx.recipe.stages?.LESSON_CAPTURE;
7432
+ return !config?.enabled;
7433
+ }
7434
+ async enter(ctx) {
7435
+ const planReviews = ctx.state.reviews.plan ?? [];
7436
+ const codeReviews = ctx.state.reviews.code ?? [];
7437
+ const ticketsDone = ctx.state.completedTickets.length;
7438
+ const planFindings = planReviews.reduce((sum, r) => sum + (r.findingCount ?? 0), 0);
7439
+ const planCritical = planReviews.reduce((sum, r) => sum + (r.criticalCount ?? 0), 0);
7440
+ const planMajor = planReviews.reduce((sum, r) => sum + (r.majorCount ?? 0), 0);
7441
+ const codeFindings = codeReviews.reduce((sum, r) => sum + (r.findingCount ?? 0), 0);
7442
+ const codeCritical = codeReviews.reduce((sum, r) => sum + (r.criticalCount ?? 0), 0);
7443
+ const codeMajor = codeReviews.reduce((sum, r) => sum + (r.majorCount ?? 0), 0);
7444
+ const totalFindings = planFindings + codeFindings;
7445
+ if (totalFindings === 0) {
7446
+ ctx.appendEvent("lesson_capture", { result: "no_findings", ticketsDone });
7447
+ return { action: "advance" };
7448
+ }
7449
+ ctx.appendEvent("lesson_capture", {
7450
+ result: "started",
7451
+ ticketsDone,
7452
+ planFindings,
7453
+ codeFindings
7454
+ });
7455
+ return {
7456
+ instruction: [
7457
+ "# Capture Lessons from Review Findings",
7458
+ "",
7459
+ `This session completed ${ticketsDone} ticket(s). Review summary:`,
7460
+ `- **Plan reviews:** ${planReviews.length} round(s), ${planCritical} critical, ${planMajor} major, ${planFindings} total findings`,
7461
+ `- **Code reviews:** ${codeReviews.length} round(s), ${codeCritical} critical, ${codeMajor} major, ${codeFindings} total findings`,
7462
+ "",
7463
+ "Review these findings for recurring patterns worth capturing as lessons:",
7464
+ "",
7465
+ "1. Call `claudestory_lesson_list` to see existing lessons",
7466
+ "2. For each pattern that recurred or was critical/major:",
7467
+ " - If it matches an existing lesson \u2192 call `claudestory_lesson_reinforce`",
7468
+ ' - If it\'s a new pattern \u2192 call `claudestory_lesson_create` with `source: "review"`',
7469
+ "3. Skip patterns that are one-off or already well-covered",
7470
+ `4. Call \`claudestory_autonomous_guide\` with completedAction: "lessons_captured"`,
7471
+ "",
7472
+ "```json",
7473
+ `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "lessons_captured" } }`,
7474
+ "```"
7475
+ ].join("\n"),
7476
+ reminders: [
7477
+ "Check existing lessons first \u2014 reinforce before creating duplicates.",
7478
+ "Only capture patterns worth remembering across sessions."
7479
+ ]
7480
+ };
7481
+ }
7482
+ async report(ctx, _report) {
7483
+ ctx.appendEvent("lesson_capture", { result: "completed" });
7484
+ return { action: "advance" };
7485
+ }
7486
+ };
7487
+ }
7488
+ });
7489
+
7406
7490
  // src/autonomous/stages/issue-sweep.ts
7407
7491
  var IssueSweepStage;
7408
7492
  var init_issue_sweep = __esm({
@@ -7611,6 +7695,7 @@ var init_stages = __esm({
7611
7695
  init_verify();
7612
7696
  init_finalize();
7613
7697
  init_complete();
7698
+ init_lesson_capture();
7614
7699
  init_issue_sweep();
7615
7700
  init_handover2();
7616
7701
  registerStage(new PickTicketStage());
@@ -7623,6 +7708,7 @@ var init_stages = __esm({
7623
7708
  registerStage(new VerifyStage());
7624
7709
  registerStage(new FinalizeStage());
7625
7710
  registerStage(new CompleteStage());
7711
+ registerStage(new LessonCaptureStage());
7626
7712
  registerStage(new IssueSweepStage());
7627
7713
  registerStage(new HandoverStage());
7628
7714
  }
@@ -8238,7 +8324,8 @@ async function processAdvance(ctx, currentStage, advance, depth = 0) {
8238
8324
  }
8239
8325
  if (next.kind === "exhausted") {
8240
8326
  const postComplete = ctx.state.resolvedPostComplete ?? ctx.recipe.postComplete;
8241
- const post = findFirstPostComplete(postComplete, ctx);
8327
+ const isInPostComplete = postComplete.includes(currentStage.id);
8328
+ const post = isInPostComplete ? findNextPostComplete(postComplete, currentStage.id, ctx) : findFirstPostComplete(postComplete, ctx);
8242
8329
  if (post.kind === "found") {
8243
8330
  assertTransition(currentStage.id, post.stage.id);
8244
8331
  ctx.writeState({ state: post.stage.id, previousState: currentStage.id });
@@ -8384,6 +8471,7 @@ async function handleResume(root, args) {
8384
8471
  // T-128: tests invalidated by HEAD change
8385
8472
  CODE_REVIEW: { state: "PLAN", resetPlan: true, resetCode: true },
8386
8473
  FINALIZE: { state: "IMPLEMENT", resetPlan: false, resetCode: true },
8474
+ LESSON_CAPTURE: { state: "PICK_TICKET", resetPlan: false, resetCode: false },
8387
8475
  ISSUE_SWEEP: { state: "PICK_TICKET", resetPlan: false, resetCode: false }
8388
8476
  // T-128: post-complete, restart sweep
8389
8477
  };
@@ -8538,6 +8626,34 @@ ${driftPreamble}Recovered to state: **${mapping.state}**. Continue from here.`,
8538
8626
  }
8539
8627
  const resumeMode = written.mode ?? "auto";
8540
8628
  const modeContext = resumeMode === "auto" ? "You are in autonomous mode \u2014 continue working." : resumeMode === "review" ? "You are in review mode \u2014 session ends after code review approval." : resumeMode === "plan" ? "You are in plan mode \u2014 session ends after plan review approval." : "You are in guided mode \u2014 single ticket, full pipeline.";
8629
+ const resumeStage = getStage(resumeState);
8630
+ if (resumeStage) {
8631
+ const recipe = resolveRecipeFromState(written);
8632
+ const ctx = new StageContext(root, info.dir, written, recipe);
8633
+ const enterResult = await resumeStage.enter(ctx);
8634
+ if (isStageAdvance(enterResult)) {
8635
+ return processAdvance(ctx, resumeStage, enterResult);
8636
+ }
8637
+ return guideResult(ctx.state, resumeState, {
8638
+ instruction: [
8639
+ "# Resumed After Compact",
8640
+ "",
8641
+ `Session restored at state: **${resumeState}**.`,
8642
+ written.ticket ? `Working on: **${written.ticket.id}: ${written.ticket.title}**` : "",
8643
+ "",
8644
+ modeContext,
8645
+ "",
8646
+ "---",
8647
+ "",
8648
+ enterResult.instruction
8649
+ ].filter(Boolean).join("\n"),
8650
+ reminders: [
8651
+ ...enterResult.reminders ?? [],
8652
+ ...resumeMode === "auto" ? ["Do NOT use plan mode.", "Do NOT stop or summarize."] : [`This is ${resumeMode} mode.`],
8653
+ "Call autonomous_guide after completing each step."
8654
+ ]
8655
+ });
8656
+ }
8541
8657
  return guideResult(written, resumeState, {
8542
8658
  instruction: [
8543
8659
  "# Resumed After Compact",
@@ -10101,7 +10217,7 @@ var init_mcp = __esm({
10101
10217
  init_init();
10102
10218
  ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
10103
10219
  CONFIG_PATH2 = ".story/config.json";
10104
- version = "0.1.26";
10220
+ version = "0.1.28";
10105
10221
  main().catch((err) => {
10106
10222
  process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}
10107
10223
  `);
@@ -13379,7 +13495,7 @@ async function runCli() {
13379
13495
  registerConfigCommand: registerConfigCommand2,
13380
13496
  registerSessionCommand: registerSessionCommand2
13381
13497
  } = await Promise.resolve().then(() => (init_register(), register_exports));
13382
- const version2 = "0.1.26";
13498
+ const version2 = "0.1.28";
13383
13499
  class HandledError extends Error {
13384
13500
  constructor() {
13385
13501
  super("HANDLED_ERROR");
package/dist/mcp.js CHANGED
@@ -3472,6 +3472,7 @@ var init_session_types = __esm({
3472
3472
  "COMPACT",
3473
3473
  "HANDOVER",
3474
3474
  "COMPLETE",
3475
+ "LESSON_CAPTURE",
3475
3476
  "ISSUE_SWEEP",
3476
3477
  "SESSION_END"
3477
3478
  ];
@@ -5200,6 +5201,8 @@ var TRANSITIONS = {
5200
5201
  // pass → FINALIZE, fail → IMPLEMENT, retry
5201
5202
  FINALIZE: ["COMPLETE"],
5202
5203
  COMPLETE: ["PICK_TICKET", "HANDOVER", "ISSUE_SWEEP", "SESSION_END"],
5204
+ LESSON_CAPTURE: ["ISSUE_SWEEP", "HANDOVER", "LESSON_CAPTURE"],
5205
+ // advance → ISSUE_SWEEP, retry self, done → HANDOVER
5203
5206
  ISSUE_SWEEP: ["ISSUE_SWEEP", "HANDOVER", "PICK_TICKET"],
5204
5207
  // retry (next issue), done → HANDOVER, loop → PICK_TICKET
5205
5208
  HANDOVER: ["COMPACT", "SESSION_END", "PICK_TICKET"],
@@ -5559,6 +5562,18 @@ function findFirstPostComplete(postComplete, ctx) {
5559
5562
  }
5560
5563
  return { kind: "exhausted" };
5561
5564
  }
5565
+ function findNextPostComplete(postComplete, currentId, ctx) {
5566
+ const currentIndex = postComplete.indexOf(currentId);
5567
+ const startIndex = currentIndex >= 0 ? currentIndex + 1 : 0;
5568
+ for (let i = startIndex; i < postComplete.length; i++) {
5569
+ const id = postComplete[i];
5570
+ const stage = stages.get(id);
5571
+ if (!stage) return { kind: "unregistered", id };
5572
+ if (stage.skip?.(ctx)) continue;
5573
+ return { kind: "found", stage };
5574
+ }
5575
+ return { kind: "exhausted" };
5576
+ }
5562
5577
 
5563
5578
  // src/autonomous/stages/types.ts
5564
5579
  init_esm_shims();
@@ -6915,6 +6930,68 @@ var CompleteStage = class {
6915
6930
  }
6916
6931
  };
6917
6932
 
6933
+ // src/autonomous/stages/lesson-capture.ts
6934
+ init_esm_shims();
6935
+ var LessonCaptureStage = class {
6936
+ id = "LESSON_CAPTURE";
6937
+ skip(ctx) {
6938
+ const config = ctx.recipe.stages?.LESSON_CAPTURE;
6939
+ return !config?.enabled;
6940
+ }
6941
+ async enter(ctx) {
6942
+ const planReviews = ctx.state.reviews.plan ?? [];
6943
+ const codeReviews = ctx.state.reviews.code ?? [];
6944
+ const ticketsDone = ctx.state.completedTickets.length;
6945
+ const planFindings = planReviews.reduce((sum, r) => sum + (r.findingCount ?? 0), 0);
6946
+ const planCritical = planReviews.reduce((sum, r) => sum + (r.criticalCount ?? 0), 0);
6947
+ const planMajor = planReviews.reduce((sum, r) => sum + (r.majorCount ?? 0), 0);
6948
+ const codeFindings = codeReviews.reduce((sum, r) => sum + (r.findingCount ?? 0), 0);
6949
+ const codeCritical = codeReviews.reduce((sum, r) => sum + (r.criticalCount ?? 0), 0);
6950
+ const codeMajor = codeReviews.reduce((sum, r) => sum + (r.majorCount ?? 0), 0);
6951
+ const totalFindings = planFindings + codeFindings;
6952
+ if (totalFindings === 0) {
6953
+ ctx.appendEvent("lesson_capture", { result: "no_findings", ticketsDone });
6954
+ return { action: "advance" };
6955
+ }
6956
+ ctx.appendEvent("lesson_capture", {
6957
+ result: "started",
6958
+ ticketsDone,
6959
+ planFindings,
6960
+ codeFindings
6961
+ });
6962
+ return {
6963
+ instruction: [
6964
+ "# Capture Lessons from Review Findings",
6965
+ "",
6966
+ `This session completed ${ticketsDone} ticket(s). Review summary:`,
6967
+ `- **Plan reviews:** ${planReviews.length} round(s), ${planCritical} critical, ${planMajor} major, ${planFindings} total findings`,
6968
+ `- **Code reviews:** ${codeReviews.length} round(s), ${codeCritical} critical, ${codeMajor} major, ${codeFindings} total findings`,
6969
+ "",
6970
+ "Review these findings for recurring patterns worth capturing as lessons:",
6971
+ "",
6972
+ "1. Call `claudestory_lesson_list` to see existing lessons",
6973
+ "2. For each pattern that recurred or was critical/major:",
6974
+ " - If it matches an existing lesson \u2192 call `claudestory_lesson_reinforce`",
6975
+ ' - If it\'s a new pattern \u2192 call `claudestory_lesson_create` with `source: "review"`',
6976
+ "3. Skip patterns that are one-off or already well-covered",
6977
+ `4. Call \`claudestory_autonomous_guide\` with completedAction: "lessons_captured"`,
6978
+ "",
6979
+ "```json",
6980
+ `{ "sessionId": "${ctx.state.sessionId}", "action": "report", "report": { "completedAction": "lessons_captured" } }`,
6981
+ "```"
6982
+ ].join("\n"),
6983
+ reminders: [
6984
+ "Check existing lessons first \u2014 reinforce before creating duplicates.",
6985
+ "Only capture patterns worth remembering across sessions."
6986
+ ]
6987
+ };
6988
+ }
6989
+ async report(ctx, _report) {
6990
+ ctx.appendEvent("lesson_capture", { result: "completed" });
6991
+ return { action: "advance" };
6992
+ }
6993
+ };
6994
+
6918
6995
  // src/autonomous/stages/issue-sweep.ts
6919
6996
  init_esm_shims();
6920
6997
  var IssueSweepStage = class {
@@ -7105,6 +7182,7 @@ registerStage(new CodeReviewStage());
7105
7182
  registerStage(new VerifyStage());
7106
7183
  registerStage(new FinalizeStage());
7107
7184
  registerStage(new CompleteStage());
7185
+ registerStage(new LessonCaptureStage());
7108
7186
  registerStage(new IssueSweepStage());
7109
7187
  registerStage(new HandoverStage());
7110
7188
 
@@ -7728,7 +7806,8 @@ async function processAdvance(ctx, currentStage, advance, depth = 0) {
7728
7806
  }
7729
7807
  if (next.kind === "exhausted") {
7730
7808
  const postComplete = ctx.state.resolvedPostComplete ?? ctx.recipe.postComplete;
7731
- const post = findFirstPostComplete(postComplete, ctx);
7809
+ const isInPostComplete = postComplete.includes(currentStage.id);
7810
+ const post = isInPostComplete ? findNextPostComplete(postComplete, currentStage.id, ctx) : findFirstPostComplete(postComplete, ctx);
7732
7811
  if (post.kind === "found") {
7733
7812
  assertTransition(currentStage.id, post.stage.id);
7734
7813
  ctx.writeState({ state: post.stage.id, previousState: currentStage.id });
@@ -7874,6 +7953,7 @@ async function handleResume(root, args) {
7874
7953
  // T-128: tests invalidated by HEAD change
7875
7954
  CODE_REVIEW: { state: "PLAN", resetPlan: true, resetCode: true },
7876
7955
  FINALIZE: { state: "IMPLEMENT", resetPlan: false, resetCode: true },
7956
+ LESSON_CAPTURE: { state: "PICK_TICKET", resetPlan: false, resetCode: false },
7877
7957
  ISSUE_SWEEP: { state: "PICK_TICKET", resetPlan: false, resetCode: false }
7878
7958
  // T-128: post-complete, restart sweep
7879
7959
  };
@@ -8028,6 +8108,34 @@ ${driftPreamble}Recovered to state: **${mapping.state}**. Continue from here.`,
8028
8108
  }
8029
8109
  const resumeMode = written.mode ?? "auto";
8030
8110
  const modeContext = resumeMode === "auto" ? "You are in autonomous mode \u2014 continue working." : resumeMode === "review" ? "You are in review mode \u2014 session ends after code review approval." : resumeMode === "plan" ? "You are in plan mode \u2014 session ends after plan review approval." : "You are in guided mode \u2014 single ticket, full pipeline.";
8111
+ const resumeStage = getStage(resumeState);
8112
+ if (resumeStage) {
8113
+ const recipe = resolveRecipeFromState(written);
8114
+ const ctx = new StageContext(root, info.dir, written, recipe);
8115
+ const enterResult = await resumeStage.enter(ctx);
8116
+ if (isStageAdvance(enterResult)) {
8117
+ return processAdvance(ctx, resumeStage, enterResult);
8118
+ }
8119
+ return guideResult(ctx.state, resumeState, {
8120
+ instruction: [
8121
+ "# Resumed After Compact",
8122
+ "",
8123
+ `Session restored at state: **${resumeState}**.`,
8124
+ written.ticket ? `Working on: **${written.ticket.id}: ${written.ticket.title}**` : "",
8125
+ "",
8126
+ modeContext,
8127
+ "",
8128
+ "---",
8129
+ "",
8130
+ enterResult.instruction
8131
+ ].filter(Boolean).join("\n"),
8132
+ reminders: [
8133
+ ...enterResult.reminders ?? [],
8134
+ ...resumeMode === "auto" ? ["Do NOT use plan mode.", "Do NOT stop or summarize."] : [`This is ${resumeMode} mode.`],
8135
+ "Call autonomous_guide after completing each step."
8136
+ ]
8137
+ });
8138
+ }
8031
8139
  return guideResult(written, resumeState, {
8032
8140
  instruction: [
8033
8141
  "# Resumed After Compact",
@@ -9266,7 +9374,7 @@ async function ensureGitignoreEntries(gitignorePath, entries) {
9266
9374
  // src/mcp/index.ts
9267
9375
  var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
9268
9376
  var CONFIG_PATH2 = ".story/config.json";
9269
- var version = "0.1.26";
9377
+ var version = "0.1.28";
9270
9378
  function tryDiscoverRoot() {
9271
9379
  const envRoot = process.env[ENV_VAR2];
9272
9380
  if (envRoot) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anthropologies/claudestory",
3
- "version": "0.1.26",
3
+ "version": "0.1.28",
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": [