@anthropologies/claudestory 0.1.1 → 0.1.3

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
@@ -224,9 +224,9 @@ function formatStatus(state, format) {
224
224
  const phases = phasesWithStatus(state);
225
225
  const data = {
226
226
  project: state.config.project,
227
- totalTickets: state.totalTicketCount,
228
- completeTickets: state.completeTicketCount,
229
- openTickets: state.openTicketCount,
227
+ totalTickets: state.leafTicketCount,
228
+ completeTickets: state.completeLeafTicketCount,
229
+ openTickets: state.leafTicketCount - state.completeLeafTicketCount,
230
230
  blockedTickets: state.blockedCount,
231
231
  openIssues: state.openIssueCount,
232
232
  handovers: state.handoverFilenames.length,
@@ -243,7 +243,7 @@ function formatStatus(state, format) {
243
243
  const lines = [
244
244
  `# ${escapeMarkdownInline(state.config.project)}`,
245
245
  "",
246
- `Tickets: ${state.completeTicketCount}/${state.totalTicketCount} complete, ${state.blockedCount} blocked`,
246
+ `Tickets: ${state.completeLeafTicketCount}/${state.leafTicketCount} complete, ${state.blockedCount} blocked`,
247
247
  `Issues: ${state.openIssueCount} open`,
248
248
  `Handovers: ${state.handoverFilenames.length}`,
249
249
  "",
@@ -465,7 +465,11 @@ function formatInitResult(result, format) {
465
465
  if (format === "json") {
466
466
  return JSON.stringify(successEnvelope(result), null, 2);
467
467
  }
468
- return [`Initialized .story/ at ${escapeMarkdownInline(result.root)}`, "", ...result.created.map((f) => ` ${f}`)].join("\n");
468
+ const lines = [`Initialized .story/ at ${escapeMarkdownInline(result.root)}`, "", ...result.created.map((f) => ` ${f}`)];
469
+ if (result.warnings.length > 0) {
470
+ lines.push("", `Warning: ${result.warnings.length} corrupt file(s) found. Run \`claudestory validate\` to inspect.`);
471
+ }
472
+ return lines.join("\n");
469
473
  }
470
474
  function formatHandoverList(filenames, format) {
471
475
  if (format === "json") {
@@ -509,6 +513,8 @@ var ProjectState = class _ProjectState {
509
513
  // --- Derived (public readonly) ---
510
514
  umbrellaIDs;
511
515
  leafTickets;
516
+ leafTicketCount;
517
+ completeLeafTicketCount;
512
518
  // --- Derived (private) ---
513
519
  leafTicketsByPhase;
514
520
  childrenByParent;
@@ -535,6 +541,10 @@ var ProjectState = class _ProjectState {
535
541
  }
536
542
  this.umbrellaIDs = parentIDs;
537
543
  this.leafTickets = input.tickets.filter((t) => !parentIDs.has(t.id));
544
+ this.leafTicketCount = this.leafTickets.length;
545
+ this.completeLeafTicketCount = this.leafTickets.filter(
546
+ (t) => t.status === "complete"
547
+ ).length;
538
548
  const byPhase = /* @__PURE__ */ new Map();
539
549
  for (const t of this.leafTickets) {
540
550
  const phase = t.phase;
@@ -640,7 +650,7 @@ var ProjectState = class _ProjectState {
640
650
  });
641
651
  }
642
652
  get blockedCount() {
643
- return this.tickets.filter((t) => this.isBlocked(t)).length;
653
+ return this.leafTickets.filter((t) => t.status !== "complete" && this.isBlocked(t)).length;
644
654
  }
645
655
  ticketByID(id) {
646
656
  return this.ticketsByID.get(id);
@@ -1757,6 +1767,18 @@ async function initProject(root, options) {
1757
1767
  };
1758
1768
  await writeConfig(config, absRoot);
1759
1769
  await writeRoadmap(roadmap, absRoot);
1770
+ const warnings = [];
1771
+ if (options.force && exists) {
1772
+ try {
1773
+ const { warnings: loadWarnings } = await loadProject(absRoot);
1774
+ for (const w of loadWarnings) {
1775
+ if (INTEGRITY_WARNING_TYPES.includes(w.type)) {
1776
+ warnings.push(`${w.file}: ${w.message}`);
1777
+ }
1778
+ }
1779
+ } catch {
1780
+ }
1781
+ }
1760
1782
  return {
1761
1783
  root: absRoot,
1762
1784
  created: [
@@ -1765,7 +1787,8 @@ async function initProject(root, options) {
1765
1787
  ".story/tickets/",
1766
1788
  ".story/issues/",
1767
1789
  ".story/handovers/"
1768
- ]
1790
+ ],
1791
+ warnings
1769
1792
  };
1770
1793
  }
1771
1794
 
@@ -3759,8 +3782,13 @@ function registerPhaseCommand(yargs2) {
3759
3782
  }
3760
3783
 
3761
3784
  // src/cli/index.ts
3762
- var version = "0.1.1";
3763
- var HANDLED_ERROR = /* @__PURE__ */ Symbol("HANDLED_ERROR");
3785
+ var version = "0.1.3";
3786
+ var HandledError = class extends Error {
3787
+ constructor() {
3788
+ super("HANDLED_ERROR");
3789
+ this.name = "HandledError";
3790
+ }
3791
+ };
3764
3792
  var rawArgs = hideBin(process.argv);
3765
3793
  function sniffFormat(args) {
3766
3794
  for (let i = 0; i < args.length; i++) {
@@ -3774,7 +3802,7 @@ var cli = yargs(rawArgs).scriptName("claudestory").version(version).strict().dem
3774
3802
  if (err) throw err;
3775
3803
  writeOutput(formatError("invalid_input", msg ?? "Unknown error", errorFormat));
3776
3804
  process.exitCode = ExitCode.USER_ERROR;
3777
- throw HANDLED_ERROR;
3805
+ throw new HandledError();
3778
3806
  });
3779
3807
  cli = registerInitCommand(cli);
3780
3808
  cli = registerStatusCommand(cli);
@@ -3784,9 +3812,14 @@ cli = registerIssueCommand(cli);
3784
3812
  cli = registerHandoverCommand(cli);
3785
3813
  cli = registerBlockerCommand(cli);
3786
3814
  cli = registerValidateCommand(cli);
3787
- await cli.parseAsync().catch((err) => {
3788
- if (err === HANDLED_ERROR) return;
3815
+ function handleUnexpectedError(err) {
3816
+ if (err instanceof HandledError) return;
3789
3817
  const message = err instanceof Error ? err.message : String(err);
3790
3818
  writeOutput(formatError("io_error", message, errorFormat));
3791
3819
  process.exitCode = ExitCode.USER_ERROR;
3792
- });
3820
+ }
3821
+ try {
3822
+ await cli.parseAsync().catch(handleUnexpectedError);
3823
+ } catch (err) {
3824
+ handleUnexpectedError(err);
3825
+ }
package/dist/index.d.ts CHANGED
@@ -400,6 +400,8 @@ declare class ProjectState {
400
400
  readonly handoverFilenames: readonly string[];
401
401
  readonly umbrellaIDs: ReadonlySet<string>;
402
402
  readonly leafTickets: readonly Ticket[];
403
+ readonly leafTicketCount: number;
404
+ readonly completeLeafTicketCount: number;
403
405
  private readonly leafTicketsByPhase;
404
406
  private readonly childrenByParent;
405
407
  private readonly reverseBlocksMap;
@@ -697,6 +699,7 @@ interface InitOptions {
697
699
  interface InitResult {
698
700
  readonly root: string;
699
701
  readonly created: readonly string[];
702
+ readonly warnings: readonly string[];
700
703
  }
701
704
  /**
702
705
  * Scaffolds a new .story/ directory structure.
@@ -762,6 +765,7 @@ declare function formatError(code: ErrorCode, message: string, format: OutputFor
762
765
  declare function formatInitResult(result: {
763
766
  root: string;
764
767
  created: readonly string[];
768
+ warnings: readonly string[];
765
769
  }, format: OutputFormat): string;
766
770
  declare function formatHandoverList(filenames: readonly string[], format: OutputFormat): string;
767
771
  declare function formatHandoverContent(filename: string, content: string, format: OutputFormat): string;
package/dist/index.js CHANGED
@@ -127,6 +127,8 @@ var ProjectState = class _ProjectState {
127
127
  // --- Derived (public readonly) ---
128
128
  umbrellaIDs;
129
129
  leafTickets;
130
+ leafTicketCount;
131
+ completeLeafTicketCount;
130
132
  // --- Derived (private) ---
131
133
  leafTicketsByPhase;
132
134
  childrenByParent;
@@ -153,6 +155,10 @@ var ProjectState = class _ProjectState {
153
155
  }
154
156
  this.umbrellaIDs = parentIDs;
155
157
  this.leafTickets = input.tickets.filter((t) => !parentIDs.has(t.id));
158
+ this.leafTicketCount = this.leafTickets.length;
159
+ this.completeLeafTicketCount = this.leafTickets.filter(
160
+ (t) => t.status === "complete"
161
+ ).length;
156
162
  const byPhase = /* @__PURE__ */ new Map();
157
163
  for (const t of this.leafTickets) {
158
164
  const phase = t.phase;
@@ -258,7 +264,7 @@ var ProjectState = class _ProjectState {
258
264
  });
259
265
  }
260
266
  get blockedCount() {
261
- return this.tickets.filter((t) => this.isBlocked(t)).length;
267
+ return this.leafTickets.filter((t) => t.status !== "complete" && this.isBlocked(t)).length;
262
268
  }
263
269
  ticketByID(id) {
264
270
  return this.ticketsByID.get(id);
@@ -1410,6 +1416,18 @@ async function initProject(root, options) {
1410
1416
  };
1411
1417
  await writeConfig(config, absRoot);
1412
1418
  await writeRoadmap(roadmap, absRoot);
1419
+ const warnings = [];
1420
+ if (options.force && exists) {
1421
+ try {
1422
+ const { warnings: loadWarnings } = await loadProject(absRoot);
1423
+ for (const w of loadWarnings) {
1424
+ if (INTEGRITY_WARNING_TYPES.includes(w.type)) {
1425
+ warnings.push(`${w.file}: ${w.message}`);
1426
+ }
1427
+ }
1428
+ } catch {
1429
+ }
1430
+ }
1413
1431
  return {
1414
1432
  root: absRoot,
1415
1433
  created: [
@@ -1418,7 +1436,8 @@ async function initProject(root, options) {
1418
1436
  ".story/tickets/",
1419
1437
  ".story/issues/",
1420
1438
  ".story/handovers/"
1421
- ]
1439
+ ],
1440
+ warnings
1422
1441
  };
1423
1442
  }
1424
1443
 
@@ -1467,9 +1486,9 @@ function formatStatus(state, format) {
1467
1486
  const phases = phasesWithStatus(state);
1468
1487
  const data = {
1469
1488
  project: state.config.project,
1470
- totalTickets: state.totalTicketCount,
1471
- completeTickets: state.completeTicketCount,
1472
- openTickets: state.openTicketCount,
1489
+ totalTickets: state.leafTicketCount,
1490
+ completeTickets: state.completeLeafTicketCount,
1491
+ openTickets: state.leafTicketCount - state.completeLeafTicketCount,
1473
1492
  blockedTickets: state.blockedCount,
1474
1493
  openIssues: state.openIssueCount,
1475
1494
  handovers: state.handoverFilenames.length,
@@ -1486,7 +1505,7 @@ function formatStatus(state, format) {
1486
1505
  const lines = [
1487
1506
  `# ${escapeMarkdownInline(state.config.project)}`,
1488
1507
  "",
1489
- `Tickets: ${state.completeTicketCount}/${state.totalTicketCount} complete, ${state.blockedCount} blocked`,
1508
+ `Tickets: ${state.completeLeafTicketCount}/${state.leafTicketCount} complete, ${state.blockedCount} blocked`,
1490
1509
  `Issues: ${state.openIssueCount} open`,
1491
1510
  `Handovers: ${state.handoverFilenames.length}`,
1492
1511
  "",
@@ -1708,7 +1727,11 @@ function formatInitResult(result, format) {
1708
1727
  if (format === "json") {
1709
1728
  return JSON.stringify(successEnvelope(result), null, 2);
1710
1729
  }
1711
- return [`Initialized .story/ at ${escapeMarkdownInline(result.root)}`, "", ...result.created.map((f) => ` ${f}`)].join("\n");
1730
+ const lines = [`Initialized .story/ at ${escapeMarkdownInline(result.root)}`, "", ...result.created.map((f) => ` ${f}`)];
1731
+ if (result.warnings.length > 0) {
1732
+ lines.push("", `Warning: ${result.warnings.length} corrupt file(s) found. Run \`claudestory validate\` to inspect.`);
1733
+ }
1734
+ return lines.join("\n");
1712
1735
  }
1713
1736
  function formatHandoverList(filenames, format) {
1714
1737
  if (format === "json") {
package/dist/mcp.js CHANGED
@@ -171,6 +171,8 @@ var ProjectState = class _ProjectState {
171
171
  // --- Derived (public readonly) ---
172
172
  umbrellaIDs;
173
173
  leafTickets;
174
+ leafTicketCount;
175
+ completeLeafTicketCount;
174
176
  // --- Derived (private) ---
175
177
  leafTicketsByPhase;
176
178
  childrenByParent;
@@ -197,6 +199,10 @@ var ProjectState = class _ProjectState {
197
199
  }
198
200
  this.umbrellaIDs = parentIDs;
199
201
  this.leafTickets = input.tickets.filter((t) => !parentIDs.has(t.id));
202
+ this.leafTicketCount = this.leafTickets.length;
203
+ this.completeLeafTicketCount = this.leafTickets.filter(
204
+ (t) => t.status === "complete"
205
+ ).length;
200
206
  const byPhase = /* @__PURE__ */ new Map();
201
207
  for (const t of this.leafTickets) {
202
208
  const phase = t.phase;
@@ -302,7 +308,7 @@ var ProjectState = class _ProjectState {
302
308
  });
303
309
  }
304
310
  get blockedCount() {
305
- return this.tickets.filter((t) => this.isBlocked(t)).length;
311
+ return this.leafTickets.filter((t) => t.status !== "complete" && this.isBlocked(t)).length;
306
312
  }
307
313
  ticketByID(id) {
308
314
  return this.ticketsByID.get(id);
@@ -853,9 +859,9 @@ function formatStatus(state, format) {
853
859
  const phases = phasesWithStatus(state);
854
860
  const data = {
855
861
  project: state.config.project,
856
- totalTickets: state.totalTicketCount,
857
- completeTickets: state.completeTicketCount,
858
- openTickets: state.openTicketCount,
862
+ totalTickets: state.leafTicketCount,
863
+ completeTickets: state.completeLeafTicketCount,
864
+ openTickets: state.leafTicketCount - state.completeLeafTicketCount,
859
865
  blockedTickets: state.blockedCount,
860
866
  openIssues: state.openIssueCount,
861
867
  handovers: state.handoverFilenames.length,
@@ -872,7 +878,7 @@ function formatStatus(state, format) {
872
878
  const lines = [
873
879
  `# ${escapeMarkdownInline(state.config.project)}`,
874
880
  "",
875
- `Tickets: ${state.completeTicketCount}/${state.totalTicketCount} complete, ${state.blockedCount} blocked`,
881
+ `Tickets: ${state.completeLeafTicketCount}/${state.leafTicketCount} complete, ${state.blockedCount} blocked`,
876
882
  `Issues: ${state.openIssueCount} open`,
877
883
  `Handovers: ${state.handoverFilenames.length}`,
878
884
  "",
@@ -1702,7 +1708,7 @@ function registerAllTools(server, pinnedRoot) {
1702
1708
  // src/mcp/index.ts
1703
1709
  var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
1704
1710
  var CONFIG_PATH2 = ".story/config.json";
1705
- var version = "0.1.1";
1711
+ var version = "0.1.3";
1706
1712
  function pinProjectRoot() {
1707
1713
  const envRoot = process.env[ENV_VAR2];
1708
1714
  if (envRoot) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anthropologies/claudestory",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {