@wrongstack/sdd 0.296.2 → 0.296.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"graph-split.d.ts","sourceRoot":"","sources":["../src/graph-split.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CACvD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,cAAc,EAAE,EAC1B,OAAO,GAAE,qBAA0B,GAClC,MAAM,EAAE,CAwCV"}
1
+ {"version":3,"file":"graph-split.d.ts","sourceRoot":"","sources":["../src/graph-split.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CACvD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,cAAc,EAAE,EAC1B,OAAO,GAAE,qBAA0B,GAClC,MAAM,EAAE,CAmCV"}
package/dist/index.d.ts CHANGED
@@ -21,7 +21,7 @@ export { AutoExecutor, createAutoExecutor, type AutoExecutorOptions, type TaskEx
21
21
  export { SddTaskDecomposer, type SddTaskDecomposerOptions, type TaskBatch, } from './sdd-task-decomposer.js';
22
22
  export { SddParallelRun, type SddParallelRunOptions, type SddProgress, type WaveResult, type RunResult, type SddSubtaskSpec, type SddSupervisorVerdict, } from './sdd-parallel-run.js';
23
23
  export { SddSupervisor, type SddSupervisorOptions } from './sdd-supervisor.js';
24
- export { makeAcceptanceCriteriaVerifier, makeCommandVerifier, makeCompositeVerifier, type AcceptanceCriteriaVerifierOptions, type CommandVerifierOptions, type SddVerifyTask, } from './verify-task.js';
24
+ export { makeAcceptanceCriteriaVerifier, makeCommandVerifier, makeCompositeVerifier, tokenizeCommand, type AcceptanceCriteriaVerifierOptions, type CommandVerifierOptions, type SddVerifyTask, } from './verify-task.js';
25
25
  export { makeLlmSubtaskGenerator, makePlanningDecomposer, type PlanningDecomposer, type PlanningDecomposerOptions, type SubtaskGeneratorOptions, } from './decompose-task.js';
26
26
  export { splitGraphNode, type SplitGraphNodeOptions } from './graph-split.js';
27
27
  export { assessTaskNodeAtomicity, decomposeNonAtomicTasks, type DecompositionProposal, type PlanDecomposeOptions, type PlanDecomposeResult, } from './plan-decompose.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1841,7 +1841,8 @@ var AISpecBuilder = class {
1841
1841
  const { atomicWrite: atomicWrite4 } = await import("@wrongstack/core/utils");
1842
1842
  await fsp6.mkdir(path6.dirname(this.sessionPath), { recursive: true });
1843
1843
  await atomicWrite4(this.sessionPath, JSON.stringify(this.session, null, 2));
1844
- } catch {
1844
+ } catch (error) {
1845
+ console.warn(JSON.stringify({ level: "warn", event: "sdd.persist.failed", message: String(error), timestamp: Date.now() }));
1845
1846
  }
1846
1847
  }
1847
1848
  /** Load session state from disk. Returns true if a session was loaded. */
@@ -2003,11 +2004,15 @@ var AISpecBuilder = class {
2003
2004
  this.autoSave();
2004
2005
  }
2005
2006
  /**
2006
- * Set the task graph ID for this session.
2007
+ * Set the task graph ID for this session. Awaits the save so a caller that
2008
+ * immediately follows with `await saveSession()` cannot end up with the
2009
+ * awaited write committing first and the fire-and-forget rename reverting
2010
+ * the persisted `taskGraphId` to its pre-set value. Same race window that
2011
+ * broke `setLastAgentText`/`setLastRunId` on the resume test.
2007
2012
  */
2008
- setTaskGraphId(graphId) {
2013
+ async setTaskGraphId(graphId) {
2009
2014
  this.session.taskGraphId = graphId;
2010
- this.autoSave();
2015
+ await this.saveSession();
2011
2016
  }
2012
2017
  /**
2013
2018
  * Get the task graph ID for this session.
@@ -2015,20 +2020,27 @@ var AISpecBuilder = class {
2015
2020
  getTaskGraphId() {
2016
2021
  return this.session.taskGraphId;
2017
2022
  }
2018
- /** Persist the last agent utterance so resume can rehydrate the UI + Q/A pairing. */
2019
- setLastAgentText(text) {
2023
+ /**
2024
+ * Persist the last agent utterance so resume can rehydrate the UI + Q/A
2025
+ * pairing. Awaits the save so the next mutation in the call chain (e.g.
2026
+ * `setLastRunId`) cannot fire a concurrent save that overwrites this one
2027
+ * with a stale snapshot — the fire-and-forget `autoSave()` pattern leaves
2028
+ * a race window where an earlier queued save may commit its rename after
2029
+ * a later one, silently reverting the persisted state.
2030
+ */
2031
+ async setLastAgentText(text) {
2020
2032
  this.session.lastAgentText = text;
2021
2033
  this.session.updatedAt = Date.now();
2022
- this.autoSave();
2034
+ await this.saveSession();
2023
2035
  }
2024
2036
  getLastAgentText() {
2025
2037
  return this.session.lastAgentText;
2026
2038
  }
2027
- /** Record a run kicked off from this interview (board deep-link after restart). */
2028
- setLastRunId(runId) {
2039
+ /** Record a run kicked off from this interview (board deep-link after restart). See {@link setLastAgentText} for the awaited-save rationale. */
2040
+ async setLastRunId(runId) {
2029
2041
  this.session.lastRunId = runId;
2030
2042
  this.session.updatedAt = Date.now();
2031
- this.autoSave();
2043
+ await this.saveSession();
2032
2044
  }
2033
2045
  getLastRunId() {
2034
2046
  return this.session.lastRunId;
@@ -2270,13 +2282,13 @@ var SddInterviewDriver = class {
2270
2282
  this.resumedFromDisk = false;
2271
2283
  }
2272
2284
  setLastAgentText(text) {
2273
- this.builder.setLastAgentText(text);
2285
+ return this.builder.setLastAgentText(text);
2274
2286
  }
2275
2287
  getLastAgentText() {
2276
2288
  return this.builder.getLastAgentText();
2277
2289
  }
2278
2290
  setLastRunId(runId) {
2279
- this.builder.setLastRunId(runId);
2291
+ return this.builder.setLastRunId(runId);
2280
2292
  }
2281
2293
  getLastRunId() {
2282
2294
  return this.builder.getLastRunId();
@@ -2368,7 +2380,7 @@ var SddInterviewDriver = class {
2368
2380
  this.tracker = tracker;
2369
2381
  this.graph = graph;
2370
2382
  await this.persistGraph(graph);
2371
- this.builder.setTaskGraphId(graph.id);
2383
+ await this.builder.setTaskGraphId(graph.id);
2372
2384
  await this.builder.saveSession();
2373
2385
  return graph;
2374
2386
  }
@@ -2481,7 +2493,7 @@ var SddInterviewDriver = class {
2481
2493
  }
2482
2494
  }
2483
2495
  await this.persistGraph(graph);
2484
- this.builder.setTaskGraphId(graph.id);
2496
+ await this.builder.setTaskGraphId(graph.id);
2485
2497
  await this.builder.saveSession();
2486
2498
  return graph.id;
2487
2499
  }
@@ -2528,8 +2540,7 @@ function splitGraphNode(tracker, taskId, subtasks, options = {}) {
2528
2540
  const dependents = tracker.getDependents(taskId);
2529
2541
  const leafIds = subtasks.map((s) => {
2530
2542
  const criterion = s.successCriterion?.trim();
2531
- const verificationCommand = criterion ? extractVerificationCommand([criterion]) : void 0;
2532
- const description = criterion && !verificationCommand ? `${s.description}
2543
+ const description = criterion ? `${s.description}
2533
2544
 
2534
2545
  **Acceptance Criteria:**
2535
2546
  - ${criterion}` : s.description;
@@ -2539,8 +2550,7 @@ function splitGraphNode(tracker, taskId, subtasks, options = {}) {
2539
2550
  type: s.type ?? node.type,
2540
2551
  priority: s.priority ?? node.priority,
2541
2552
  status: "pending",
2542
- parentId: taskId,
2543
- ...verificationCommand ? { metadata: { verificationCommand } } : {}
2553
+ parentId: taskId
2544
2554
  }).id;
2545
2555
  });
2546
2556
  for (const leaf of leafIds) {
@@ -4768,8 +4778,70 @@ Supervisor rescues already used: ${attempts}`,
4768
4778
 
4769
4779
  // src/verify-task.ts
4770
4780
  import { spawn } from "node:child_process";
4771
- function verificationShell(platform) {
4772
- return platform === "win32" ? ["cmd", "/d", "/c"] : ["sh", "-c"];
4781
+ function tokenizeCommand(command) {
4782
+ const trimmed = command.trim();
4783
+ if (!trimmed) return void 0;
4784
+ const argv = [];
4785
+ let current = "";
4786
+ let inSingle = false;
4787
+ let inDouble = false;
4788
+ let hasToken = false;
4789
+ for (let i = 0; i < trimmed.length; i++) {
4790
+ const ch = trimmed[i];
4791
+ if (inSingle) {
4792
+ if (ch === "'") {
4793
+ inSingle = false;
4794
+ } else {
4795
+ current += ch;
4796
+ }
4797
+ continue;
4798
+ }
4799
+ if (inDouble) {
4800
+ if (ch === '"') {
4801
+ inDouble = false;
4802
+ } else if (ch === "\\" && i + 1 < trimmed.length) {
4803
+ const next = trimmed[i + 1];
4804
+ if (next === '"' || next === "\\" || next === "$" || next === "`") {
4805
+ current += next;
4806
+ i++;
4807
+ } else {
4808
+ current += ch;
4809
+ }
4810
+ } else {
4811
+ current += ch;
4812
+ }
4813
+ continue;
4814
+ }
4815
+ if (ch === "'") {
4816
+ inSingle = true;
4817
+ hasToken = true;
4818
+ continue;
4819
+ }
4820
+ if (ch === '"') {
4821
+ inDouble = true;
4822
+ hasToken = true;
4823
+ continue;
4824
+ }
4825
+ if (ch === "\\" && i + 1 < trimmed.length) {
4826
+ current += trimmed[i + 1];
4827
+ i++;
4828
+ hasToken = true;
4829
+ continue;
4830
+ }
4831
+ if (ch === " " || ch === " ") {
4832
+ if (hasToken) {
4833
+ argv.push(current);
4834
+ current = "";
4835
+ hasToken = false;
4836
+ }
4837
+ continue;
4838
+ }
4839
+ current += ch;
4840
+ hasToken = true;
4841
+ }
4842
+ if (inSingle || inDouble) return void 0;
4843
+ if (hasToken) argv.push(current);
4844
+ return argv.length > 0 ? argv : void 0;
4773
4845
  }
4774
4846
  function makeCompositeVerifier(parts) {
4775
4847
  return async function verifyTask(info) {
@@ -4820,11 +4892,15 @@ function makeCommandVerifier(options = {}) {
4820
4892
  const metadataKey = options.metadataKey ?? "verificationCommand";
4821
4893
  const timeoutMs = options.timeoutMs ?? 18e4;
4822
4894
  return async function verifyTask(info) {
4823
- const cmd = info.task.metadata?.[metadataKey];
4824
- if (typeof cmd !== "string" || !cmd.trim()) return { ok: true };
4895
+ const rawCommand = info.task.metadata?.[metadataKey];
4896
+ if (typeof rawCommand !== "string" || !rawCommand.trim()) return { ok: true };
4897
+ const argv = tokenizeCommand(rawCommand);
4898
+ if (!argv || argv.length === 0) {
4899
+ return { ok: false, reason: `verification command is malformed: ${rawCommand}` };
4900
+ }
4901
+ const [executable, ...args] = argv;
4825
4902
  return await new Promise((resolve) => {
4826
- const [shell, ...shellArgs] = verificationShell(process.platform);
4827
- const child = spawn(shell, [...shellArgs, cmd], {
4903
+ const child = spawn(executable, args, {
4828
4904
  cwd: info.cwd,
4829
4905
  shell: false,
4830
4906
  windowsHide: true,
@@ -4834,13 +4910,13 @@ function makeCommandVerifier(options = {}) {
4834
4910
  const timer = setTimeout(() => {
4835
4911
  timedOut = true;
4836
4912
  child.kill();
4837
- resolve({ ok: false, reason: `verification timed out: ${cmd}` });
4913
+ resolve({ ok: false, reason: `verification timed out: ${rawCommand}` });
4838
4914
  }, timeoutMs);
4839
4915
  child.on("exit", (code) => {
4840
4916
  clearTimeout(timer);
4841
4917
  if (timedOut) return;
4842
4918
  resolve(
4843
- code === 0 ? { ok: true } : { ok: false, reason: `verification failed (exit ${code}): ${cmd}` }
4919
+ code === 0 ? { ok: true } : { ok: false, reason: `verification failed (exit ${code}): ${rawCommand}` }
4844
4920
  );
4845
4921
  });
4846
4922
  child.on("error", (err) => {
@@ -5178,6 +5254,7 @@ export {
5178
5254
  shortIdMap,
5179
5255
  splitGraphNode,
5180
5256
  startSddRun,
5181
- templateToMarkdown
5257
+ templateToMarkdown,
5258
+ tokenizeCommand
5182
5259
  };
5183
5260
  //# sourceMappingURL=index.js.map