@anthropologies/claudestory 0.1.12 → 0.1.14

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
@@ -262,7 +262,12 @@ var init_config = __esm({
262
262
  type: z6.string(),
263
263
  language: z6.string(),
264
264
  features: FeaturesSchema,
265
- recipe: z6.string().optional()
265
+ recipe: z6.string().optional(),
266
+ recipeOverrides: z6.object({
267
+ maxTicketsPerSession: z6.number().min(0).optional(),
268
+ compactThreshold: z6.string().optional(),
269
+ reviewBackends: z6.array(z6.string()).optional()
270
+ }).optional()
266
271
  }).passthrough();
267
272
  }
268
273
  });
@@ -4491,9 +4496,9 @@ var init_session_types = __esm({
4491
4496
  supersededBy: z8.string().optional(),
4492
4497
  supersededSession: z8.string().optional(),
4493
4498
  stealReason: z8.string().optional(),
4494
- // Recipe overrides
4499
+ // Recipe overrides (maxTicketsPerSession: 0 = no limit)
4495
4500
  config: z8.object({
4496
- maxTicketsPerSession: z8.number().default(3),
4501
+ maxTicketsPerSession: z8.number().min(0).default(3),
4497
4502
  compactThreshold: z8.string().default("high"),
4498
4503
  reviewBackends: z8.array(z8.string()).default(["codex", "agent"])
4499
4504
  }).default({ maxTicketsPerSession: 3, compactThreshold: "high", reviewBackends: ["codex", "agent"] })
@@ -4527,7 +4532,7 @@ function statePath(dir) {
4527
4532
  function eventsPath(dir) {
4528
4533
  return join6(dir, "events.log");
4529
4534
  }
4530
- function createSession(root, recipe, workspaceId) {
4535
+ function createSession(root, recipe, workspaceId, configOverrides) {
4531
4536
  const id = randomUUID();
4532
4537
  const dir = sessionDir(root, id);
4533
4538
  mkdirSync(dir, { recursive: true });
@@ -4563,9 +4568,9 @@ function createSession(root, recipe, workspaceId) {
4563
4568
  startedAt: now,
4564
4569
  guideCallCount: 0,
4565
4570
  config: {
4566
- maxTicketsPerSession: 3,
4567
- compactThreshold: "high",
4568
- reviewBackends: ["codex", "agent"]
4571
+ maxTicketsPerSession: configOverrides?.maxTicketsPerSession ?? 3,
4572
+ compactThreshold: configOverrides?.compactThreshold ?? "high",
4573
+ reviewBackends: configOverrides?.reviewBackends ?? ["codex", "agent"]
4569
4574
  }
4570
4575
  };
4571
4576
  writeSessionSync(dir, state);
@@ -4973,8 +4978,21 @@ async function handleStart(root, args) {
4973
4978
  writeSessionSync(stale.dir, { ...stale.state, status: "superseded" });
4974
4979
  }
4975
4980
  const wsId = deriveWorkspaceId(root);
4976
- const recipe = "coding";
4977
- const session = createSession(root, recipe, wsId);
4981
+ let recipe = "coding";
4982
+ let sessionConfig = {};
4983
+ try {
4984
+ const { state: projectState } = await loadProject(root);
4985
+ const projectConfig = projectState.config;
4986
+ if (typeof projectConfig.recipe === "string") recipe = projectConfig.recipe;
4987
+ if (projectConfig.recipeOverrides && typeof projectConfig.recipeOverrides === "object") {
4988
+ const overrides = projectConfig.recipeOverrides;
4989
+ if (typeof overrides.maxTicketsPerSession === "number") sessionConfig.maxTicketsPerSession = overrides.maxTicketsPerSession;
4990
+ if (typeof overrides.compactThreshold === "string") sessionConfig.compactThreshold = overrides.compactThreshold;
4991
+ if (Array.isArray(overrides.reviewBackends)) sessionConfig.reviewBackends = overrides.reviewBackends;
4992
+ }
4993
+ } catch {
4994
+ }
4995
+ const session = createSession(root, recipe, wsId, sessionConfig);
4978
4996
  const dir = sessionDir(root, session.sessionId);
4979
4997
  try {
4980
4998
  const headResult = await gitHead(root);
@@ -5101,29 +5119,30 @@ ${strategiesText}` : ""
5101
5119
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5102
5120
  data: { recipe, branch: written.git.branch, head: written.git.initHead }
5103
5121
  });
5122
+ const topCandidate = nextResult.kind === "found" ? nextResult.candidates[0] : null;
5104
5123
  const instruction = [
5105
5124
  "# Autonomous Session Started",
5106
5125
  "",
5107
- "I've loaded your project context and found ticket candidates.",
5126
+ "You are now in autonomous mode. Work continuously until all tickets are done or the session limit is reached.",
5127
+ "Do NOT stop to summarize. Do NOT ask the user. Pick a ticket and start working immediately.",
5108
5128
  "",
5109
5129
  "## Ticket Candidates",
5110
5130
  "",
5111
5131
  candidatesText,
5112
5132
  recsText,
5113
5133
  "",
5114
- "Pick a ticket by calling `claudestory_autonomous_guide` with:",
5134
+ topCandidate ? `Pick **${topCandidate.ticket.id}** (highest priority) by calling \`claudestory_autonomous_guide\` now:` : "Pick a ticket by calling `claudestory_autonomous_guide` now:",
5115
5135
  "```json",
5116
- `{ "sessionId": "${updated.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "T-XXX" } }`,
5117
- "```",
5118
- "",
5119
- "Replace T-XXX with the ticket ID you want to work on."
5136
+ topCandidate ? `{ "sessionId": "${updated.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "${topCandidate.ticket.id}" } }` : `{ "sessionId": "${updated.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "T-XXX" } }`,
5137
+ "```"
5120
5138
  ].join("\n");
5121
5139
  return guideResult(updated, "PICK_TICKET", {
5122
5140
  instruction,
5123
5141
  reminders: [
5124
5142
  "Do NOT use Claude Code's plan mode \u2014 write plans as markdown files.",
5125
5143
  "Do NOT ask the user for confirmation or approval.",
5126
- "Call autonomous_guide after completing each step."
5144
+ "Do NOT stop or summarize between tickets \u2014 call autonomous_guide IMMEDIATELY.",
5145
+ "You are in autonomous mode \u2014 continue working until done."
5127
5146
  ],
5128
5147
  transitionedFrom: "INIT"
5129
5148
  });
@@ -5578,7 +5597,7 @@ async function handleReportComplete(root, dir, state, report) {
5578
5597
  if (pressure === "critical") {
5579
5598
  nextState = "HANDOVER";
5580
5599
  advice = "compact-now";
5581
- } else if (ticketsDone >= maxTickets) {
5600
+ } else if (maxTickets > 0 && ticketsDone >= maxTickets) {
5582
5601
  nextState = "HANDOVER";
5583
5602
  } else if (pressure === "high") {
5584
5603
  advice = "consider-compact";
@@ -5617,15 +5636,25 @@ async function handleReportComplete(root, dir, state, report) {
5617
5636
  (c, i) => `${i + 1}. **${c.ticket.id}: ${c.ticket.title}** (${c.ticket.type})`
5618
5637
  ).join("\n");
5619
5638
  }
5639
+ const topCandidate = candidates.kind === "found" ? candidates.candidates[0] : null;
5620
5640
  return guideResult(transitioned, "PICK_TICKET", {
5621
5641
  instruction: [
5622
- `# Ticket Complete \u2014 Pick Next (${ticketsDone}/${maxTickets})`,
5642
+ `# Ticket Complete \u2014 Continuing (${ticketsDone}/${maxTickets})`,
5643
+ "",
5644
+ "Do NOT stop. Do NOT ask the user. Continue immediately with the next ticket.",
5623
5645
  "",
5624
5646
  candidatesText,
5625
5647
  "",
5626
- 'Pick a ticket by calling me with completedAction: "ticket_picked" and ticketId.'
5648
+ topCandidate ? `Pick **${topCandidate.ticket.id}** (highest priority) by calling \`claudestory_autonomous_guide\` now:` : "Pick a ticket by calling `claudestory_autonomous_guide` now:",
5649
+ "```json",
5650
+ topCandidate ? `{ "sessionId": "${transitioned.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "${topCandidate.ticket.id}" } }` : `{ "sessionId": "${transitioned.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "T-XXX" } }`,
5651
+ "```"
5627
5652
  ].join("\n"),
5628
- reminders: [],
5653
+ reminders: [
5654
+ "Do NOT stop or summarize. Call autonomous_guide IMMEDIATELY to pick the next ticket.",
5655
+ "Do NOT ask the user for confirmation.",
5656
+ "You are in autonomous mode \u2014 continue working until all tickets are done or the session limit is reached."
5657
+ ],
5629
5658
  transitionedFrom: "COMPLETE",
5630
5659
  contextAdvice: advice
5631
5660
  });
@@ -6806,7 +6835,7 @@ var init_mcp = __esm({
6806
6835
  init_init();
6807
6836
  ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
6808
6837
  CONFIG_PATH2 = ".story/config.json";
6809
- version = "0.1.12";
6838
+ version = "0.1.14";
6810
6839
  main().catch((err) => {
6811
6840
  process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}
6812
6841
  `);
@@ -9310,7 +9339,7 @@ async function runCli() {
9310
9339
  registerSetupSkillCommand: registerSetupSkillCommand2,
9311
9340
  registerHookStatusCommand: registerHookStatusCommand2
9312
9341
  } = await Promise.resolve().then(() => (init_register(), register_exports));
9313
- const version2 = "0.1.12";
9342
+ const version2 = "0.1.14";
9314
9343
  class HandledError extends Error {
9315
9344
  constructor() {
9316
9345
  super("HANDLED_ERROR");
package/dist/index.d.ts CHANGED
@@ -341,6 +341,19 @@ declare const ConfigSchema: z.ZodObject<{
341
341
  reviews: z.ZodBoolean;
342
342
  }, z.ZodTypeAny, "passthrough">>;
343
343
  recipe: z.ZodOptional<z.ZodString>;
344
+ recipeOverrides: z.ZodOptional<z.ZodObject<{
345
+ maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
346
+ compactThreshold: z.ZodOptional<z.ZodString>;
347
+ reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
348
+ }, "strip", z.ZodTypeAny, {
349
+ maxTicketsPerSession?: number | undefined;
350
+ compactThreshold?: string | undefined;
351
+ reviewBackends?: string[] | undefined;
352
+ }, {
353
+ maxTicketsPerSession?: number | undefined;
354
+ compactThreshold?: string | undefined;
355
+ reviewBackends?: string[] | undefined;
356
+ }>>;
344
357
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
345
358
  version: z.ZodNumber;
346
359
  schemaVersion: z.ZodOptional<z.ZodNumber>;
@@ -367,6 +380,19 @@ declare const ConfigSchema: z.ZodObject<{
367
380
  reviews: z.ZodBoolean;
368
381
  }, z.ZodTypeAny, "passthrough">>;
369
382
  recipe: z.ZodOptional<z.ZodString>;
383
+ recipeOverrides: z.ZodOptional<z.ZodObject<{
384
+ maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
385
+ compactThreshold: z.ZodOptional<z.ZodString>;
386
+ reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
387
+ }, "strip", z.ZodTypeAny, {
388
+ maxTicketsPerSession?: number | undefined;
389
+ compactThreshold?: string | undefined;
390
+ reviewBackends?: string[] | undefined;
391
+ }, {
392
+ maxTicketsPerSession?: number | undefined;
393
+ compactThreshold?: string | undefined;
394
+ reviewBackends?: string[] | undefined;
395
+ }>>;
370
396
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
371
397
  version: z.ZodNumber;
372
398
  schemaVersion: z.ZodOptional<z.ZodNumber>;
@@ -393,6 +419,19 @@ declare const ConfigSchema: z.ZodObject<{
393
419
  reviews: z.ZodBoolean;
394
420
  }, z.ZodTypeAny, "passthrough">>;
395
421
  recipe: z.ZodOptional<z.ZodString>;
422
+ recipeOverrides: z.ZodOptional<z.ZodObject<{
423
+ maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
424
+ compactThreshold: z.ZodOptional<z.ZodString>;
425
+ reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
426
+ }, "strip", z.ZodTypeAny, {
427
+ maxTicketsPerSession?: number | undefined;
428
+ compactThreshold?: string | undefined;
429
+ reviewBackends?: string[] | undefined;
430
+ }, {
431
+ maxTicketsPerSession?: number | undefined;
432
+ compactThreshold?: string | undefined;
433
+ reviewBackends?: string[] | undefined;
434
+ }>>;
396
435
  }, z.ZodTypeAny, "passthrough">>;
397
436
  type Config = z.infer<typeof ConfigSchema>;
398
437
 
@@ -853,6 +892,19 @@ declare const SnapshotV1Schema: z.ZodObject<{
853
892
  reviews: z.ZodBoolean;
854
893
  }, z.ZodTypeAny, "passthrough">>;
855
894
  recipe: z.ZodOptional<z.ZodString>;
895
+ recipeOverrides: z.ZodOptional<z.ZodObject<{
896
+ maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
897
+ compactThreshold: z.ZodOptional<z.ZodString>;
898
+ reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
899
+ }, "strip", z.ZodTypeAny, {
900
+ maxTicketsPerSession?: number | undefined;
901
+ compactThreshold?: string | undefined;
902
+ reviewBackends?: string[] | undefined;
903
+ }, {
904
+ maxTicketsPerSession?: number | undefined;
905
+ compactThreshold?: string | undefined;
906
+ reviewBackends?: string[] | undefined;
907
+ }>>;
856
908
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
857
909
  version: z.ZodNumber;
858
910
  schemaVersion: z.ZodOptional<z.ZodNumber>;
@@ -879,6 +931,19 @@ declare const SnapshotV1Schema: z.ZodObject<{
879
931
  reviews: z.ZodBoolean;
880
932
  }, z.ZodTypeAny, "passthrough">>;
881
933
  recipe: z.ZodOptional<z.ZodString>;
934
+ recipeOverrides: z.ZodOptional<z.ZodObject<{
935
+ maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
936
+ compactThreshold: z.ZodOptional<z.ZodString>;
937
+ reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
938
+ }, "strip", z.ZodTypeAny, {
939
+ maxTicketsPerSession?: number | undefined;
940
+ compactThreshold?: string | undefined;
941
+ reviewBackends?: string[] | undefined;
942
+ }, {
943
+ maxTicketsPerSession?: number | undefined;
944
+ compactThreshold?: string | undefined;
945
+ reviewBackends?: string[] | undefined;
946
+ }>>;
882
947
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
883
948
  version: z.ZodNumber;
884
949
  schemaVersion: z.ZodOptional<z.ZodNumber>;
@@ -905,6 +970,19 @@ declare const SnapshotV1Schema: z.ZodObject<{
905
970
  reviews: z.ZodBoolean;
906
971
  }, z.ZodTypeAny, "passthrough">>;
907
972
  recipe: z.ZodOptional<z.ZodString>;
973
+ recipeOverrides: z.ZodOptional<z.ZodObject<{
974
+ maxTicketsPerSession: z.ZodOptional<z.ZodNumber>;
975
+ compactThreshold: z.ZodOptional<z.ZodString>;
976
+ reviewBackends: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
977
+ }, "strip", z.ZodTypeAny, {
978
+ maxTicketsPerSession?: number | undefined;
979
+ compactThreshold?: string | undefined;
980
+ reviewBackends?: string[] | undefined;
981
+ }, {
982
+ maxTicketsPerSession?: number | undefined;
983
+ compactThreshold?: string | undefined;
984
+ reviewBackends?: string[] | undefined;
985
+ }>>;
908
986
  }, z.ZodTypeAny, "passthrough">>;
909
987
  roadmap: z.ZodObject<{
910
988
  title: z.ZodString;
@@ -1159,35 +1237,15 @@ declare const SnapshotV1Schema: z.ZodObject<{
1159
1237
  file: z.ZodString;
1160
1238
  message: z.ZodString;
1161
1239
  }, "strip", z.ZodTypeAny, {
1162
- type: string;
1163
1240
  message: string;
1241
+ type: string;
1164
1242
  file: string;
1165
1243
  }, {
1166
- type: string;
1167
1244
  message: string;
1245
+ type: string;
1168
1246
  file: string;
1169
1247
  }>, "many">>;
1170
1248
  }, "strip", z.ZodTypeAny, {
1171
- version: 1;
1172
- config: {
1173
- version: number;
1174
- type: string;
1175
- language: string;
1176
- project: string;
1177
- features: {
1178
- issues: boolean;
1179
- tickets: boolean;
1180
- handovers: boolean;
1181
- roadmap: boolean;
1182
- reviews: boolean;
1183
- } & {
1184
- [k: string]: unknown;
1185
- };
1186
- schemaVersion?: number | undefined;
1187
- recipe?: string | undefined;
1188
- } & {
1189
- [k: string]: unknown;
1190
- };
1191
1249
  issues: z.objectOutputType<{
1192
1250
  id: z.ZodString;
1193
1251
  title: z.ZodString;
@@ -1223,8 +1281,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1223
1281
  lastModifiedBy: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1224
1282
  }, z.ZodTypeAny, "passthrough">[];
1225
1283
  roadmap: {
1226
- date: string;
1227
1284
  title: string;
1285
+ date: string;
1228
1286
  phases: z.objectOutputType<{
1229
1287
  id: z.ZodString;
1230
1288
  label: z.ZodString;
@@ -1242,6 +1300,7 @@ declare const SnapshotV1Schema: z.ZodObject<{
1242
1300
  } & {
1243
1301
  [k: string]: unknown;
1244
1302
  };
1303
+ version: 1;
1245
1304
  project: string;
1246
1305
  notes: z.objectOutputType<{
1247
1306
  id: z.ZodString;
@@ -1253,19 +1312,11 @@ declare const SnapshotV1Schema: z.ZodObject<{
1253
1312
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
1254
1313
  }, z.ZodTypeAny, "passthrough">[];
1255
1314
  createdAt: string;
1256
- handoverFilenames: string[];
1257
- warnings?: {
1258
- type: string;
1259
- message: string;
1260
- file: string;
1261
- }[] | undefined;
1262
- }, {
1263
- version: 1;
1264
1315
  config: {
1265
- version: number;
1266
1316
  type: string;
1267
- language: string;
1317
+ version: number;
1268
1318
  project: string;
1319
+ language: string;
1269
1320
  features: {
1270
1321
  issues: boolean;
1271
1322
  tickets: boolean;
@@ -1277,9 +1328,21 @@ declare const SnapshotV1Schema: z.ZodObject<{
1277
1328
  };
1278
1329
  schemaVersion?: number | undefined;
1279
1330
  recipe?: string | undefined;
1331
+ recipeOverrides?: {
1332
+ maxTicketsPerSession?: number | undefined;
1333
+ compactThreshold?: string | undefined;
1334
+ reviewBackends?: string[] | undefined;
1335
+ } | undefined;
1280
1336
  } & {
1281
1337
  [k: string]: unknown;
1282
1338
  };
1339
+ handoverFilenames: string[];
1340
+ warnings?: {
1341
+ message: string;
1342
+ type: string;
1343
+ file: string;
1344
+ }[] | undefined;
1345
+ }, {
1283
1346
  issues: z.objectInputType<{
1284
1347
  id: z.ZodString;
1285
1348
  title: z.ZodString;
@@ -1315,8 +1378,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1315
1378
  lastModifiedBy: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1316
1379
  }, z.ZodTypeAny, "passthrough">[];
1317
1380
  roadmap: {
1318
- date: string;
1319
1381
  title: string;
1382
+ date: string;
1320
1383
  phases: z.objectInputType<{
1321
1384
  id: z.ZodString;
1322
1385
  label: z.ZodString;
@@ -1334,8 +1397,33 @@ declare const SnapshotV1Schema: z.ZodObject<{
1334
1397
  } & {
1335
1398
  [k: string]: unknown;
1336
1399
  };
1400
+ version: 1;
1337
1401
  project: string;
1338
1402
  createdAt: string;
1403
+ config: {
1404
+ type: string;
1405
+ version: number;
1406
+ project: string;
1407
+ language: string;
1408
+ features: {
1409
+ issues: boolean;
1410
+ tickets: boolean;
1411
+ handovers: boolean;
1412
+ roadmap: boolean;
1413
+ reviews: boolean;
1414
+ } & {
1415
+ [k: string]: unknown;
1416
+ };
1417
+ schemaVersion?: number | undefined;
1418
+ recipe?: string | undefined;
1419
+ recipeOverrides?: {
1420
+ maxTicketsPerSession?: number | undefined;
1421
+ compactThreshold?: string | undefined;
1422
+ reviewBackends?: string[] | undefined;
1423
+ } | undefined;
1424
+ } & {
1425
+ [k: string]: unknown;
1426
+ };
1339
1427
  notes?: z.objectInputType<{
1340
1428
  id: z.ZodString;
1341
1429
  title: z.ZodNullable<z.ZodString>;
@@ -1346,8 +1434,8 @@ declare const SnapshotV1Schema: z.ZodObject<{
1346
1434
  updatedDate: z.ZodEffects<z.ZodString, string, string>;
1347
1435
  }, z.ZodTypeAny, "passthrough">[] | undefined;
1348
1436
  warnings?: {
1349
- type: string;
1350
1437
  message: string;
1438
+ type: string;
1351
1439
  file: string;
1352
1440
  }[] | undefined;
1353
1441
  handoverFilenames?: string[] | undefined;
package/dist/index.js CHANGED
@@ -129,7 +129,12 @@ var ConfigSchema = z6.object({
129
129
  type: z6.string(),
130
130
  language: z6.string(),
131
131
  features: FeaturesSchema,
132
- recipe: z6.string().optional()
132
+ recipe: z6.string().optional(),
133
+ recipeOverrides: z6.object({
134
+ maxTicketsPerSession: z6.number().min(0).optional(),
135
+ compactThreshold: z6.string().optional(),
136
+ reviewBackends: z6.array(z6.string()).optional()
137
+ }).optional()
133
138
  }).passthrough();
134
139
 
135
140
  // src/core/project-state.ts
package/dist/mcp.js CHANGED
@@ -204,7 +204,12 @@ var init_config = __esm({
204
204
  type: z6.string(),
205
205
  language: z6.string(),
206
206
  features: FeaturesSchema,
207
- recipe: z6.string().optional()
207
+ recipe: z6.string().optional(),
208
+ recipeOverrides: z6.object({
209
+ maxTicketsPerSession: z6.number().min(0).optional(),
210
+ compactThreshold: z6.string().optional(),
211
+ reviewBackends: z6.array(z6.string()).optional()
212
+ }).optional()
208
213
  }).passthrough();
209
214
  }
210
215
  });
@@ -4025,9 +4030,9 @@ var SessionStateSchema = z8.object({
4025
4030
  supersededBy: z8.string().optional(),
4026
4031
  supersededSession: z8.string().optional(),
4027
4032
  stealReason: z8.string().optional(),
4028
- // Recipe overrides
4033
+ // Recipe overrides (maxTicketsPerSession: 0 = no limit)
4029
4034
  config: z8.object({
4030
- maxTicketsPerSession: z8.number().default(3),
4035
+ maxTicketsPerSession: z8.number().min(0).default(3),
4031
4036
  compactThreshold: z8.string().default("high"),
4032
4037
  reviewBackends: z8.array(z8.string()).default(["codex", "agent"])
4033
4038
  }).default({ maxTicketsPerSession: 3, compactThreshold: "high", reviewBackends: ["codex", "agent"] })
@@ -4062,7 +4067,7 @@ function statePath(dir) {
4062
4067
  function eventsPath(dir) {
4063
4068
  return join6(dir, "events.log");
4064
4069
  }
4065
- function createSession(root, recipe, workspaceId) {
4070
+ function createSession(root, recipe, workspaceId, configOverrides) {
4066
4071
  const id = randomUUID();
4067
4072
  const dir = sessionDir(root, id);
4068
4073
  mkdirSync(dir, { recursive: true });
@@ -4098,9 +4103,9 @@ function createSession(root, recipe, workspaceId) {
4098
4103
  startedAt: now,
4099
4104
  guideCallCount: 0,
4100
4105
  config: {
4101
- maxTicketsPerSession: 3,
4102
- compactThreshold: "high",
4103
- reviewBackends: ["codex", "agent"]
4106
+ maxTicketsPerSession: configOverrides?.maxTicketsPerSession ?? 3,
4107
+ compactThreshold: configOverrides?.compactThreshold ?? "high",
4108
+ reviewBackends: configOverrides?.reviewBackends ?? ["codex", "agent"]
4104
4109
  }
4105
4110
  };
4106
4111
  writeSessionSync(dir, state);
@@ -4475,8 +4480,21 @@ async function handleStart(root, args) {
4475
4480
  writeSessionSync(stale.dir, { ...stale.state, status: "superseded" });
4476
4481
  }
4477
4482
  const wsId = deriveWorkspaceId(root);
4478
- const recipe = "coding";
4479
- const session = createSession(root, recipe, wsId);
4483
+ let recipe = "coding";
4484
+ let sessionConfig = {};
4485
+ try {
4486
+ const { state: projectState } = await loadProject(root);
4487
+ const projectConfig = projectState.config;
4488
+ if (typeof projectConfig.recipe === "string") recipe = projectConfig.recipe;
4489
+ if (projectConfig.recipeOverrides && typeof projectConfig.recipeOverrides === "object") {
4490
+ const overrides = projectConfig.recipeOverrides;
4491
+ if (typeof overrides.maxTicketsPerSession === "number") sessionConfig.maxTicketsPerSession = overrides.maxTicketsPerSession;
4492
+ if (typeof overrides.compactThreshold === "string") sessionConfig.compactThreshold = overrides.compactThreshold;
4493
+ if (Array.isArray(overrides.reviewBackends)) sessionConfig.reviewBackends = overrides.reviewBackends;
4494
+ }
4495
+ } catch {
4496
+ }
4497
+ const session = createSession(root, recipe, wsId, sessionConfig);
4480
4498
  const dir = sessionDir(root, session.sessionId);
4481
4499
  try {
4482
4500
  const headResult = await gitHead(root);
@@ -4603,29 +4621,30 @@ ${strategiesText}` : ""
4603
4621
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4604
4622
  data: { recipe, branch: written.git.branch, head: written.git.initHead }
4605
4623
  });
4624
+ const topCandidate = nextResult.kind === "found" ? nextResult.candidates[0] : null;
4606
4625
  const instruction = [
4607
4626
  "# Autonomous Session Started",
4608
4627
  "",
4609
- "I've loaded your project context and found ticket candidates.",
4628
+ "You are now in autonomous mode. Work continuously until all tickets are done or the session limit is reached.",
4629
+ "Do NOT stop to summarize. Do NOT ask the user. Pick a ticket and start working immediately.",
4610
4630
  "",
4611
4631
  "## Ticket Candidates",
4612
4632
  "",
4613
4633
  candidatesText,
4614
4634
  recsText,
4615
4635
  "",
4616
- "Pick a ticket by calling `claudestory_autonomous_guide` with:",
4636
+ topCandidate ? `Pick **${topCandidate.ticket.id}** (highest priority) by calling \`claudestory_autonomous_guide\` now:` : "Pick a ticket by calling `claudestory_autonomous_guide` now:",
4617
4637
  "```json",
4618
- `{ "sessionId": "${updated.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "T-XXX" } }`,
4619
- "```",
4620
- "",
4621
- "Replace T-XXX with the ticket ID you want to work on."
4638
+ topCandidate ? `{ "sessionId": "${updated.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "${topCandidate.ticket.id}" } }` : `{ "sessionId": "${updated.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "T-XXX" } }`,
4639
+ "```"
4622
4640
  ].join("\n");
4623
4641
  return guideResult(updated, "PICK_TICKET", {
4624
4642
  instruction,
4625
4643
  reminders: [
4626
4644
  "Do NOT use Claude Code's plan mode \u2014 write plans as markdown files.",
4627
4645
  "Do NOT ask the user for confirmation or approval.",
4628
- "Call autonomous_guide after completing each step."
4646
+ "Do NOT stop or summarize between tickets \u2014 call autonomous_guide IMMEDIATELY.",
4647
+ "You are in autonomous mode \u2014 continue working until done."
4629
4648
  ],
4630
4649
  transitionedFrom: "INIT"
4631
4650
  });
@@ -5080,7 +5099,7 @@ async function handleReportComplete(root, dir, state, report) {
5080
5099
  if (pressure === "critical") {
5081
5100
  nextState = "HANDOVER";
5082
5101
  advice = "compact-now";
5083
- } else if (ticketsDone >= maxTickets) {
5102
+ } else if (maxTickets > 0 && ticketsDone >= maxTickets) {
5084
5103
  nextState = "HANDOVER";
5085
5104
  } else if (pressure === "high") {
5086
5105
  advice = "consider-compact";
@@ -5119,15 +5138,25 @@ async function handleReportComplete(root, dir, state, report) {
5119
5138
  (c, i) => `${i + 1}. **${c.ticket.id}: ${c.ticket.title}** (${c.ticket.type})`
5120
5139
  ).join("\n");
5121
5140
  }
5141
+ const topCandidate = candidates.kind === "found" ? candidates.candidates[0] : null;
5122
5142
  return guideResult(transitioned, "PICK_TICKET", {
5123
5143
  instruction: [
5124
- `# Ticket Complete \u2014 Pick Next (${ticketsDone}/${maxTickets})`,
5144
+ `# Ticket Complete \u2014 Continuing (${ticketsDone}/${maxTickets})`,
5145
+ "",
5146
+ "Do NOT stop. Do NOT ask the user. Continue immediately with the next ticket.",
5125
5147
  "",
5126
5148
  candidatesText,
5127
5149
  "",
5128
- 'Pick a ticket by calling me with completedAction: "ticket_picked" and ticketId.'
5150
+ topCandidate ? `Pick **${topCandidate.ticket.id}** (highest priority) by calling \`claudestory_autonomous_guide\` now:` : "Pick a ticket by calling `claudestory_autonomous_guide` now:",
5151
+ "```json",
5152
+ topCandidate ? `{ "sessionId": "${transitioned.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "${topCandidate.ticket.id}" } }` : `{ "sessionId": "${transitioned.sessionId}", "action": "report", "report": { "completedAction": "ticket_picked", "ticketId": "T-XXX" } }`,
5153
+ "```"
5129
5154
  ].join("\n"),
5130
- reminders: [],
5155
+ reminders: [
5156
+ "Do NOT stop or summarize. Call autonomous_guide IMMEDIATELY to pick the next ticket.",
5157
+ "Do NOT ask the user for confirmation.",
5158
+ "You are in autonomous mode \u2014 continue working until all tickets are done or the session limit is reached."
5159
+ ],
5131
5160
  transitionedFrom: "COMPLETE",
5132
5161
  contextAdvice: advice
5133
5162
  });
@@ -6005,7 +6034,7 @@ async function ensureGitignoreEntries(gitignorePath, entries) {
6005
6034
  // src/mcp/index.ts
6006
6035
  var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
6007
6036
  var CONFIG_PATH2 = ".story/config.json";
6008
- var version = "0.1.12";
6037
+ var version = "0.1.14";
6009
6038
  function tryDiscoverRoot() {
6010
6039
  const envRoot = process.env[ENV_VAR2];
6011
6040
  if (envRoot) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anthropologies/claudestory",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
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": [