@wrongstack/tools 0.305.0 → 0.305.1

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/builtin.js CHANGED
@@ -10800,7 +10800,6 @@ import * as fs12 from "node:fs";
10800
10800
  import * as os5 from "node:os";
10801
10801
  import * as path17 from "node:path";
10802
10802
  import { fileURLToPath } from "node:url";
10803
- import { assertUnixSocketPathWithinLimit } from "@wrongstack/core/utils";
10804
10803
 
10805
10804
  // src/codebase-index/writer.ts
10806
10805
  import { expectDefined as expectDefined2 } from "@wrongstack/core/utils";
@@ -20878,7 +20877,7 @@ async function detectFixer(cwd) {
20878
20877
  init_util();
20879
20878
  import { spawn as spawn9 } from "node:child_process";
20880
20879
  import { statSync as statSync4 } from "node:fs";
20881
- import { dirname as dirname14, resolve as resolve13, sep as sep6 } from "node:path";
20880
+ import { dirname as dirname13, resolve as resolve13, sep as sep6 } from "node:path";
20882
20881
  import { assessCommitSafety } from "@wrongstack/core/coordination";
20883
20882
  import { buildChildEnv as buildChildEnv4 } from "@wrongstack/core/utils";
20884
20883
  var TIMEOUT_MS2 = 3e4;
@@ -21057,7 +21056,7 @@ function findGitDir2(cwd, projectRoot) {
21057
21056
  } catch {
21058
21057
  }
21059
21058
  if (dir === root) break;
21060
- const parent = dirname14(dir);
21059
+ const parent = dirname13(dir);
21061
21060
  if (parent === dir) break;
21062
21061
  dir = parent;
21063
21062
  }
@@ -31,6 +31,7 @@ export { internalKindToLspKind, lspKindToInternalKind, } from './lsp-kind.js';
31
31
  export type { ProjectIndexServerClientHealth, ProjectIndexServerConnectionState, ProjectIndexServerConnectionStatus, } from './project-server-client.js';
32
32
  export type { ProjectIndexServerActivity, ProjectIndexServerHealth, } from './project-server-protocol.js';
33
33
  export type { CallSite, CodeMapGraph, FileMeta, FileSymbols, GraphEdge, GraphNode, IndexResult, IndexStats, SearchResult, Symbol, SymbolKind, SymbolLang, } from './schema.js';
34
+ export { projectIndexServerEndpoint, projectIndexServerMetadataPath, } from './project-server-endpoint.js';
34
35
  export { SCHEMA_VERSION } from './schema.js';
35
36
  export { codebaseIndexDirOverride, IndexStore, resolveIndexDir } from './writer.js';
36
37
  //# sourceMappingURL=index.d.ts.map
@@ -2815,7 +2815,6 @@ import * as fs4 from "node:fs";
2815
2815
  import * as os from "node:os";
2816
2816
  import * as path5 from "node:path";
2817
2817
  import { fileURLToPath } from "node:url";
2818
- import { assertUnixSocketPathWithinLimit } from "@wrongstack/core/utils";
2819
2818
 
2820
2819
  // src/codebase-index/writer.ts
2821
2820
  import { expectDefined } from "@wrongstack/core/utils";
@@ -9489,6 +9488,8 @@ export {
9489
9488
  onIndexStateChange,
9490
9489
  outgoingCallsService2 as outgoingCallsService,
9491
9490
  packageGraphService2 as packageGraphService,
9491
+ projectIndexServerEndpoint,
9492
+ projectIndexServerMetadataPath,
9492
9493
  resetIndexCircuitBreaker,
9493
9494
  resolveIndexDir,
9494
9495
  resolveProjectIndexDaemonAvailability,
@@ -3,7 +3,7 @@ export declare const PROJECT_INDEX_SERVER_METADATA_FILE = "server.json";
3
3
  /**
4
4
  * Short directory name that owns the per-project Unix socket on Linux.
5
5
  *
6
- * The directory is created `0o700` by `ensureProjectIndexSocketDirectory`: on
6
+ * The directory is created `0o700` by `bindProjectEndpoint`: on
7
7
  * multi-user Linux `/tmp` the kernel's sticky bit otherwise lets a local
8
8
  * attacker pre-bind a predictable socket name (project paths are guessable
9
9
  * via the public `buildId` handshake), hijacking clients whose `bind()` hits
@@ -48,5 +48,4 @@ export declare function projectIndexServerKey(projectRoot: string, indexDir?: st
48
48
  */
49
49
  export declare function projectIndexServerEndpoint(projectRoot: string, indexDir?: string): string;
50
50
  export declare function projectIndexServerMetadataPath(projectRoot: string, indexDir?: string): string;
51
- export declare function ensureProjectIndexSocketDirectory(endpoint: string): void;
52
51
  //# sourceMappingURL=project-server-endpoint.d.ts.map
@@ -2713,6 +2713,7 @@ import {
2713
2713
  useDaemonPerfDefaults,
2714
2714
  watchProjectTree
2715
2715
  } from "@wrongstack/core/utils";
2716
+ import { bindProjectEndpoint } from "@wrongstack/persistence";
2716
2717
 
2717
2718
  // src/codebase-index/indexer.ts
2718
2719
  import { expectDefined as expectDefined5 } from "@wrongstack/core/utils";
@@ -7218,7 +7219,6 @@ import * as fs10 from "node:fs";
7218
7219
  import * as os3 from "node:os";
7219
7220
  import * as path13 from "node:path";
7220
7221
  import { fileURLToPath as fileURLToPath3 } from "node:url";
7221
- import { assertUnixSocketPathWithinLimit } from "@wrongstack/core/utils";
7222
7222
  var PROJECT_INDEX_SERVER_PROTOCOL_VERSION = 1;
7223
7223
  var PROJECT_INDEX_SERVER_METADATA_FILE = "server.json";
7224
7224
  var PROJECT_INDEX_SERVER_SOCKET_DIR = `wsci-v${PROJECT_INDEX_SERVER_PROTOCOL_VERSION}`;
@@ -7260,12 +7260,6 @@ function projectIndexServerMetadataPath(projectRoot2, indexDir2) {
7260
7260
  PROJECT_INDEX_SERVER_METADATA_FILE
7261
7261
  );
7262
7262
  }
7263
- function ensureProjectIndexSocketDirectory(endpoint2) {
7264
- if (process.platform !== "win32") {
7265
- assertUnixSocketPathWithinLimit(endpoint2, "codebase-index");
7266
- fs10.mkdirSync(path13.dirname(endpoint2), { recursive: true, mode: 448 });
7267
- }
7268
- }
7269
7263
 
7270
7264
  // src/codebase-index/project-server-protocol.ts
7271
7265
  var PROJECT_INDEX_SERVER_MAX_FRAME_CHARS = 64 * 1024 * 1024;
@@ -7877,27 +7871,32 @@ async function stop(_reason) {
7877
7871
  }
7878
7872
  await stopMemoryWatchdog();
7879
7873
  }
7880
- ensureProjectIndexSocketDirectory(endpoint);
7881
- server.once("error", (error) => {
7882
- if (error.code === "EADDRINUSE") {
7874
+ void (async () => {
7875
+ const bind = await bindProjectEndpoint({ server, endpoint, service: "codebase-index" });
7876
+ if (bind.outcome === "already-owned") {
7883
7877
  process.exitCode = 0;
7884
7878
  return;
7885
7879
  }
7886
- process.stderr.write(`codebase-index server failed: ${error.message}
7880
+ if (bind.outcome === "failed") {
7881
+ process.stderr.write(`codebase-index server failed: ${bind.error.message}
7882
+ `);
7883
+ process.exitCode = 1;
7884
+ return;
7885
+ }
7886
+ if (bind.reclaimedStaleEndpoint) {
7887
+ process.stderr.write(`codebase-index server reclaimed stale endpoint ${endpoint}
7887
7888
  `);
7888
- process.exitCode = 1;
7889
- });
7890
- server.listen(endpoint, () => {
7891
- if (process.platform !== "win32") {
7892
- try {
7893
- fs11.chmodSync(endpoint, 384);
7894
- } catch {
7895
- }
7896
7889
  }
7890
+ server.on("error", (error) => {
7891
+ if (stopping) return;
7892
+ process.stderr.write(`codebase-index server error: ${error.message}
7893
+ `);
7894
+ process.exitCode = 1;
7895
+ });
7897
7896
  writeMetadata();
7898
7897
  markMetadataWritten?.();
7899
7898
  scheduleIdleStop();
7900
- });
7899
+ })();
7901
7900
  process.once("SIGINT", () => void stop("SIGINT"));
7902
7901
  process.once("SIGTERM", () => void stop("SIGTERM"));
7903
7902
  //# sourceMappingURL=project-server.js.map
package/dist/index.js CHANGED
@@ -11170,7 +11170,6 @@ import * as fs12 from "node:fs";
11170
11170
  import * as os5 from "node:os";
11171
11171
  import * as path17 from "node:path";
11172
11172
  import { fileURLToPath } from "node:url";
11173
- import { assertUnixSocketPathWithinLimit } from "@wrongstack/core/utils";
11174
11173
 
11175
11174
  // src/codebase-index/writer.ts
11176
11175
  import { expectDefined as expectDefined2 } from "@wrongstack/core/utils";
@@ -21129,7 +21128,7 @@ async function detectFixer(cwd) {
21129
21128
  init_util();
21130
21129
  import { spawn as spawn9 } from "node:child_process";
21131
21130
  import { statSync as statSync4 } from "node:fs";
21132
- import { dirname as dirname14, resolve as resolve13, sep as sep6 } from "node:path";
21131
+ import { dirname as dirname13, resolve as resolve13, sep as sep6 } from "node:path";
21133
21132
  import { assessCommitSafety } from "@wrongstack/core/coordination";
21134
21133
  import { buildChildEnv as buildChildEnv4 } from "@wrongstack/core/utils";
21135
21134
  var TIMEOUT_MS2 = 3e4;
@@ -21308,7 +21307,7 @@ function findGitDir2(cwd, projectRoot) {
21308
21307
  } catch {
21309
21308
  }
21310
21309
  if (dir === root) break;
21311
- const parent = dirname14(dir);
21310
+ const parent = dirname13(dir);
21312
21311
  if (parent === dir) break;
21313
21312
  dir = parent;
21314
21313
  }
@@ -23909,7 +23908,7 @@ var KANBAN_INPUT_SCHEMA = {
23909
23908
 
23910
23909
  // src/session-kanban.ts
23911
23910
  import { watch } from "node:fs";
23912
- import { basename as basename13, dirname as dirname15 } from "node:path";
23911
+ import { basename as basename13, dirname as dirname14 } from "node:path";
23913
23912
  import { getSharedProjectMailbox } from "@wrongstack/core/coordination";
23914
23913
  import {
23915
23914
  loadPlan,
@@ -24527,7 +24526,7 @@ function attachSessionKanbanMirror(context) {
24527
24526
  const configureWatcher = () => {
24528
24527
  const planPath = context.meta["plan.path"];
24529
24528
  const taskPath = context.meta["task.path"];
24530
- const candidate = typeof planPath === "string" && planPath ? dirname15(planPath) : typeof taskPath === "string" && taskPath ? dirname15(taskPath) : "";
24529
+ const candidate = typeof planPath === "string" && planPath ? dirname14(planPath) : typeof taskPath === "string" && taskPath ? dirname14(taskPath) : "";
24531
24530
  if (!candidate || candidate === watchedDir) return;
24532
24531
  watcher?.close();
24533
24532
  watcher = null;
@@ -24618,9 +24617,21 @@ async function rebindSessionKanbanTask(context) {
24618
24617
  context.setCurrentKanbanTask(best.taskId, best.boardId);
24619
24618
  return { boardId: best.boardId, taskId: best.taskId };
24620
24619
  }
24620
+ var degradationReason;
24621
24621
  async function hydrateSessionKanban(context) {
24622
24622
  const id = context.session?.id ?? "";
24623
24623
  if (!id) return null;
24624
+ try {
24625
+ const board = await hydrateSessionKanbanBoard(context, id);
24626
+ degradationReason = void 0;
24627
+ return board;
24628
+ } catch (error) {
24629
+ degradationReason = error instanceof Error ? error.message : String(error);
24630
+ fireAndForget("hydrate", Promise.reject(error));
24631
+ return null;
24632
+ }
24633
+ }
24634
+ async function hydrateSessionKanbanBoard(context, id) {
24624
24635
  await rebindSessionKanbanTask(context);
24625
24636
  await cleanupEmptySessionKanbanBoards(context.projectRoot, id);
24626
24637
  if (context.projectRoot) {
package/dist/pack.js CHANGED
@@ -10800,7 +10800,6 @@ import * as fs12 from "node:fs";
10800
10800
  import * as os5 from "node:os";
10801
10801
  import * as path17 from "node:path";
10802
10802
  import { fileURLToPath } from "node:url";
10803
- import { assertUnixSocketPathWithinLimit } from "@wrongstack/core/utils";
10804
10803
 
10805
10804
  // src/codebase-index/writer.ts
10806
10805
  import { expectDefined as expectDefined2 } from "@wrongstack/core/utils";
@@ -20878,7 +20877,7 @@ async function detectFixer(cwd) {
20878
20877
  init_util();
20879
20878
  import { spawn as spawn9 } from "node:child_process";
20880
20879
  import { statSync as statSync4 } from "node:fs";
20881
- import { dirname as dirname14, resolve as resolve13, sep as sep6 } from "node:path";
20880
+ import { dirname as dirname13, resolve as resolve13, sep as sep6 } from "node:path";
20882
20881
  import { assessCommitSafety } from "@wrongstack/core/coordination";
20883
20882
  import { buildChildEnv as buildChildEnv4 } from "@wrongstack/core/utils";
20884
20883
  var TIMEOUT_MS2 = 3e4;
@@ -21057,7 +21056,7 @@ function findGitDir2(cwd, projectRoot) {
21057
21056
  } catch {
21058
21057
  }
21059
21058
  if (dir === root) break;
21060
- const parent = dirname14(dir);
21059
+ const parent = dirname13(dir);
21061
21060
  if (parent === dir) break;
21062
21061
  dir = parent;
21063
21062
  }
package/dist/read.js CHANGED
@@ -7277,7 +7277,6 @@ import * as fs10 from "node:fs";
7277
7277
  import * as os3 from "node:os";
7278
7278
  import * as path14 from "node:path";
7279
7279
  import { fileURLToPath as fileURLToPath3 } from "node:url";
7280
- import { assertUnixSocketPathWithinLimit } from "@wrongstack/core/utils";
7281
7280
  var PROJECT_INDEX_SERVER_PROTOCOL_VERSION = 1;
7282
7281
  var PROJECT_INDEX_SERVER_METADATA_FILE = "server.json";
7283
7282
  var PROJECT_INDEX_SERVER_SOCKET_DIR = `wsci-v${PROJECT_INDEX_SERVER_PROTOCOL_VERSION}`;
@@ -97,6 +97,31 @@ export declare function rebindSessionKanbanTask(context: Context): Promise<{
97
97
  boardId: string;
98
98
  taskId: string;
99
99
  } | null>;
100
+ /**
101
+ * Why session Kanban is unavailable, or undefined while it is healthy.
102
+ *
103
+ * Surfaces exist so a startup path can tell the user their board will not sync
104
+ * without having to catch and classify the failure itself. Cleared on the
105
+ * first hydrate that succeeds, so a daemon that comes back stops being
106
+ * reported as down.
107
+ */
108
+ export declare function sessionKanbanDegradation(): string | undefined;
109
+ /**
110
+ * Project the session's todos, plan, and tasks onto its Kanban board.
111
+ *
112
+ * Kanban is a projection: every card here is derived from state that lives
113
+ * somewhere else and is authoritative there. Losing the board costs the user a
114
+ * view, not any work — so an unreachable Kanban daemon degrades this to `null`
115
+ * rather than propagating.
116
+ *
117
+ * That distinction used to be missing, and it cost an entire session. When a
118
+ * killed daemon left a stale IPC endpoint behind, the connect error thrown
119
+ * here unwound through `setupSession` and killed `wstack` at startup: no
120
+ * prompt, no session, just a socket path in a stack trace — for a board the
121
+ * user had not asked to see. `bindProjectEndpoint` now stops the daemon from
122
+ * wedging in the first place, but the call site must still hold: an optional
123
+ * view may never take down the session it decorates.
124
+ */
100
125
  export declare function hydrateSessionKanban(context: Context): Promise<KanbanBoard | null>;
101
126
  export interface SessionKanbanSourceUpdate {
102
127
  source: 'todo' | 'task' | 'plan' | null;
@@ -720,9 +720,24 @@ async function rebindSessionKanbanTask(context) {
720
720
  context.setCurrentKanbanTask(best.taskId, best.boardId);
721
721
  return { boardId: best.boardId, taskId: best.taskId };
722
722
  }
723
+ var degradationReason;
724
+ function sessionKanbanDegradation() {
725
+ return degradationReason;
726
+ }
723
727
  async function hydrateSessionKanban(context) {
724
728
  const id = context.session?.id ?? "";
725
729
  if (!id) return null;
730
+ try {
731
+ const board = await hydrateSessionKanbanBoard(context, id);
732
+ degradationReason = void 0;
733
+ return board;
734
+ } catch (error) {
735
+ degradationReason = error instanceof Error ? error.message : String(error);
736
+ fireAndForget("hydrate", Promise.reject(error));
737
+ return null;
738
+ }
739
+ }
740
+ async function hydrateSessionKanbanBoard(context, id) {
726
741
  await rebindSessionKanbanTask(context);
727
742
  await cleanupEmptySessionKanbanBoards(context.projectRoot, id);
728
743
  if (context.projectRoot) {
@@ -958,6 +973,7 @@ export {
958
973
  projectSessionTasksToKanban,
959
974
  projectSessionTodosToKanban,
960
975
  rebindSessionKanbanTask,
976
+ sessionKanbanDegradation,
961
977
  takeSessionMirrorFailure,
962
978
  taskFileToSerializedGraph,
963
979
  todoListToSerializedGraph,
package/dist/tool-tier.js CHANGED
@@ -10800,7 +10800,6 @@ import * as fs12 from "node:fs";
10800
10800
  import * as os5 from "node:os";
10801
10801
  import * as path17 from "node:path";
10802
10802
  import { fileURLToPath } from "node:url";
10803
- import { assertUnixSocketPathWithinLimit } from "@wrongstack/core/utils";
10804
10803
 
10805
10804
  // src/codebase-index/writer.ts
10806
10805
  import { expectDefined as expectDefined2 } from "@wrongstack/core/utils";
@@ -20878,7 +20877,7 @@ async function detectFixer(cwd) {
20878
20877
  init_util();
20879
20878
  import { spawn as spawn9 } from "node:child_process";
20880
20879
  import { statSync as statSync4 } from "node:fs";
20881
- import { dirname as dirname14, resolve as resolve13, sep as sep6 } from "node:path";
20880
+ import { dirname as dirname13, resolve as resolve13, sep as sep6 } from "node:path";
20882
20881
  import { assessCommitSafety } from "@wrongstack/core/coordination";
20883
20882
  import { buildChildEnv as buildChildEnv4 } from "@wrongstack/core/utils";
20884
20883
  var TIMEOUT_MS2 = 3e4;
@@ -21057,7 +21056,7 @@ function findGitDir2(cwd, projectRoot) {
21057
21056
  } catch {
21058
21057
  }
21059
21058
  if (dir === root) break;
21060
- const parent = dirname14(dir);
21059
+ const parent = dirname13(dir);
21061
21060
  if (parent === dir) break;
21062
21061
  dir = parent;
21063
21062
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/tools",
3
- "version": "0.305.0",
3
+ "version": "0.305.1",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack built-in tools: read/write/edit, bash/exec, grep/glob, git, fetch, test, lint, and more.",
6
6
  "repository": {
@@ -253,8 +253,9 @@
253
253
  "turndown": "^7.2.4",
254
254
  "undici": "^8.9.0",
255
255
  "web-tree-sitter": "0.26.12",
256
- "@wrongstack/kanban": "0.305.0",
257
- "@wrongstack/core": "0.305.0"
256
+ "@wrongstack/kanban": "0.305.1",
257
+ "@wrongstack/core": "0.305.1",
258
+ "@wrongstack/persistence": "0.305.1"
258
259
  },
259
260
  "devDependencies": {
260
261
  "@types/node": "^26.1.2",