@anthropologies/claudestory 0.1.5 → 0.1.6

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/index.d.ts CHANGED
@@ -573,6 +573,7 @@ declare function guardPath(target: string, root: string): Promise<void>;
573
573
  *
574
574
  * CLAUDESTORY_PROJECT_ROOT env var overrides walk-up discovery.
575
575
  * Returns the canonical absolute path, or null if not found.
576
+ * Throws ProjectLoaderError if .story/ exists but is unreadable.
576
577
  */
577
578
  declare function discoverProjectRoot(startDir?: string): string | null;
578
579
 
package/dist/index.js CHANGED
@@ -971,30 +971,43 @@ async function withLock(wrapDir, fn) {
971
971
  }
972
972
 
973
973
  // src/core/project-root-discovery.ts
974
- import { existsSync as existsSync3 } from "fs";
974
+ import { existsSync as existsSync3, accessSync, constants } from "fs";
975
975
  import { resolve as resolve2, dirname as dirname2, join as join3 } from "path";
976
976
  var ENV_VAR = "CLAUDESTORY_PROJECT_ROOT";
977
+ var STORY_DIR = ".story";
977
978
  var CONFIG_PATH = ".story/config.json";
978
979
  function discoverProjectRoot(startDir) {
979
980
  const envRoot = process.env[ENV_VAR];
980
981
  if (envRoot) {
981
982
  const resolved = resolve2(envRoot);
982
- if (existsSync3(join3(resolved, CONFIG_PATH))) {
983
- return resolved;
984
- }
985
- return null;
983
+ return checkRoot(resolved);
986
984
  }
987
985
  let current = resolve2(startDir ?? process.cwd());
988
986
  for (; ; ) {
989
- if (existsSync3(join3(current, CONFIG_PATH))) {
990
- return current;
991
- }
987
+ const result = checkRoot(current);
988
+ if (result) return result;
992
989
  const parent = dirname2(current);
993
990
  if (parent === current) break;
994
991
  current = parent;
995
992
  }
996
993
  return null;
997
994
  }
995
+ function checkRoot(candidate) {
996
+ if (existsSync3(join3(candidate, CONFIG_PATH))) {
997
+ return candidate;
998
+ }
999
+ if (existsSync3(join3(candidate, STORY_DIR))) {
1000
+ try {
1001
+ accessSync(join3(candidate, STORY_DIR), constants.R_OK);
1002
+ } catch {
1003
+ throw new ProjectLoaderError(
1004
+ "io_error",
1005
+ `Permission denied: cannot read .story/ in ${candidate}`
1006
+ );
1007
+ }
1008
+ }
1009
+ return null;
1010
+ }
998
1011
 
999
1012
  // src/core/queries.ts
1000
1013
  function nextTicket(state) {
package/dist/mcp.js CHANGED
@@ -7,30 +7,61 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
7
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
8
 
9
9
  // src/core/project-root-discovery.ts
10
- import { existsSync } from "fs";
10
+ import { existsSync, accessSync, constants } from "fs";
11
11
  import { resolve, dirname, join } from "path";
12
+
13
+ // src/core/errors.ts
14
+ var CURRENT_SCHEMA_VERSION = 1;
15
+ var ProjectLoaderError = class extends Error {
16
+ constructor(code, message, cause) {
17
+ super(message);
18
+ this.code = code;
19
+ this.cause = cause;
20
+ }
21
+ name = "ProjectLoaderError";
22
+ };
23
+ var INTEGRITY_WARNING_TYPES = [
24
+ "parse_error",
25
+ "schema_error",
26
+ "duplicate_id"
27
+ ];
28
+
29
+ // src/core/project-root-discovery.ts
12
30
  var ENV_VAR = "CLAUDESTORY_PROJECT_ROOT";
31
+ var STORY_DIR = ".story";
13
32
  var CONFIG_PATH = ".story/config.json";
14
33
  function discoverProjectRoot(startDir) {
15
34
  const envRoot = process.env[ENV_VAR];
16
35
  if (envRoot) {
17
36
  const resolved = resolve(envRoot);
18
- if (existsSync(join(resolved, CONFIG_PATH))) {
19
- return resolved;
20
- }
21
- return null;
37
+ return checkRoot(resolved);
22
38
  }
23
39
  let current = resolve(startDir ?? process.cwd());
24
40
  for (; ; ) {
25
- if (existsSync(join(current, CONFIG_PATH))) {
26
- return current;
27
- }
41
+ const result = checkRoot(current);
42
+ if (result) return result;
28
43
  const parent = dirname(current);
29
44
  if (parent === current) break;
30
45
  current = parent;
31
46
  }
32
47
  return null;
33
48
  }
49
+ function checkRoot(candidate) {
50
+ if (existsSync(join(candidate, CONFIG_PATH))) {
51
+ return candidate;
52
+ }
53
+ if (existsSync(join(candidate, STORY_DIR))) {
54
+ try {
55
+ accessSync(join(candidate, STORY_DIR), constants.R_OK);
56
+ } catch {
57
+ throw new ProjectLoaderError(
58
+ "io_error",
59
+ `Permission denied: cannot read .story/ in ${candidate}`
60
+ );
61
+ }
62
+ }
63
+ return null;
64
+ }
34
65
 
35
66
  // src/mcp/tools.ts
36
67
  import { z as z7 } from "zod";
@@ -365,22 +396,6 @@ var ProjectState = class _ProjectState {
365
396
  }
366
397
  };
367
398
 
368
- // src/core/errors.ts
369
- var CURRENT_SCHEMA_VERSION = 1;
370
- var ProjectLoaderError = class extends Error {
371
- constructor(code, message, cause) {
372
- super(message);
373
- this.code = code;
374
- this.cause = cause;
375
- }
376
- name = "ProjectLoaderError";
377
- };
378
- var INTEGRITY_WARNING_TYPES = [
379
- "parse_error",
380
- "schema_error",
381
- "duplicate_id"
382
- ];
383
-
384
399
  // src/core/handover-parser.ts
385
400
  import { readdir, readFile } from "fs/promises";
386
401
  import { existsSync as existsSync2 } from "fs";
@@ -2476,7 +2491,7 @@ function registerAllTools(server, pinnedRoot) {
2476
2491
  // src/mcp/index.ts
2477
2492
  var ENV_VAR2 = "CLAUDESTORY_PROJECT_ROOT";
2478
2493
  var CONFIG_PATH2 = ".story/config.json";
2479
- var version = "0.1.5";
2494
+ var version = "0.1.6";
2480
2495
  function pinProjectRoot() {
2481
2496
  const envRoot = process.env[ENV_VAR2];
2482
2497
  if (envRoot) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anthropologies/claudestory",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {