@gempack/squad-mcp 0.10.0 → 0.11.0

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 (46) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/CHANGELOG.md +89 -0
  4. package/README.md +34 -8
  5. package/dist/errors.d.ts +1 -1
  6. package/dist/errors.js.map +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/learning/format.js +0 -0
  9. package/dist/learning/format.js.map +1 -1
  10. package/dist/learning/normalize.d.ts +28 -0
  11. package/dist/learning/normalize.js +54 -0
  12. package/dist/learning/normalize.js.map +1 -0
  13. package/dist/learning/store.d.ts +33 -3
  14. package/dist/learning/store.js +39 -3
  15. package/dist/learning/store.js.map +1 -1
  16. package/dist/runs/aggregate.js +6 -9
  17. package/dist/runs/aggregate.js.map +1 -1
  18. package/dist/runs/store.d.ts +14 -0
  19. package/dist/runs/store.js +54 -2
  20. package/dist/runs/store.js.map +1 -1
  21. package/dist/tools/list-runs.js +2 -2
  22. package/dist/tools/list-runs.js.map +1 -1
  23. package/dist/tools/prune-learnings.d.ts +84 -0
  24. package/dist/tools/prune-learnings.js +256 -0
  25. package/dist/tools/prune-learnings.js.map +1 -0
  26. package/dist/tools/read-learnings.d.ts +37 -1
  27. package/dist/tools/read-learnings.js +102 -10
  28. package/dist/tools/read-learnings.js.map +1 -1
  29. package/dist/tools/record-learning.d.ts +0 -0
  30. package/dist/tools/record-learning.js +0 -0
  31. package/dist/tools/record-learning.js.map +1 -1
  32. package/dist/tools/record-run.js +21 -15
  33. package/dist/tools/record-run.js.map +1 -1
  34. package/dist/tools/registry.js +13 -1
  35. package/dist/tools/registry.js.map +1 -1
  36. package/dist/util/atomic-rewrite-jsonl.d.ts +36 -0
  37. package/dist/util/atomic-rewrite-jsonl.js +95 -0
  38. package/dist/util/atomic-rewrite-jsonl.js.map +1 -0
  39. package/dist/util/path-safety.d.ts +36 -0
  40. package/dist/util/path-safety.js +76 -0
  41. package/dist/util/path-safety.js.map +1 -1
  42. package/package.json +1 -1
  43. package/skills/brainstorm/SKILL.md +70 -7
  44. package/skills/question/SKILL.md +73 -1
  45. package/skills/squad/SKILL.md +66 -74
  46. package/skills/stats/SKILL.md +1 -0
@@ -6,8 +6,13 @@ import { resolveSafePath, createSafePathContext } from "../util/path-safety.js";
6
6
  import { AGENT_NAMES_TUPLE } from "../config/ownership-matrix.js";
7
7
  const schema = z.object({
8
8
  workspace_root: z.string().min(1).max(4096),
9
- /** Cap rendered/returned entries. Default 50. */
10
- limit: z.number().int().positive().max(200).optional().default(50),
9
+ /**
10
+ * Cap rendered/returned entries. Default 50. `0` is a valid sentinel
11
+ * meaning "summary only, no entries" (used by `/squad:stats` to fetch
12
+ * counts without paging the file). Range widened from `positive()` to
13
+ * `nonnegative()` in v0.11.0 to accommodate that.
14
+ */
15
+ limit: z.number().int().nonnegative().max(200).optional().default(50),
11
16
  /** When set, restrict to learnings for this agent. */
12
17
  agent: z.enum(AGENT_NAMES_TUPLE).optional(),
13
18
  /** When set, restrict to accepts or rejects. Default both. */
@@ -23,6 +28,21 @@ const schema = z.object({
23
28
  * array. Skip the render when the caller will format their own.
24
29
  */
25
30
  include_rendered: z.boolean().optional().default(true),
31
+ /**
32
+ * v0.11.0+ : when true, include entries with `archived: true` in the
33
+ * result. Default false — archived entries are kept on disk for forensics
34
+ * but suppressed from the active read path. Set true for debug / audit /
35
+ * `/squad:stats` summary panels that need the total count.
36
+ */
37
+ include_archived: z.boolean().optional().default(false),
38
+ /**
39
+ * v0.11.0+ : when true, include a `summary` object on the response with
40
+ * `{total, active, archived, promoted}` counts (computed over the full
41
+ * file, ignoring agent / decision / scope filters but respecting
42
+ * include_archived semantics). Used by `/squad:stats` to surface the
43
+ * journal health line.
44
+ */
45
+ include_summary: z.boolean().optional().default(false),
26
46
  });
27
47
  /**
28
48
  * Read recent learnings from `.squad/learnings.jsonl` (path overridable via
@@ -37,26 +57,98 @@ export async function readLearningsTool(input) {
37
57
  // Honor the master switch — if learnings disabled, return empty without
38
58
  // touching the filesystem (the user explicitly turned it off).
39
59
  if (!config.learnings.enabled) {
40
- return { entries: [], total_in_store: 0, rendered: "", source: null };
60
+ const baseOut = {
61
+ entries: [],
62
+ total_in_store: 0,
63
+ rendered: "",
64
+ source: null,
65
+ };
66
+ return input.include_summary
67
+ ? { ...baseOut, summary: { total: 0, active: 0, archived: 0, promoted: 0 } }
68
+ : baseOut;
41
69
  }
42
70
  const configuredPath = config.learnings.path;
43
71
  const allEntries = await readLearnings(safeRoot, { configuredPath });
44
- const filtered = tailRecent(allEntries, input.limit, {
45
- ...(input.agent !== undefined ? { agent: input.agent } : {}),
46
- ...(input.decision !== undefined ? { decision: input.decision } : {}),
47
- });
48
- const rendered = input.include_rendered
49
- ? formatLearningsForPrompt(filtered, {
72
+ // v0.11.0: compute summary over the FULL file before any filter is applied.
73
+ // Counts respect file-level state, not query-level filters.
74
+ const summary = input.include_summary
75
+ ? {
76
+ total: allEntries.length,
77
+ active: allEntries.filter((e) => !e.archived).length,
78
+ archived: allEntries.filter((e) => e.archived === true).length,
79
+ promoted: allEntries.filter((e) => e.promoted === true).length,
80
+ }
81
+ : undefined;
82
+ // v0.11.0: default read suppresses archived entries. include_archived: true
83
+ // opts back in (debug / audit / stats panel surfacing).
84
+ const visible = input.include_archived
85
+ ? allEntries
86
+ : allEntries.filter((e) => e.archived !== true);
87
+ // v0.11.0 (cycle-2 Blocker B1 fix): promoted entries surface FIRST in
88
+ // BOTH the entries[] array (API view for direct callers) AND in the
89
+ // rendered markdown block (LLM prompt view).
90
+ //
91
+ // The previous implementation built `[...promoted, ...rest]` and passed
92
+ // it through `tailRecent.slice(-limit)`, which is a TAIL slice — so
93
+ // promoted entries (sitting at the HEAD) were silently dropped the
94
+ // moment `entries.length > limit`. Worse, `formatLearningsForPrompt`
95
+ // reverses the array before rendering, so even in small fixtures the
96
+ // promoted entries landed at the BOTTOM of the rendered output.
97
+ //
98
+ // New flow:
99
+ // 1. Partition visible entries into promoted vs. rest.
100
+ // 2. Cap promoted at MAX_PROMOTED_IN_PROMPT to bound prompt size as
101
+ // the journal accumulates promoted entries over a project lifetime
102
+ // (architect cycle-2 Major M2). Pick the most-recent N by ts.
103
+ // 3. Apply the user's agent / decision filter ONLY to `rest` — promoted
104
+ // entries are team policy and bypass per-agent narrowing by design.
105
+ // 4. Order BOTH lists newest-first.
106
+ // 5. Build the API-visible `entries` array as
107
+ // `[...promotedNewestFirst, ...restNewestFirst]` so direct API
108
+ // consumers see promoted at the top.
109
+ // 6. For the render input, REVERSE `entries` once so the formatter's
110
+ // internal `.reverse()` flips it back to the same shape — promoted
111
+ // stays at the top of the rendered output. This keeps the formatter
112
+ // contract (input is chronological-oldest-first) intact for the
113
+ // existing test suite.
114
+ const MAX_PROMOTED_IN_PROMPT = 10;
115
+ const promoted = visible.filter((e) => e.promoted === true);
116
+ const rest = visible.filter((e) => e.promoted !== true);
117
+ // promoted: sort ascending by ts so slice(-N) returns newest N (in oldest-
118
+ // first order), then reverse to get newest-first.
119
+ const promotedSorted = [...promoted].sort((a, b) => a.ts.localeCompare(b.ts));
120
+ const promotedCappedNewestFirst = [...promotedSorted.slice(-MAX_PROMOTED_IN_PROMPT)].reverse();
121
+ // rest: tailRecent returns tail-N in storage order (oldest-first within
122
+ // the tail). Reverse for newest-first display.
123
+ const restBudget = Math.max(0, input.limit - promotedCappedNewestFirst.length);
124
+ const restTail = restBudget > 0
125
+ ? tailRecent(rest, restBudget, {
126
+ ...(input.agent !== undefined ? { agent: input.agent } : {}),
127
+ ...(input.decision !== undefined ? { decision: input.decision } : {}),
128
+ })
129
+ : [];
130
+ const restTailNewestFirst = [...restTail].reverse();
131
+ // API-visible entries: promoted first, newest-within-each-group first.
132
+ const filtered = input.limit === 0 ? [] : [...promotedCappedNewestFirst, ...restTailNewestFirst];
133
+ // Format-input shape: chronological oldest-first. Since `filtered` is
134
+ // already in newest-first display order, reverse it before handing to
135
+ // the formatter (the formatter's internal `.reverse()` flips it back).
136
+ // This is the load-bearing detail that keeps the existing
137
+ // `learning-format.test.ts` contract intact while also putting promoted
138
+ // entries at the top of the rendered output (cycle-2 Blocker B1 fix).
139
+ const rendered = input.include_rendered && input.limit > 0
140
+ ? formatLearningsForPrompt([...filtered].reverse(), {
50
141
  ...(input.changed_files ? { changedFiles: input.changed_files } : {}),
51
142
  limit: input.limit,
52
143
  })
53
144
  : "";
54
- return {
145
+ const baseOut = {
55
146
  entries: filtered,
56
147
  total_in_store: allEntries.length,
57
148
  rendered,
58
149
  source: allEntries.length > 0 ? `${safeRoot}/${configuredPath ?? ".squad/learnings.jsonl"}` : null,
59
150
  };
151
+ return summary ? { ...baseOut, summary } : baseOut;
60
152
  }
61
153
  export const readLearningsToolDef = {
62
154
  name: "read_learnings",
@@ -1 +1 @@
1
- {"version":3,"file":"read-learnings.js","sourceRoot":"","sources":["../../src/tools/read-learnings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"read-learnings.js","sourceRoot":"","sources":["../../src/tools/read-learnings.ts"],"names":[],"mappings":"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"}
Binary file
Binary file
@@ -1 +1 @@
1
- {"version":3,"file":"record-learning.js","sourceRoot":"","sources":["../../src/tools/record-learning.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"record-learning.js","sourceRoot":"","sources":["../../src/tools/record-learning.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,27 @@
1
1
  import { z } from "zod";
2
2
  import { SafeString } from "./_shared/schemas.js";
3
3
  import { AGENT_NAMES_TUPLE } from "../config/ownership-matrix.js";
4
- import { appendRun } from "../runs/store.js";
4
+ import { appendRun, INVOCATION_VALUES } from "../runs/store.js";
5
5
  /**
6
- * SINGLE WRITER CONTRACT (plan v4, cycle 2 architect A-4; extended in v0.10.0).
6
+ * SINGLE WRITER CONTRACT (plan v4, cycle 2 architect A-4; extended in v0.10.0,
7
+ * v0.10.1).
7
8
  *
8
9
  * Legitimate callers of this tool are skills that own a two-phase lifecycle:
9
10
  *
10
11
  * - `skills/squad/SKILL.md` (v0.9.0+) — Phase 1 `in_flight` + Phase 10
11
- * terminal pair for `/squad:implement` and `/squad:review` runs.
12
+ * terminal pair for `/squad:implement` and `/squad:review` runs
13
+ * (invocations: `implement`, `review`, `task`).
12
14
  * - `skills/debug/SKILL.md` (v0.10.0+) — Phase A `in_flight` + Phase C
13
- * terminal pair for `/squad:debug` runs with `invocation: "debug"`.
15
+ * terminal pair for `/squad:debug` runs (invocation: `debug`).
16
+ * - `skills/question/SKILL.md` (v0.10.1+) — Phase 1.5 `in_flight` + Phase
17
+ * 3.5 terminal pair for `/squad:question` runs (invocation: `question`).
18
+ * - `skills/brainstorm/SKILL.md` (v0.10.1+) — Step 1.5 `in_flight` + Step
19
+ * 5.5 terminal pair for `/brainstorm` runs (invocation: `brainstorm`).
14
20
  *
15
- * Any other caller is a bug. The Phase-1 / Phase-10 (or Phase-A / Phase-C
16
- * for debug) write pair is the transactional unit; emitting terminal rows
17
- * from any other path (notably `apply_consolidation_rules`) breaks the
18
- * two-phase `(in_flight, completed)` pair-by-id invariant that the
19
- * aggregator relies on for stranded-run detection.
21
+ * Any other caller is a bug. The two-phase write pair is the transactional
22
+ * unit; emitting terminal rows from any other path (notably
23
+ * `apply_consolidation_rules`) breaks the `(in_flight, completed)` pair-by-id
24
+ * invariant that the aggregator relies on for stranded-run detection.
20
25
  *
21
26
  * Two phases of the skill's lifecycle:
22
27
  *
@@ -40,7 +45,7 @@ import { appendRun } from "../runs/store.js";
40
45
  // instance; instead we redefine the inputs here as the tool boundary. The
41
46
  // store re-validates inside `appendRun`, so any drift between the two
42
47
  // schemas trips at the store layer rather than silently passing.
43
- const InvocationEnum = z.enum(["implement", "review", "task", "question", "brainstorm", "debug"]);
48
+ const InvocationEnum = z.enum(INVOCATION_VALUES);
44
49
  const ModeEnum = z.enum(["quick", "normal", "deep"]);
45
50
  const ModeSourceEnum = z.enum(["user", "auto"]);
46
51
  const StatusEnum = z.enum(["in_flight", "completed", "aborted"]);
@@ -107,11 +112,12 @@ async function handler(input) {
107
112
  }
108
113
  export const recordRunToolDef = {
109
114
  name: "record_run",
110
- description: "Append one RunRecord to .squad/runs.jsonl. Single-writer contract: only the squad skill " +
111
- "(Phase 1 in_flight + Phase 10 completed/aborted) and the debug skill (Phase A in_flight + " +
112
- "Phase C completed/aborted) should call this. Validates against the RunRecord schema_version:1 " +
113
- "and enforces MAX_RECORD_BYTES (4000) via RECORD_TOO_LARGE on overflow. Caller is responsible " +
114
- "for matching in_flight↔terminal rows by id. File mode is 0o600 (user-only) on first create.",
115
+ description: "Append one RunRecord to .squad/runs.jsonl. Single-writer contract: only the lifecycle-owning " +
116
+ "skills should call this — squad (Phase 1 + Phase 10), debug (Phase A + Phase C), question " +
117
+ "(Phase 1.5 + Phase 3.5), brainstorm (Step 1.5 + Step 5.5). Validates against the RunRecord " +
118
+ "schema_version:1 and enforces MAX_RECORD_BYTES (4000) via RECORD_TOO_LARGE on overflow. " +
119
+ "Caller is responsible for matching in_flight↔terminal rows by id. File mode is 0o600 " +
120
+ "(user-only) on first create. mode_warning.message is stripped of control chars at write time.",
115
121
  schema,
116
122
  handler,
117
123
  };
@@ -1 +1 @@
1
- {"version":3,"file":"record-run.js","sourceRoot":"","sources":["../../src/tools/record-run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"record-run.js","sourceRoot":"","sources":["../../src/tools/record-run.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ import { scoreRubricTool } from "./score-rubric.js";
8
8
  import { readSquadConfigTool } from "./read-squad-config.js";
9
9
  import { readLearningsToolDef } from "./read-learnings.js";
10
10
  import { recordLearningToolDef } from "./record-learning.js";
11
+ import { pruneLearningsToolDef } from "./prune-learnings.js";
11
12
  import { listTasksToolDef } from "./list-tasks.js";
12
13
  import { nextTaskToolDef } from "./next-task.js";
13
14
  import { recordTasksToolDef } from "./record-tasks.js";
@@ -23,6 +24,7 @@ import { composeAdvisoryBundleTool } from "./compose-advisory-bundle.js";
23
24
  import { recordRunToolDef } from "./record-run.js";
24
25
  import { listRunsToolDef } from "./list-runs.js";
25
26
  import { isSquadError } from "../errors.js";
27
+ import { pathSafe, pathSafeDetails } from "../util/path-safety.js";
26
28
  import { logger, newRequestId } from "../observability/logger.js";
27
29
  const tools = new Map();
28
30
  export function register(def) {
@@ -40,6 +42,7 @@ export function registerTools() {
40
42
  register(readSquadConfigTool);
41
43
  register(readLearningsToolDef);
42
44
  register(recordLearningToolDef);
45
+ register(pruneLearningsToolDef);
43
46
  register(listTasksToolDef);
44
47
  register(nextTaskToolDef);
45
48
  register(recordTasksToolDef);
@@ -149,8 +152,17 @@ export async function dispatchTool(name, args) {
149
152
  duration_ms,
150
153
  error_code: err.code,
151
154
  });
155
+ // Sanitize absolute filesystem paths before the payload crosses the MCP
156
+ // dispatch boundary to the (potentially untrusted) client. The in-
157
+ // process SquadError still carries full paths for local debug; only
158
+ // this serialised copy is truncated. See path-safety.ts:pathSafe for
159
+ // the truncation shape (last 3 segments with `…/` prefix).
152
160
  return asToolErrorResponse({
153
- error: { code: err.code, message: err.message, details: err.details },
161
+ error: {
162
+ code: err.code,
163
+ message: pathSafe(err.message),
164
+ details: pathSafeDetails(err.details),
165
+ },
154
166
  });
155
167
  }
156
168
  const message = err instanceof Error ? err.message : String(err);
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Atomically rewrite a JSONL file with a new set of rows. Survives crashes
3
+ * mid-write and races with concurrent appenders that hold the same file
4
+ * lock. Concurrent READERS (which do not take the lock today by design)
5
+ * also survive — they either see the pre-rewrite file in full or the
6
+ * post-rewrite file in full, never a half-written state. The protocol
7
+ * uses POSIX rename semantics (atomic-within-filesystem).
8
+ *
9
+ * Used by:
10
+ * - `prune_learnings` (v0.11.0+) to mark entries archived/promoted in a
11
+ * full rewrite of `.squad/learnings.jsonl`.
12
+ *
13
+ * Protocol (executes inside the lock):
14
+ * 1. Read current file contents into memory (caller does this BEFORE
15
+ * calling; we receive the new rows to write).
16
+ * 2. Write new content to `<file>.tmp` with mode 0o600 (private).
17
+ * 3. Rename current `<file>` → `<file>.prev` (atomic). This is the
18
+ * rollback point — if the next step fails, the user can manually
19
+ * `mv <file>.prev <file>` to recover.
20
+ * 4. Rename `<file>.tmp` → `<file>` (atomic).
21
+ * 5. Lock released by the caller's withFileLock wrapper.
22
+ *
23
+ * On failure between steps 3 and 4 (rare — both renames are usually a
24
+ * single syscall on the same FS), the file goes missing for a moment but
25
+ * `.prev` is intact. Step 4 retries inside the lock could be added; for
26
+ * now, surface the error and let the caller decide.
27
+ *
28
+ * The function takes a `lock: false` escape hatch for tests that want to
29
+ * exercise the rename sequence without taking the cross-process lock (we
30
+ * never use it in production).
31
+ */
32
+ export interface AtomicRewriteOptions {
33
+ /** When false, skip the file-lock acquisition. Test-only. Default true. */
34
+ lock?: boolean;
35
+ }
36
+ export declare function atomicRewriteJsonl(filePath: string, rows: ReadonlyArray<object>, options?: AtomicRewriteOptions): Promise<void>;
@@ -0,0 +1,95 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import { withFileLock } from "./file-lock.js";
4
+ import { SquadError } from "../errors.js";
5
+ export async function atomicRewriteJsonl(filePath, rows, options = {}) {
6
+ const useLock = options.lock !== false;
7
+ const body = rows.map((r) => JSON.stringify(r)).join("\n") + (rows.length > 0 ? "\n" : "");
8
+ const tmpPath = `${filePath}.tmp`;
9
+ const prevPath = `${filePath}.prev`;
10
+ const performRewrite = async () => {
11
+ // Ensure the directory exists. mkdir is idempotent.
12
+ await fs.mkdir(path.dirname(filePath), { recursive: true, mode: 0o700 });
13
+ // 1. Write the new content to <file>.tmp with private mode. fh.writeFile
14
+ // truncates if the file existed (we never reuse a stale tmp).
15
+ const fh = await fs.open(tmpPath, "w", 0o600);
16
+ try {
17
+ await fh.writeFile(body, "utf8");
18
+ }
19
+ finally {
20
+ await fh.close();
21
+ }
22
+ // 2. Move the current file to <file>.prev as a rollback snapshot. If the
23
+ // source doesn't exist (first-ever write), the rename is skipped.
24
+ let prevMoved = false;
25
+ try {
26
+ await fs.rename(filePath, prevPath);
27
+ prevMoved = true;
28
+ }
29
+ catch (err) {
30
+ if (err.code !== "ENOENT")
31
+ throw err;
32
+ }
33
+ // 3. Move the new tmp into place. Atomic on POSIX same-FS rename.
34
+ // v0.11.0 cycle-2 Blocker B2 fix: on failure here, attempt to rollback
35
+ // .prev → <file> so the caller never sees a missing journal. If the
36
+ // rollback also fails, surface a SquadError with the manual recovery
37
+ // command embedded so the user can `mv .prev <file>` themselves.
38
+ try {
39
+ await fs.rename(tmpPath, filePath);
40
+ }
41
+ catch (err) {
42
+ const step3Err = err;
43
+ if (!prevMoved) {
44
+ // First-ever write — no .prev to roll back. Clean up tmp and rethrow.
45
+ try {
46
+ await fs.unlink(tmpPath);
47
+ }
48
+ catch {
49
+ /* swallow — tmp cleanup is best-effort */
50
+ }
51
+ throw step3Err;
52
+ }
53
+ // We moved source → .prev and now the second rename failed. Try to
54
+ // put .prev back so the journal isn't missing.
55
+ try {
56
+ await fs.rename(prevPath, filePath);
57
+ // Rollback succeeded. Cleanup tmp.
58
+ try {
59
+ await fs.unlink(tmpPath);
60
+ }
61
+ catch {
62
+ /* swallow */
63
+ }
64
+ throw new SquadError("ATOMIC_REWRITE_FAILED", `failed to swap new content into place (${step3Err.message}). Rollback applied: original journal restored from .prev. No data loss.`, {
65
+ step: "rename_tmp_to_file",
66
+ path: filePath,
67
+ errno: step3Err.code,
68
+ });
69
+ }
70
+ catch (rollbackErr) {
71
+ // Rollback failed too — surface manual recovery instructions.
72
+ if (rollbackErr.code === "ATOMIC_REWRITE_FAILED") {
73
+ // The error from the success-rollback branch above; bubble unchanged.
74
+ throw rollbackErr;
75
+ }
76
+ throw new SquadError("ATOMIC_REWRITE_FAILED", `failed to swap new content into place AND failed to rollback .prev → original. ` +
77
+ `To recover manually: mv ${prevPath} ${filePath}`, {
78
+ step: "rename_tmp_to_file_with_rollback_failure",
79
+ path: filePath,
80
+ prev: prevPath,
81
+ tmp: tmpPath,
82
+ primary_errno: step3Err.code,
83
+ rollback_errno: rollbackErr.code,
84
+ });
85
+ }
86
+ }
87
+ };
88
+ if (useLock) {
89
+ await withFileLock(filePath, performRewrite);
90
+ }
91
+ else {
92
+ await performRewrite();
93
+ }
94
+ }
95
+ //# sourceMappingURL=atomic-rewrite-jsonl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atomic-rewrite-jsonl.js","sourceRoot":"","sources":["../../src/util/atomic-rewrite-jsonl.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,40 @@
1
1
  export declare const MAX_BYTES = 16384;
2
+ /**
3
+ * Truncate absolute filesystem paths inside a string to their last 3 segments,
4
+ * with a `…/` prefix indicating truncation. Used by the MCP dispatch boundary
5
+ * (`src/tools/registry.ts`) to sanitise `SquadError.message` and
6
+ * `SquadError.details` before they leave the server to a (potentially
7
+ * untrusted) MCP client.
8
+ *
9
+ * Why: error messages routinely embed `workspaceRoot` or absolute file paths
10
+ * (e.g. `failed to read runs file /home/<user>/work/some-repo/.squad/runs.jsonl`).
11
+ * The full path leaks the local user's home directory and folder layout —
12
+ * useful debug context, but a sidechannel for username discovery if an MCP
13
+ * client logs or relays error payloads.
14
+ *
15
+ * The transform is purely cosmetic — the `SquadError` itself, in-process,
16
+ * still carries the full path for local debugging. Only the serialised
17
+ * payload that crosses the dispatch boundary is sanitised.
18
+ *
19
+ * Recognised path shapes (handled non-greedily so multiple paths in one
20
+ * string each truncate independently):
21
+ *
22
+ * - POSIX absolute: `/foo/bar/baz/qux/file.ts` → `…/baz/qux/file.ts`
23
+ * - Windows drive: `C:\foo\bar\baz\qux\file.ts` → `…/baz/qux/file.ts`
24
+ *
25
+ * Paths with fewer than 4 non-empty segments do not match the pattern (the
26
+ * regex requires at least two interior separators) and are returned as-is.
27
+ * Already-truncated paths (begin with `…/`) are idempotent under this
28
+ * function (lookbehind prevents re-matching).
29
+ */
30
+ export declare function pathSafe(s: string): string;
31
+ /**
32
+ * Recursively apply `pathSafe` to every string leaf in an error-details
33
+ * payload. Top-level wrapper for `SquadError.details` sanitisation at the
34
+ * dispatch boundary. Returns a deep-cloned object — the in-process error
35
+ * is not mutated.
36
+ */
37
+ export declare function pathSafeDetails(details: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
2
38
  export interface SafePathContext {
3
39
  rootRealCache: Map<string, string>;
4
40
  }
@@ -3,6 +3,82 @@ import path from "node:path";
3
3
  import { SquadError } from "../errors.js";
4
4
  import { rejectIfMalformed, realpathOrSelf } from "./path-internal.js";
5
5
  export const MAX_BYTES = 16_384;
6
+ /**
7
+ * Truncate absolute filesystem paths inside a string to their last 3 segments,
8
+ * with a `…/` prefix indicating truncation. Used by the MCP dispatch boundary
9
+ * (`src/tools/registry.ts`) to sanitise `SquadError.message` and
10
+ * `SquadError.details` before they leave the server to a (potentially
11
+ * untrusted) MCP client.
12
+ *
13
+ * Why: error messages routinely embed `workspaceRoot` or absolute file paths
14
+ * (e.g. `failed to read runs file /home/<user>/work/some-repo/.squad/runs.jsonl`).
15
+ * The full path leaks the local user's home directory and folder layout —
16
+ * useful debug context, but a sidechannel for username discovery if an MCP
17
+ * client logs or relays error payloads.
18
+ *
19
+ * The transform is purely cosmetic — the `SquadError` itself, in-process,
20
+ * still carries the full path for local debugging. Only the serialised
21
+ * payload that crosses the dispatch boundary is sanitised.
22
+ *
23
+ * Recognised path shapes (handled non-greedily so multiple paths in one
24
+ * string each truncate independently):
25
+ *
26
+ * - POSIX absolute: `/foo/bar/baz/qux/file.ts` → `…/baz/qux/file.ts`
27
+ * - Windows drive: `C:\foo\bar\baz\qux\file.ts` → `…/baz/qux/file.ts`
28
+ *
29
+ * Paths with fewer than 4 non-empty segments do not match the pattern (the
30
+ * regex requires at least two interior separators) and are returned as-is.
31
+ * Already-truncated paths (begin with `…/`) are idempotent under this
32
+ * function (lookbehind prevents re-matching).
33
+ */
34
+ export function pathSafe(s) {
35
+ if (typeof s !== "string" || s.length === 0)
36
+ return s;
37
+ // POSIX absolute path: starts with /, captures everything until a whitespace,
38
+ // quote, or message-formatting boundary. The `(?<!…)` lookbehind prevents
39
+ // re-matching after an already-truncated `…/` prefix (idempotency).
40
+ const posix = /(?<!…)\/(?:[A-Za-z0-9._-][^\s'"`<>:,)\]]*\/)+[A-Za-z0-9._-][^\s'"`<>:,)\]]*/g;
41
+ // Windows drive path: drive letter + colon + backslash, captured similarly.
42
+ // Note: the Windows segment char-class adds a space (`[A-Za-z0-9._ -]` vs
43
+ // POSIX's `[A-Za-z0-9._-]`) because Windows directory names commonly contain
44
+ // spaces (`C:\Program Files\...`). POSIX paths conventionally do not, so
45
+ // the asymmetry is intentional, not a copy-paste oversight.
46
+ const win = /[A-Za-z]:\\(?:[A-Za-z0-9._ -][^\s'"`<>:,)\]]*\\)+[A-Za-z0-9._ -][^\s'"`<>:,)\]]*/g;
47
+ const truncate = (match, sep) => {
48
+ // Drop empty leading segment from absolute paths (leading `/` gives `""`).
49
+ const segments = match.split(sep).filter((p) => p.length > 0);
50
+ if (segments.length <= 3)
51
+ return match;
52
+ return "…/" + segments.slice(-3).join("/");
53
+ };
54
+ return s.replace(posix, (m) => truncate(m, "/")).replace(win, (m) => truncate(m, "\\"));
55
+ }
56
+ /**
57
+ * Recursively apply `pathSafe` to every string leaf in an error-details
58
+ * payload. Top-level wrapper for `SquadError.details` sanitisation at the
59
+ * dispatch boundary. Returns a deep-cloned object — the in-process error
60
+ * is not mutated.
61
+ */
62
+ export function pathSafeDetails(details) {
63
+ if (details === undefined)
64
+ return undefined;
65
+ const out = {};
66
+ for (const [k, v] of Object.entries(details)) {
67
+ if (typeof v === "string") {
68
+ out[k] = pathSafe(v);
69
+ }
70
+ else if (Array.isArray(v)) {
71
+ out[k] = v.map((item) => (typeof item === "string" ? pathSafe(item) : item));
72
+ }
73
+ else if (v !== null && typeof v === "object") {
74
+ out[k] = pathSafeDetails(v);
75
+ }
76
+ else {
77
+ out[k] = v;
78
+ }
79
+ }
80
+ return out;
81
+ }
6
82
  export function createSafePathContext() {
7
83
  return { rootRealCache: new Map() };
8
84
  }