@wrongstack/core 0.68.0 → 0.77.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 (59) hide show
  1. package/dist/{agent-bridge-D-j6OOBT.d.ts → agent-bridge-EWdqs8v6.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-DRZ9-NnR.d.ts → agent-subagent-runner-D8qW8OSC.d.ts} +13 -5
  3. package/dist/{config--86aHSln.d.ts → config-Dy0CK_o6.d.ts} +44 -1
  4. package/dist/coordination/index.d.ts +10 -10
  5. package/dist/coordination/index.js +74 -10
  6. package/dist/coordination/index.js.map +1 -1
  7. package/dist/defaults/index.d.ts +17 -17
  8. package/dist/defaults/index.js +160 -67
  9. package/dist/defaults/index.js.map +1 -1
  10. package/dist/{events-CIplI98R.d.ts → events-CYaoLN5_.d.ts} +45 -0
  11. package/dist/execution/index.d.ts +9 -9
  12. package/dist/execution/index.js +4 -4
  13. package/dist/execution/index.js.map +1 -1
  14. package/dist/extension/index.d.ts +5 -5
  15. package/dist/{index-b5uhfTSl.d.ts → index-DIxjTOga.d.ts} +6 -6
  16. package/dist/{index-DKUvyTvV.d.ts → index-Dsda0uCn.d.ts} +4 -4
  17. package/dist/index.d.ts +108 -33
  18. package/dist/index.js +388 -58
  19. package/dist/index.js.map +1 -1
  20. package/dist/infrastructure/index.d.ts +5 -5
  21. package/dist/infrastructure/index.js +16 -2
  22. package/dist/infrastructure/index.js.map +1 -1
  23. package/dist/kernel/index.d.ts +7 -7
  24. package/dist/kernel/index.js.map +1 -1
  25. package/dist/{logger-bOzkF5LL.d.ts → logger-BppKxDqZ.d.ts} +9 -0
  26. package/dist/{mcp-servers-DwoNBf6r.d.ts → mcp-servers-T0O6UN_w.d.ts} +1 -1
  27. package/dist/{mode-CV077NjV.d.ts → mode-BO4SEUIv.d.ts} +7 -0
  28. package/dist/models/index.d.ts +1 -1
  29. package/dist/models/index.js +18 -9
  30. package/dist/models/index.js.map +1 -1
  31. package/dist/{multi-agent-coordinator-CWnH-CiX.d.ts → multi-agent-coordinator-DpbG3wiy.d.ts} +1 -1
  32. package/dist/{null-fleet-bus-CuN0ObJr.d.ts → null-fleet-bus-u5ys3lW_.d.ts} +28 -9
  33. package/dist/observability/index.d.ts +1 -1
  34. package/dist/{parallel-eternal-engine-0UwotoSx.d.ts → parallel-eternal-engine-Dn0P8Pbj.d.ts} +3 -3
  35. package/dist/{path-resolver-DVkEcIw8.d.ts → path-resolver-B32v2JIq.d.ts} +1 -1
  36. package/dist/{permission-C1A5whY5.d.ts → permission-V5BLOrY6.d.ts} +0 -4
  37. package/dist/{permission-policy-B2dK-T5N.d.ts → permission-policy-CBVx-d-8.d.ts} +1 -5
  38. package/dist/{plan-templates-Bprrzhbu.d.ts → plan-templates-BcUwLlMQ.d.ts} +8 -3
  39. package/dist/{provider-runner-mXvXGSIw.d.ts → provider-runner-CSi_7l0h.d.ts} +1 -1
  40. package/dist/sdd/index.d.ts +6 -6
  41. package/dist/sdd/index.js +3 -3
  42. package/dist/sdd/index.js.map +1 -1
  43. package/dist/security/index.d.ts +2 -2
  44. package/dist/security/index.js +0 -8
  45. package/dist/security/index.js.map +1 -1
  46. package/dist/skills/index.js +1 -0
  47. package/dist/skills/index.js.map +1 -1
  48. package/dist/storage/index.d.ts +4 -4
  49. package/dist/storage/index.js +48 -8
  50. package/dist/storage/index.js.map +1 -1
  51. package/dist/{system-prompt-b61lOd49.d.ts → system-prompt-CA11g6Jo.d.ts} +1 -1
  52. package/dist/types/index.d.ts +14 -14
  53. package/dist/types/index.js +35 -12
  54. package/dist/types/index.js.map +1 -1
  55. package/dist/utils/index.d.ts +2 -2
  56. package/dist/utils/index.js +14 -3
  57. package/dist/utils/index.js.map +1 -1
  58. package/dist/{wstack-paths-eMXnY1_X.d.ts → wstack-paths-D7evAFWM.d.ts} +8 -1
  59. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { readFile, readdir, stat, mkdir } from 'fs/promises';
5
5
  import * as path6 from 'path';
6
6
  import { join, extname, relative, isAbsolute, resolve, sep } from 'path';
7
7
  import * as fs2 from 'fs';
8
- import * as os6 from 'os';
8
+ import * as os7 from 'os';
9
9
  import { execFile, spawn } from 'child_process';
10
10
  import { promisify } from 'util';
11
11
  import { EventEmitter } from 'events';
@@ -1404,11 +1404,13 @@ var DefaultLogger = class _DefaultLogger {
1404
1404
  file;
1405
1405
  bindings;
1406
1406
  pretty;
1407
+ stderr;
1407
1408
  constructor(opts = {}) {
1408
1409
  this.level = opts.level ?? process.env.WRONGSTACK_LOG_LEVEL ?? "info";
1409
1410
  this.file = opts.file;
1410
1411
  this.bindings = opts.bindings ?? {};
1411
1412
  this.pretty = opts.pretty ?? true;
1413
+ this.stderr = opts.stderr !== false;
1412
1414
  if (this.file) {
1413
1415
  try {
1414
1416
  fs2.mkdirSync(path6.dirname(this.file), { recursive: true });
@@ -1436,6 +1438,7 @@ var DefaultLogger = class _DefaultLogger {
1436
1438
  level: this.level,
1437
1439
  file: this.file,
1438
1440
  pretty: this.pretty,
1441
+ stderr: this.stderr,
1439
1442
  bindings: { ...this.bindings, ...bindings }
1440
1443
  });
1441
1444
  }
@@ -1455,6 +1458,7 @@ var DefaultLogger = class _DefaultLogger {
1455
1458
  } catch {
1456
1459
  }
1457
1460
  }
1461
+ if (!this.stderr) return;
1458
1462
  if (r <= LEVEL_RANK.warn || this.level === "debug" || this.level === "trace") {
1459
1463
  const head = `${color.dim(ts)} ${COLORS[level](level.toUpperCase().padEnd(5))} ${msg}`;
1460
1464
  if (ctx !== void 0) {
@@ -2000,7 +2004,11 @@ var PROJECT_MARKERS = [
2000
2004
  "go.mod",
2001
2005
  "Cargo.toml",
2002
2006
  "pyproject.toml",
2003
- ".wrongstack"
2007
+ // Use AGENTS.md, not the bare .wrongstack directory. A bare .wrongstack/
2008
+ // directory can be the global config directory (~/.wrongstack), which is
2009
+ // NOT a project marker. Only .wrongstack/AGENTS.md signals a real
2010
+ // WrongStack project.
2011
+ ".wrongstack/AGENTS.md"
2004
2012
  ];
2005
2013
  var DefaultPathResolver = class {
2006
2014
  projectRoot;
@@ -2012,7 +2020,12 @@ var DefaultPathResolver = class {
2012
2020
  detectProjectRoot(start) {
2013
2021
  let dir = path6.resolve(start);
2014
2022
  const root = path6.parse(dir).root;
2023
+ const home = path6.resolve(os7.homedir());
2024
+ const startPath = path6.resolve(start);
2015
2025
  while (dir !== root) {
2026
+ if (dir === home && dir !== startPath) {
2027
+ break;
2028
+ }
2016
2029
  for (const marker of PROJECT_MARKERS) {
2017
2030
  try {
2018
2031
  fs2.accessSync(path6.join(dir, marker));
@@ -2024,7 +2037,7 @@ var DefaultPathResolver = class {
2024
2037
  if (parent === dir) break;
2025
2038
  dir = parent;
2026
2039
  }
2027
- return path6.resolve(start);
2040
+ return startPath;
2028
2041
  }
2029
2042
  resolve(input) {
2030
2043
  const abs = path6.isAbsolute(input) ? input : path6.resolve(this.cwd, input);
@@ -2677,7 +2690,8 @@ When reviewing code:
2677
2690
  - Verify test coverage for critical paths
2678
2691
  - Ensure naming conventions are followed`,
2679
2692
  tags: ["review", "quality", "security"],
2680
- toolPreferences: ["read", "grep", "git", "diff", "test"]
2693
+ toolPreferences: ["read", "grep", "git", "diff", "test"],
2694
+ suggestedSkills: ["bug-hunter", "security-scanner", "typescript-strict", "testing"]
2681
2695
  },
2682
2696
  {
2683
2697
  id: "code-auditor",
@@ -2694,7 +2708,8 @@ When auditing code for security:
2694
2708
  - Assess input validation and output encoding
2695
2709
  - Look for timing attacks and information leakage`,
2696
2710
  tags: ["security", "audit", "compliance"],
2697
- toolPreferences: ["grep", "read", "audit", "bash"]
2711
+ toolPreferences: ["grep", "read", "audit", "bash"],
2712
+ suggestedSkills: ["security-scanner", "bug-hunter", "audit-log"]
2698
2713
  },
2699
2714
  {
2700
2715
  id: "architect",
@@ -2712,7 +2727,8 @@ When designing or reviewing architecture:
2712
2727
  - Assess API design and contract stability
2713
2728
  - Consider operational aspects (monitoring, logging, deployment)`,
2714
2729
  tags: ["architecture", "design", "scalability"],
2715
- toolPreferences: ["read", "glob", "tree", "diff"]
2730
+ toolPreferences: ["read", "glob", "tree", "diff"],
2731
+ suggestedSkills: ["api-design", "refactor-planner", "node-modern", "docker-deploy"]
2716
2732
  },
2717
2733
  {
2718
2734
  id: "debugger",
@@ -2730,7 +2746,8 @@ When investigating bugs:
2730
2746
  - Use binary search to isolate the root cause
2731
2747
  - Verify fixes with tests before considering done`,
2732
2748
  tags: ["debug", "investigation", "error-resolution"],
2733
- toolPreferences: ["read", "grep", "bash", "logs", "test"]
2749
+ toolPreferences: ["read", "grep", "bash", "logs", "test"],
2750
+ suggestedSkills: ["bug-hunter", "audit-log", "observability"]
2734
2751
  },
2735
2752
  {
2736
2753
  id: "tester",
@@ -2748,7 +2765,8 @@ When testing or writing tests:
2748
2765
  - Check for integration test gaps
2749
2766
  - Verify test isolation and cleanup`,
2750
2767
  tags: ["testing", "qa", "quality"],
2751
- toolPreferences: ["read", "grep", "test", "bash"]
2768
+ toolPreferences: ["read", "grep", "test", "bash"],
2769
+ suggestedSkills: ["testing", "bug-hunter", "typescript-strict"]
2752
2770
  },
2753
2771
  {
2754
2772
  id: "devops",
@@ -2766,7 +2784,8 @@ When working on infrastructure:
2766
2784
  - Assess secrets management
2767
2785
  - Check for resource limits and quotas`,
2768
2786
  tags: ["devops", "infrastructure", "operations"],
2769
- toolPreferences: ["read", "bash", "grep", "logs", "git"]
2787
+ toolPreferences: ["read", "bash", "grep", "logs", "git"],
2788
+ suggestedSkills: ["docker-deploy", "observability", "security-scanner"]
2770
2789
  },
2771
2790
  {
2772
2791
  id: "refactorer",
@@ -2784,7 +2803,8 @@ When refactoring code:
2784
2803
  - Don't mix formatting changes with logic changes
2785
2804
  - Keep performance in mind \u2014 don't regress`,
2786
2805
  tags: ["refactor", "modernization", "improvement"],
2787
- toolPreferences: ["read", "edit", "test", "git", "grep"]
2806
+ toolPreferences: ["read", "edit", "test", "git", "grep"],
2807
+ suggestedSkills: ["refactor-planner", "typescript-strict", "node-modern", "testing"]
2788
2808
  },
2789
2809
  {
2790
2810
  id: "brief",
@@ -2814,7 +2834,8 @@ Get to the point \u2014 read files, run commands, make changes.
2814
2834
  - One-liner sufficient? One liner.
2815
2835
  - Max 3 sentences per paragraph.`,
2816
2836
  tags: ["fast", "concise", "direct"],
2817
- toolPreferences: ["read", "edit", "bash"]
2837
+ toolPreferences: ["read", "edit", "bash"],
2838
+ suggestedSkills: []
2818
2839
  },
2819
2840
  {
2820
2841
  id: "teach",
@@ -2879,7 +2900,8 @@ You follow these principles, but always with explanation:
2879
2900
 
2880
2901
  Remember: your job is to make the user a better developer, not just to complete tasks faster.`,
2881
2902
  tags: ["teaching", "mentor", "learning"],
2882
- toolPreferences: ["read", "edit", "explain"]
2903
+ toolPreferences: ["read", "edit", "explain"],
2904
+ suggestedSkills: ["prompt-engineering", "skill-creator", "node-modern", "typescript-strict"]
2883
2905
  }
2884
2906
  ];
2885
2907
 
@@ -3512,7 +3534,7 @@ ${errorDetails}`,
3512
3534
  const decision = await this.opts.permissionPolicy.evaluate(tool, use.input, ctx);
3513
3535
  let effectivePermission = decision.permission;
3514
3536
  const policy = this.opts.permissionPolicy;
3515
- const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true || policy.getForceAllYolo?.() === true;
3537
+ const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true;
3516
3538
  if (toolDangerousCaps.length > 0 && effectivePermission === "auto" && !yolo) {
3517
3539
  effectivePermission = "confirm";
3518
3540
  }
@@ -4517,11 +4539,20 @@ function unifiedDiff(oldText, newText, opts = {}) {
4517
4539
  function projectHash(absRoot) {
4518
4540
  return createHash("sha256").update(path6.resolve(absRoot)).digest("hex").slice(0, 12);
4519
4541
  }
4542
+ function projectSlug(absRoot) {
4543
+ const base = slugify(path6.basename(absRoot));
4544
+ const hash = createHash("sha256").update(path6.resolve(absRoot)).digest("hex").slice(0, 6);
4545
+ return `${base}-${hash}`;
4546
+ }
4547
+ function slugify(name) {
4548
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "project";
4549
+ }
4520
4550
  function resolveWstackPaths(opts) {
4521
- const home = opts.userHome ?? os6.homedir();
4551
+ const home = opts.userHome ?? os7.homedir();
4522
4552
  const globalRoot = opts.globalRoot ?? path6.join(home, ".wrongstack");
4523
4553
  const hash = projectHash(opts.projectRoot);
4524
- const projectDir = path6.join(globalRoot, "projects", hash);
4554
+ const slug = projectSlug(opts.projectRoot);
4555
+ const projectDir = path6.join(globalRoot, "projects", slug);
4525
4556
  return {
4526
4557
  globalRoot,
4527
4558
  configDir: globalRoot,
@@ -4546,6 +4577,7 @@ function resolveWstackPaths(opts) {
4546
4577
  inProjectSkills: path6.join(opts.projectRoot, ".wrongstack", "skills"),
4547
4578
  inProjectWorktrees: path6.join(opts.projectRoot, ".wrongstack", "worktrees"),
4548
4579
  projectHash: hash,
4580
+ projectSlug: slug,
4549
4581
  projectGoal: path6.join(projectDir, "goal.json"),
4550
4582
  projectSpecs: path6.join(projectDir, "specs"),
4551
4583
  projectTaskGraphs: path6.join(projectDir, "task-graphs"),
@@ -4654,7 +4686,8 @@ function isGlob(p) {
4654
4686
  return false;
4655
4687
  }
4656
4688
  function globToRegex(pat) {
4657
- let i = 0, re = "^";
4689
+ let i = 0;
4690
+ let re = "^";
4658
4691
  while (i < pat.length) {
4659
4692
  const c = pat[i];
4660
4693
  if (c === "*") {
@@ -4867,6 +4900,16 @@ function mergeCustomModelDefs(providerCustomModels, configModels) {
4867
4900
 
4868
4901
  // src/storage/session-store.ts
4869
4902
  init_atomic_write();
4903
+ function sanitizeModel(model) {
4904
+ return model.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
4905
+ }
4906
+ function generateSessionId(startedAt, model) {
4907
+ const date = startedAt.slice(0, 10);
4908
+ const time = startedAt.slice(11, 19).replace(/:/g, "-");
4909
+ const suffix = randomBytes(2).toString("hex");
4910
+ const modelPart = model ? `_${sanitizeModel(model)}` : "";
4911
+ return `${date}/${time}Z${modelPart}_${suffix}`;
4912
+ }
4870
4913
  var DefaultSessionStore = class {
4871
4914
  dir;
4872
4915
  events;
@@ -4880,15 +4923,21 @@ var DefaultSessionStore = class {
4880
4923
  sessionPath(id, ext) {
4881
4924
  return path6.join(this.dir, `${id}${ext}`);
4882
4925
  }
4883
- async ensureShardDir(_id) {
4884
- await ensureDir(this.dir);
4885
- return this.dir;
4926
+ /**
4927
+ * Ensure the directory implied by the session ID exists. When the ID
4928
+ * contains a date prefix like `2026-06-06/...`, this creates the date
4929
+ * subdirectory so sessions group naturally by day.
4930
+ */
4931
+ async ensureShardDir(id) {
4932
+ const dirPath = path6.dirname(path6.join(this.dir, id));
4933
+ await ensureDir(dirPath);
4934
+ return dirPath;
4886
4935
  }
4887
4936
  async create(meta) {
4888
4937
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
4889
- const id = meta.id ?? `${startedAt.replace(/[:.]/g, "-")}-${randomBytes(2).toString("hex")}`;
4938
+ const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt, meta.model ?? meta.provider);
4890
4939
  const shardDir = await this.ensureShardDir(id);
4891
- const file = path6.join(shardDir, `${id}.jsonl`);
4940
+ const file = path6.join(shardDir, `${path6.basename(id)}.jsonl`);
4892
4941
  let handle;
4893
4942
  try {
4894
4943
  handle = await fsp3.open(file, "a", 384);
@@ -5922,8 +5971,17 @@ var BEHAVIOR_DEFAULTS = {
5922
5971
  modelsRegistry: true,
5923
5972
  skills: true
5924
5973
  },
5974
+ indexing: {
5975
+ onSessionStart: true,
5976
+ onEdit: true,
5977
+ watchExternal: true,
5978
+ debounceMs: 400
5979
+ },
5925
5980
  session: { ...DEFAULT_SESSION_LOGGING_CONFIG }
5926
5981
  };
5982
+ function envBool(v) {
5983
+ return !/^(0|false|no|off)$/i.test(v.trim());
5984
+ }
5927
5985
  var ENV_MAP = {
5928
5986
  WRONGSTACK_PROVIDER: (c, v) => {
5929
5987
  c.provider = v;
@@ -5948,8 +6006,23 @@ var ENV_MAP = {
5948
6006
  WRONGSTACK_LOG_LEVEL: (c, v) => {
5949
6007
  if (!c.log) c.log = { level: "info" };
5950
6008
  c.log.level = v;
6009
+ },
6010
+ WRONGSTACK_INDEX_ON_START: (c, v) => {
6011
+ c.indexing = { ...defaultIndexing, ...c.indexing, onSessionStart: envBool(v) };
6012
+ },
6013
+ WRONGSTACK_INDEX_ON_EDIT: (c, v) => {
6014
+ c.indexing = { ...defaultIndexing, ...c.indexing, onEdit: envBool(v) };
6015
+ },
6016
+ WRONGSTACK_INDEX_WATCH: (c, v) => {
6017
+ c.indexing = { ...defaultIndexing, ...c.indexing, watchExternal: envBool(v) };
5951
6018
  }
5952
6019
  };
6020
+ var defaultIndexing = {
6021
+ onSessionStart: true,
6022
+ onEdit: true,
6023
+ watchExternal: true,
6024
+ debounceMs: 400
6025
+ };
5953
6026
  function isPrimitiveArray(a) {
5954
6027
  return a.every((v) => v === null || typeof v !== "object");
5955
6028
  }
@@ -6210,7 +6283,7 @@ var RecoveryLock = class {
6210
6283
  constructor(opts) {
6211
6284
  this.file = path6.join(opts.dir, LOCK_FILE);
6212
6285
  this.pid = opts.pid ?? process.pid;
6213
- this.hostname = opts.hostname ?? os6.hostname();
6286
+ this.hostname = opts.hostname ?? os7.hostname();
6214
6287
  this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
6215
6288
  this.sessionStore = opts.sessionStore;
6216
6289
  this.probe = opts.isPidAlive ?? defaultIsPidAlive;
@@ -6538,7 +6611,7 @@ async function loadTodosCheckpoint(filePath) {
6538
6611
  const parsed = JSON.parse(raw);
6539
6612
  if (parsed?.version !== 1 || !Array.isArray(parsed.todos)) return null;
6540
6613
  return parsed.todos.filter(
6541
- (t2) => !!t2 && typeof t2.id === "string" && typeof t2.content === "string" && typeof t2.status === "string"
6614
+ (t2) => !!t2 && typeof t2.id === "string" && typeof t2.content === "string" && typeof t2.status === "string" && (t2.activeForm === void 0 || typeof t2.activeForm === "string")
6542
6615
  );
6543
6616
  } catch {
6544
6617
  return null;
@@ -7174,14 +7247,6 @@ var DefaultPermissionPolicy = class {
7174
7247
  getConfirmDestructive() {
7175
7248
  return this.confirmDestructive;
7176
7249
  }
7177
- /** @deprecated Use `setYoloDestructive`. */
7178
- setForceAllYolo(enabled) {
7179
- this.setYoloDestructive(enabled);
7180
- }
7181
- /** @deprecated Use `getYoloDestructive`. */
7182
- getForceAllYolo() {
7183
- return this.getYoloDestructive();
7184
- }
7185
7250
  async reload() {
7186
7251
  try {
7187
7252
  const raw = await fsp3.readFile(this.trustFile, "utf8");
@@ -8842,7 +8907,7 @@ init_atomic_write();
8842
8907
  var MAX_JOURNAL_ENTRIES = 500;
8843
8908
  function goalFilePath(projectRoot) {
8844
8909
  const hash = createHash("sha256").update(path6.resolve(projectRoot)).digest("hex").slice(0, 12);
8845
- return path6.join(os6.homedir(), ".wrongstack", "projects", hash, "goal.json");
8910
+ return path6.join(os7.homedir(), ".wrongstack", "projects", hash, "goal.json");
8846
8911
  }
8847
8912
  async function loadGoal(filePath) {
8848
8913
  let raw;
@@ -12899,7 +12964,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
12899
12964
  }
12900
12965
  async spawn(subagent) {
12901
12966
  const id = subagent.id || randomUUID();
12902
- subagent = this.withNickname(subagent, id);
12967
+ const cfg = this.withNickname(subagent, id);
12903
12968
  if (this.subagents.has(id)) {
12904
12969
  throw new Error(`Subagent id "${id}" already exists \u2014 refusing to overwrite`);
12905
12970
  }
@@ -12914,12 +12979,12 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
12914
12979
  maxConcurrent: this.config.maxConcurrent ?? 16
12915
12980
  };
12916
12981
  this.subagents.set(id, {
12917
- config: { ...subagent, id },
12982
+ config: { ...cfg, id },
12918
12983
  context,
12919
12984
  status: "idle",
12920
12985
  abortController: new AbortController()
12921
12986
  });
12922
- this.emit("subagent.started", { subagent: { ...subagent, id } });
12987
+ this.emit("subagent.started", { subagent: { ...cfg, id } });
12923
12988
  this.fleetBus?.emit({
12924
12989
  subagentId: id,
12925
12990
  ts: Date.now(),
@@ -14604,6 +14669,10 @@ A scratchpad shared with the rest of the fleet is mounted at \`${parts.sharedScr
14604
14669
  - Use stable filenames (one file per concern); overwrite instead of appending so the Director sees the latest state.`
14605
14670
  );
14606
14671
  }
14672
+ if (parts.skills && parts.skills.trim().length > 0) {
14673
+ sections.push(`Domain knowledge:
14674
+ ${parts.skills.trim()}`);
14675
+ }
14607
14676
  if (parts.override && parts.override.trim().length > 0) {
14608
14677
  sections.push(parts.override.trim());
14609
14678
  }
@@ -16448,6 +16517,7 @@ var Director = class _Director {
16448
16517
  role: config.prompt,
16449
16518
  task: taskBrief,
16450
16519
  sharedScratchpad: this.sharedScratchpadPath ?? void 0,
16520
+ skills: config.skillContent,
16451
16521
  override: config.systemPromptOverride
16452
16522
  });
16453
16523
  }
@@ -16597,6 +16667,7 @@ function createDelegateTool(opts) {
16597
16667
  if (typeof i.task !== "string" || !i.task.trim()) {
16598
16668
  return { ok: false, error: "`task` is required." };
16599
16669
  }
16670
+ const target = i.role ?? i.name ?? "subagent";
16600
16671
  try {
16601
16672
  let director = await opts.host.ensureDirector();
16602
16673
  if (!director) {
@@ -16657,6 +16728,7 @@ function createDelegateTool(opts) {
16657
16728
  if (!cfg.timeoutMs) {
16658
16729
  cfg.timeoutMs = Math.max(3e4, timeoutMs - SUBAGENT_TIMEOUT_BUFFER_MS);
16659
16730
  }
16731
+ opts.events?.emit("delegate.started", { target, task: i.task });
16660
16732
  const subagentId = await director.spawn(cfg);
16661
16733
  const taskId = await director.assign({
16662
16734
  id: `${randomUUID()}`,
@@ -16691,6 +16763,17 @@ function createDelegateTool(opts) {
16691
16763
  });
16692
16764
  if ("__timeout" in result) {
16693
16765
  const partial2 = await readSubagentPartial(opts, subagentId);
16766
+ opts.events?.emit("delegate.completed", {
16767
+ target,
16768
+ task: i.task,
16769
+ ok: false,
16770
+ status: "host_timeout",
16771
+ summary: `[${target}] timed out \u2014 no result within ${Math.round(timeoutMs / 1e3)}s`,
16772
+ durationMs: timeoutMs,
16773
+ iterations: partial2?.events ?? 0,
16774
+ toolCalls: partial2?.toolUsesObserved ?? 0,
16775
+ subagentId
16776
+ });
16694
16777
  return {
16695
16778
  ok: false,
16696
16779
  stopReason: "host_timeout",
@@ -16707,6 +16790,24 @@ function createDelegateTool(opts) {
16707
16790
  const retryable = result.error?.retryable;
16708
16791
  const backoffMs = result.error?.backoffMs;
16709
16792
  const summary = buildDelegateSummary(i.role, result);
16793
+ let costUsd;
16794
+ try {
16795
+ costUsd = dir.snapshot().perSubagent[result.subagentId]?.cost;
16796
+ } catch {
16797
+ costUsd = void 0;
16798
+ }
16799
+ opts.events?.emit("delegate.completed", {
16800
+ target,
16801
+ task: i.task,
16802
+ ok: result.status === "success",
16803
+ status: result.status,
16804
+ summary,
16805
+ durationMs: result.durationMs,
16806
+ iterations: result.iterations,
16807
+ toolCalls: result.toolCalls,
16808
+ costUsd,
16809
+ subagentId: result.subagentId
16810
+ });
16710
16811
  return {
16711
16812
  ok: result.status === "success",
16712
16813
  status: result.status,
@@ -16728,10 +16829,21 @@ function createDelegateTool(opts) {
16728
16829
  summary
16729
16830
  };
16730
16831
  } catch (err) {
16832
+ const message = err instanceof Error ? err.message : String(err);
16833
+ opts.events?.emit("delegate.completed", {
16834
+ target,
16835
+ task: i.task,
16836
+ ok: false,
16837
+ status: "error",
16838
+ summary: `[${target}] failed \u2014 ${message}`,
16839
+ durationMs: 0,
16840
+ iterations: 0,
16841
+ toolCalls: 0
16842
+ });
16731
16843
  return {
16732
16844
  ok: false,
16733
16845
  stopReason: "error",
16734
- error: err instanceof Error ? err.message : String(err)
16846
+ error: message
16735
16847
  };
16736
16848
  }
16737
16849
  }
@@ -20753,6 +20865,7 @@ var MAX_TARBALL_SIZE = 50 * 1024 * 1024;
20753
20865
  async function downloadGitHubTarball(parsed) {
20754
20866
  const url = `https://api.github.com/repos/${parsed.owner}/${parsed.repo}/tarball/${parsed.ref}`;
20755
20867
  const response = await fetch(url, {
20868
+ signal: AbortSignal.timeout(3e4),
20756
20869
  headers: {
20757
20870
  Accept: "application/vnd.github+json",
20758
20871
  "User-Agent": "wrongstack-skill-installer"
@@ -20778,7 +20891,7 @@ async function downloadGitHubTarball(parsed) {
20778
20891
  `Tarball too large (${(Number.parseInt(contentLength, 10) / 1024 / 1024).toFixed(1)}MB). Max: ${MAX_TARBALL_SIZE / 1024 / 1024}MB`
20779
20892
  );
20780
20893
  }
20781
- const tempDir = await fsp3.mkdtemp(path6.join(os6.tmpdir(), "wskill-"));
20894
+ const tempDir = await fsp3.mkdtemp(path6.join(os7.tmpdir(), "wskill-"));
20782
20895
  try {
20783
20896
  if (!response.body) {
20784
20897
  throw new Error("Empty response body from GitHub API");
@@ -21588,7 +21701,6 @@ var SessionRecovery = class {
21588
21701
  }
21589
21702
  return null;
21590
21703
  } catch {
21591
- continue;
21592
21704
  }
21593
21705
  }
21594
21706
  return null;
@@ -21819,7 +21931,7 @@ var ToolAuditLog = class {
21819
21931
  await fsp3.appendFile(fp, line, "utf8");
21820
21932
  const count = (this.unSyncedWrites.get(sessionId) ?? 0) + 1;
21821
21933
  this.unSyncedWrites.set(sessionId, count);
21822
- if (this.fsyncEvery !== Infinity && count % this.fsyncEvery === 0) {
21934
+ if (this.fsyncEvery !== Number.POSITIVE_INFINITY && count % this.fsyncEvery === 0) {
21823
21935
  await this.sync(sessionId, fp);
21824
21936
  }
21825
21937
  }
@@ -22258,6 +22370,7 @@ var CloudSync = class {
22258
22370
  async githubFetch(token, owner, repo, method, pathSegment, body) {
22259
22371
  const url = `https://api.github.com/repos/${owner}/${repo}${pathSegment}`;
22260
22372
  const res = await fetch(url, {
22373
+ signal: AbortSignal.timeout(15e3),
22261
22374
  method,
22262
22375
  headers: {
22263
22376
  Authorization: `Bearer ${token}`,
@@ -24225,16 +24338,16 @@ Use \`/security report <number>\` to view a specific report.` };
24225
24338
  }
24226
24339
  const index = Number.parseInt(reportId, 10) - 1;
24227
24340
  if (!Number.isNaN(index) && reports[index]) {
24228
- const { readFile: readFile37 } = await import('fs/promises');
24229
- const content = await readFile37(join(reportsDir, reports[index]), "utf-8");
24341
+ const { readFile: readFile38 } = await import('fs/promises');
24342
+ const content = await readFile38(join(reportsDir, reports[index]), "utf-8");
24230
24343
  return { message: `# Security Report
24231
24344
 
24232
24345
  ${content}` };
24233
24346
  }
24234
24347
  const match = reports.find((r) => r.includes(reportId));
24235
24348
  if (match) {
24236
- const { readFile: readFile37 } = await import('fs/promises');
24237
- const content = await readFile37(join(reportsDir, match), "utf-8");
24349
+ const { readFile: readFile38 } = await import('fs/promises');
24350
+ const content = await readFile38(join(reportsDir, match), "utf-8");
24238
24351
  return { message: `# Security Report
24239
24352
 
24240
24353
  ${content}` };
@@ -26039,12 +26152,14 @@ async function bootConfig(options = {}) {
26039
26152
  const cwd = typeof flags["cwd"] === "string" ? path6.resolve(flags["cwd"]) : process.cwd();
26040
26153
  const pathResolver = new DefaultPathResolver(cwd);
26041
26154
  const projectRoot = pathResolver.projectRoot;
26042
- const userHome = os6.homedir();
26155
+ const userHome = os7.homedir();
26043
26156
  const wpaths = resolveWstackPaths({ projectRoot, userHome });
26044
26157
  await fsp3.mkdir(wpaths.globalRoot, { recursive: true });
26045
26158
  await fsp3.mkdir(wpaths.projectDir, { recursive: true });
26046
26159
  await fsp3.mkdir(wpaths.projectSessions, { recursive: true });
26047
26160
  await writeProjectMeta(wpaths, projectRoot);
26161
+ cleanupStaleProjects(wpaths).catch(() => {
26162
+ });
26048
26163
  const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey });
26049
26164
  for (const file of [wpaths.globalConfig, wpaths.projectLocalConfig]) {
26050
26165
  try {
@@ -26110,6 +26225,7 @@ async function writeProjectMeta(paths, projectRoot) {
26110
26225
  await fsp3.mkdir(paths.projectDir, { recursive: true });
26111
26226
  const meta = {
26112
26227
  hash: paths.projectHash,
26228
+ slug: paths.projectSlug,
26113
26229
  root: projectRoot,
26114
26230
  lastSeen: (/* @__PURE__ */ new Date()).toISOString()
26115
26231
  };
@@ -26117,6 +26233,31 @@ async function writeProjectMeta(paths, projectRoot) {
26117
26233
  } catch {
26118
26234
  }
26119
26235
  }
26236
+ async function cleanupStaleProjects(wpaths) {
26237
+ const projectsRoot = path6.dirname(wpaths.projectDir);
26238
+ let entries;
26239
+ try {
26240
+ entries = await fsp3.readdir(projectsRoot, { withFileTypes: true });
26241
+ } catch {
26242
+ return;
26243
+ }
26244
+ for (const entry of entries) {
26245
+ if (!entry.isDirectory()) continue;
26246
+ const metaPath = path6.join(projectsRoot, entry.name, "meta.json");
26247
+ try {
26248
+ const raw = await fsp3.readFile(metaPath, "utf8");
26249
+ const meta = JSON.parse(raw);
26250
+ if (typeof meta.root === "string") {
26251
+ try {
26252
+ await fsp3.access(meta.root);
26253
+ } catch {
26254
+ await fsp3.rm(path6.join(projectsRoot, entry.name), { recursive: true, force: true });
26255
+ }
26256
+ }
26257
+ } catch {
26258
+ }
26259
+ }
26260
+ }
26120
26261
 
26121
26262
  // src/core/conversation-state.ts
26122
26263
  var ConversationState = class {
@@ -26155,9 +26296,11 @@ var ConversationState = class {
26155
26296
  this.emit({ kind: "messages_replaced", messages: [...messages] });
26156
26297
  }
26157
26298
  replaceTodos(todos) {
26299
+ const allDone = todos.length > 0 && todos.every((t2) => t2.status === "completed");
26300
+ const effective = allDone ? [] : todos;
26158
26301
  this.ctx.todos.length = 0;
26159
- this.ctx.todos.splice(0, 0, ...todos);
26160
- this.emit({ kind: "todos_replaced", todos: [...todos] });
26302
+ this.ctx.todos.splice(0, 0, ...effective);
26303
+ this.emit({ kind: "todos_replaced", todos: [...effective] });
26161
26304
  }
26162
26305
  setMeta(key, value) {
26163
26306
  this.ctx.meta[key] = value;
@@ -26390,7 +26533,7 @@ var InputBuilder = class {
26390
26533
  meta: { label: paragraphLabel(text) }
26391
26534
  });
26392
26535
  this.refs.push(ref);
26393
- const lines = text.split("\n").length;
26536
+ const lines = text.split(/\r?\n|\r/).length;
26394
26537
  return `[pasted #${ref.seq}, ${lines} lines]`;
26395
26538
  }
26396
26539
  /**
@@ -26447,14 +26590,16 @@ var InputBuilder = class {
26447
26590
  if (text.length >= this.pasteCharThreshold) return true;
26448
26591
  let lines = 1;
26449
26592
  for (let i = 0; i < text.length; i++) {
26450
- if (text.charCodeAt(i) === 10) lines++;
26593
+ const c = text.charCodeAt(i);
26594
+ if (c === 10) lines++;
26595
+ else if (c === 13 && text.charCodeAt(i + 1) !== 10) lines++;
26451
26596
  if (lines >= this.pasteLineThreshold) return true;
26452
26597
  }
26453
26598
  return false;
26454
26599
  }
26455
26600
  };
26456
26601
  function paragraphLabel(text) {
26457
- const lines = text.split("\n").length;
26602
+ const lines = text.split(/\r?\n|\r/).length;
26458
26603
  const bytes = Buffer.byteLength(text, "utf8");
26459
26604
  if (bytes < 1024) return `${lines} lines, ${bytes} B`;
26460
26605
  return `${lines} lines, ${(bytes / 1024).toFixed(1)} KB`;
@@ -26465,23 +26610,34 @@ var PROMPT = `You are WrongStack, a command-line AI coding agent.
26465
26610
 
26466
26611
  You operate inside the user's terminal with direct read and write access to their working directory, the ability to run shell commands, and access to the web. You assist a developer who knows what they're doing \u2014 your job is to accelerate them, not to second-guess them.
26467
26612
 
26613
+ These are your baseline instructions. When an active mode prompt (Teach, Brief, Code Reviewer, etc.) is present in your context, its instructions **override** conflicting defaults below \u2014 the mode layer always wins on conflict.
26614
+
26468
26615
  ## Core principles
26469
26616
 
26470
26617
  1. **Read before you write.** Always inspect the relevant files before proposing changes. Assumptions about code you haven't read are bugs in waiting.
26471
26618
  2. **Prefer surgical edits over rewrites.** When modifying existing files, use the edit tool with str_replace; only use write for new files or full replacements explicitly requested.
26472
26619
  3. **Show your work.** Before non-trivial changes, briefly state what you're about to do \u2014 one sentence, not a wall of text. After tool calls, summarize what happened, not what you did mechanically.
26473
26620
  4. **Be honest about limits.** If you don't know, say so. If something failed, say what failed and what you'll try next. Never fabricate file contents, API responses, or test results.
26474
- 5. **Be concise.** The user is a developer in a terminal. No marketing language, no "great question!", no bullet-point lists when prose works. If a one-liner answers, a one-liner is the answer.
26621
+ 5. **Be concise.** The user is a developer in a terminal. No marketing language, no "great question!", no bullet-point lists when prose works. If a one-liner answers, a one-liner is the answer. (Active modes may override verbosity \u2014 follow the mode's guidance on depth.)
26475
26622
  6. **Ask when blocked, proceed when not.** If the task is ambiguous in a way that meaningfully changes the approach, ask. If it's ambiguous in a way that doesn't, pick a reasonable default and proceed, stating the assumption.
26476
26623
  7. **Trust the tools.** If a permission prompt is shown, the user will answer. Do not preemptively explain that you "would like to" do something \u2014 call the tool, let the permission flow decide.
26477
26624
  8. **Format for scanability.** Use code blocks for code, backticks for file paths, bold for key terms. One-liners stay one line. Paragraphs max 3 sentences.
26478
- 9. **Recover explicitly.** When a tool fails, state: (1) what failed, (2) what you tried, (3) what you'll attempt next. Never silently skip.
26625
+ 9. **Match the user's language.** Respond in the same language the user writes in. If they write in Turkish, reply in Turkish. If they mix languages, follow the dominant one.
26626
+ 10. **Recover explicitly.** When a tool fails, distinguish the failure type and respond accordingly:
26627
+
26628
+ | Failure type | Examples | Strategy |
26629
+ |---|---|---|
26630
+ | **Transient** | Timeout, rate limit, network hiccup | Retry once with adjusted params, then report |
26631
+ | **Permanent** | Syntax error, missing file, type error, permission denied | Do NOT retry \u2014 diagnose and report the root cause |
26632
+ | **Validation** | Invalid argument, out-of-range value, schema mismatch | State what was rejected and what range/format is accepted |
26633
+
26634
+ Never silently skip a failure \u2014 always report it, even when you choose not to retry.
26479
26635
 
26480
26636
  ## Decision heuristics
26481
26637
 
26482
26638
  - **Task is ambiguous** (unclear which file, conflicting requirements) \u2192 ask before proceeding
26483
26639
  - **Task is clear, approach is unknown** \u2192 try one approach, report what happened
26484
- - **Tool fails** \u2192 retry once with adjusted params, then report failure
26640
+ - **Tool fails** \u2192 classify the failure (transient/permanent/validation), then apply the appropriate recovery
26485
26641
  - **Permission prompt shown** \u2192 wait for user, do not act unilaterally
26486
26642
  - **Tool denied by user** \u2192 do NOT retry the same tool in the next iteration. If the user denies a write, bash, or any tool, respect that decision. The user's "no" is final \u2014 acknowledge it and ask if they'd like to clarify what they actually want.
26487
26643
  - **Context window filling up** \u2192 use context_manager proactively; don't wait to be told
@@ -26512,6 +26668,8 @@ var DefaultSystemPromptBuilder = class {
26512
26668
  */
26513
26669
  envCacheByRoot = /* @__PURE__ */ new Map();
26514
26670
  skillCache;
26671
+ /** Cached full skill bodies (after frontmatter), built once per session. */
26672
+ skillBodyCache;
26515
26673
  async build(ctx) {
26516
26674
  if (this.opts.skillLoader && !this.skillCache) {
26517
26675
  try {
@@ -26519,8 +26677,8 @@ var DefaultSystemPromptBuilder = class {
26519
26677
  if (entries.length > 0) {
26520
26678
  const lines = [];
26521
26679
  for (const e of entries) {
26522
- const scopeTag = e.scope.length > 0 ? ` \u2014 ${e.scope.slice(0, 4).join(", ")}` : "";
26523
- lines.push(`- **${e.name}**${scopeTag} (${e.trigger})`);
26680
+ const shortTrigger = compactTrigger(e.trigger);
26681
+ lines.push(`- **${e.name}** (${shortTrigger})`);
26524
26682
  }
26525
26683
  this.skillCache = lines.join("\n");
26526
26684
  }
@@ -26552,6 +26710,24 @@ var DefaultSystemPromptBuilder = class {
26552
26710
  cache_control: { type: "ephemeral" }
26553
26711
  });
26554
26712
  }
26713
+ if (this.opts.modeStore && this.opts.skillLoader) {
26714
+ try {
26715
+ const activeMode = await this.opts.modeStore.getActiveMode();
26716
+ if (activeMode?.suggestedSkills && activeMode.suggestedSkills.length > 0) {
26717
+ const skills = await this.opts.skillLoader.list();
26718
+ const loadedNames = new Set(skills.map((s) => s.name));
26719
+ const available = activeMode.suggestedSkills.filter((n) => loadedNames.has(n));
26720
+ if (available.length > 0) {
26721
+ blocks.push({
26722
+ type: "text",
26723
+ text: `Mode "${activeMode.id}" works best with these skills: ${available.join(", ")}. Their full instructions are in the Active Skills block above.`,
26724
+ cache_control: { type: "ephemeral" }
26725
+ });
26726
+ }
26727
+ }
26728
+ } catch {
26729
+ }
26730
+ }
26555
26731
  if (layer6.trim()) {
26556
26732
  blocks.push({
26557
26733
  type: "text",
@@ -26748,7 +26924,7 @@ summarize it, and let the tool result hold only the summary.`);
26748
26924
  const cached = this.envCacheByRoot.get(ctx.projectRoot);
26749
26925
  if (cached) return cached;
26750
26926
  const today = this.opts.todayIso ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
26751
- const platform2 = `${os6.platform()} ${os6.release()}`;
26927
+ const platform2 = `${os7.platform()} ${os7.release()}`;
26752
26928
  const shell = process.env.SHELL ?? process.env.ComSpec ?? "unknown";
26753
26929
  const node = process.version;
26754
26930
  const isGit = await this.dirExists(path6.join(ctx.projectRoot, ".git"));
@@ -26782,7 +26958,13 @@ summarize it, and let the tool result hold only the summary.`);
26782
26958
  );
26783
26959
  }
26784
26960
  if (this.skillCache) {
26785
- lines.push("", "## Skills in scope for this session", this.skillCache);
26961
+ lines.push(
26962
+ "",
26963
+ "## Skills in scope for this session",
26964
+ this.skillCache,
26965
+ "",
26966
+ "Full skill instructions are injected in the Active Skills block below."
26967
+ );
26786
26968
  }
26787
26969
  const text = lines.join("\n");
26788
26970
  this.envCacheByRoot.set(ctx.projectRoot, text);
@@ -26799,6 +26981,40 @@ ${mem}`);
26799
26981
  } catch {
26800
26982
  }
26801
26983
  }
26984
+ if (this.opts.skillLoader && this.skillBodyCache === void 0) {
26985
+ try {
26986
+ const skills = await this.opts.skillLoader.list();
26987
+ if (skills.length > 0) {
26988
+ const bodies = [];
26989
+ for (const s of skills) {
26990
+ try {
26991
+ const raw = await this.opts.skillLoader.readBody(s.name);
26992
+ const body = stripFrontmatter(raw);
26993
+ if (body.trim()) {
26994
+ bodies.push(`## Skill: ${s.name}
26995
+
26996
+ ${body.trim()}`);
26997
+ }
26998
+ } catch {
26999
+ }
27000
+ }
27001
+ if (bodies.length > 0) {
27002
+ this.skillBodyCache = bodies.join("\n\n---\n\n");
27003
+ } else {
27004
+ this.skillBodyCache = "";
27005
+ }
27006
+ } else {
27007
+ this.skillBodyCache = "";
27008
+ }
27009
+ } catch {
27010
+ this.skillBodyCache = "";
27011
+ }
27012
+ }
27013
+ if (this.skillBodyCache) {
27014
+ parts.push(`# Active Skills
27015
+
27016
+ ${this.skillBodyCache}`);
27017
+ }
26802
27018
  return parts.join("\n\n");
26803
27019
  }
26804
27020
  async buildMode() {
@@ -26888,6 +27104,22 @@ ${mem}`);
26888
27104
  return langs.size === 0 ? "unknown" : Array.from(langs).join(", ");
26889
27105
  }
26890
27106
  };
27107
+ function stripFrontmatter(raw) {
27108
+ if (!raw.startsWith("---")) return raw;
27109
+ const end = raw.indexOf("\n---", 4);
27110
+ if (end === -1) return raw;
27111
+ let body = raw.slice(end + 4);
27112
+ if (body.startsWith("\n")) body = body.slice(1);
27113
+ return body;
27114
+ }
27115
+ function compactTrigger(trigger) {
27116
+ let s = trigger.replace(/^Use this skill when /i, "").replace(/^Use this skill for /i, "").replace(/^Use when /i, "").replace(/\.$/, "");
27117
+ if (s.length > 72) {
27118
+ const cut = s.lastIndexOf(" ", 68);
27119
+ s = cut > 50 ? s.slice(0, cut) + "\u2026" : s.slice(0, 68) + "\u2026";
27120
+ }
27121
+ return s;
27122
+ }
26891
27123
 
26892
27124
  // src/registry/tool-registry.ts
26893
27125
  var ToolRegistry = class _ToolRegistry {
@@ -27631,6 +27863,104 @@ function wrapApiForCapabilityCheck(plugin, api, log, enforce = false) {
27631
27863
  });
27632
27864
  }
27633
27865
 
27866
+ // src/execution/prompt-enhancer.ts
27867
+ var ENHANCER_SYSTEM_PROMPT = `You are a request refiner embedded in a coding agent. Your ONLY job is to rewrite the user's message into a single, clearer, unambiguous instruction that the coding agent can act on confidently.
27868
+
27869
+ Rules:
27870
+ - Preserve the user's intent and scope EXACTLY. Do not add new requirements, features, constraints, or steps the user did not ask for. Do not remove anything they did ask for.
27871
+ - Do NOT answer, solve, or perform the request. Only restate it more clearly.
27872
+ - Keep all concrete details verbatim: file paths, identifiers, code, error text, numbers, names, URLs.
27873
+ - Resolve obvious ambiguity by making the implied subject explicit, not by inventing specifics. If something is genuinely unspecified, leave it general rather than guessing.
27874
+ - Be concise: one tight instruction (a few sentences at most). No preamble, no explanation, no quotes, no markdown headers.
27875
+ - If the message is already clear and complete, return it essentially unchanged.
27876
+ - Preserve the user's language (if they wrote in Turkish, refine in Turkish).
27877
+
27878
+ When earlier conversation turns are provided, they are CONTEXT ONLY. Use them to resolve references in the user's latest message \u2014 "it", "that", "the same", "the other one", "this file", "again" \u2014 so the refined instruction is self-contained. Refine ONLY the user's latest message; do not answer it, do not act on or restate earlier turns, and do not summarize the conversation.
27879
+
27880
+ Output ONLY the refined request text \u2014 nothing else.`;
27881
+ var AFFIRMATION_RE = /^(y|n|yes|no|yep|nope|ok|okay|sure|go|go ahead|continue|proceed|stop|cancel|done|next|skip|retry|again|please do|do it)\b[.! ]*$/i;
27882
+ function shouldEnhance(text) {
27883
+ const t2 = text.trim();
27884
+ if (!t2) return false;
27885
+ if (t2.startsWith("/")) return false;
27886
+ if (t2.length < 12) return false;
27887
+ if (AFFIRMATION_RE.test(t2)) return false;
27888
+ if (/^[\d\s.,]+$/.test(t2)) return false;
27889
+ const words = t2.split(/\s+/).filter(Boolean);
27890
+ if (words.length < 3) return false;
27891
+ return true;
27892
+ }
27893
+ function normalizedEqual(a, b) {
27894
+ const norm = (s) => s.trim().replace(/\s+/g, " ").toLowerCase();
27895
+ return norm(a) === norm(b);
27896
+ }
27897
+ function buildRefinerInput(text, history) {
27898
+ if (!history || history.length === 0) return text;
27899
+ const lines = history.map((t2) => `${t2.role === "user" ? "User" : "Assistant"}: ${t2.text}`);
27900
+ return [
27901
+ "Recent conversation (context only \u2014 do not act on it):",
27902
+ ...lines,
27903
+ "",
27904
+ "Latest message to refine:",
27905
+ text
27906
+ ].join("\n");
27907
+ }
27908
+ async function enhanceUserPrompt(opts) {
27909
+ const { provider, model, text } = opts;
27910
+ const timeoutMs = opts.timeoutMs ?? 25e3;
27911
+ const maxTokens = opts.maxTokens ?? 2048;
27912
+ const req = {
27913
+ model,
27914
+ system: [{ type: "text", text: ENHANCER_SYSTEM_PROMPT }],
27915
+ messages: [{ role: "user", content: buildRefinerInput(text, opts.history) }],
27916
+ maxTokens
27917
+ // NOTE: deliberately NO `temperature`. The main agent loop never sets it,
27918
+ // and reasoning models (DeepSeek reasoner, o1/o3, …) return HTTP 400 when
27919
+ // `temperature` is present — which would make every refine call fail and
27920
+ // silently fall back to the original (no panel shown).
27921
+ };
27922
+ const timer = new AbortController();
27923
+ const to = setTimeout(() => timer.abort(new Error("enhancer timeout")), timeoutMs);
27924
+ const signal = opts.signal ? AbortSignal.any([opts.signal, timer.signal]) : timer.signal;
27925
+ try {
27926
+ const res = await provider.complete(req, { signal });
27927
+ const refined = res.content.filter(isTextBlock).map((b) => b.text).join("\n").trim();
27928
+ if (!refined) {
27929
+ opts.onError?.("model returned no text");
27930
+ return null;
27931
+ }
27932
+ return refined;
27933
+ } catch (err) {
27934
+ if (opts.signal?.aborted) return null;
27935
+ if (timer.signal.aborted) {
27936
+ opts.onError?.(`timed out after ${Math.round(timeoutMs / 1e3)}s`);
27937
+ return null;
27938
+ }
27939
+ opts.onError?.(err instanceof Error ? err.message : String(err));
27940
+ return null;
27941
+ } finally {
27942
+ clearTimeout(to);
27943
+ }
27944
+ }
27945
+ function messageText(content) {
27946
+ if (typeof content === "string") return content;
27947
+ return content.filter(isTextBlock).map((b) => b.text).join("\n").trim();
27948
+ }
27949
+ function recentTextTurns(messages, maxTurns = 6, maxChars = 1500) {
27950
+ const turns = [];
27951
+ for (let i = messages.length - 1; i >= 0 && turns.length < maxTurns; i--) {
27952
+ const m = messages[i];
27953
+ if (!m || m.role !== "user" && m.role !== "assistant") continue;
27954
+ const text = messageText(m.content);
27955
+ if (!text) continue;
27956
+ turns.unshift({
27957
+ role: m.role,
27958
+ text: text.length > maxChars ? `${text.slice(0, maxChars - 1)}\u2026` : text
27959
+ });
27960
+ }
27961
+ return turns;
27962
+ }
27963
+
27634
27964
  // src/autophase/phase-graph-builder.ts
27635
27965
  var PhaseGraphBuilder = class _PhaseGraphBuilder {
27636
27966
  constructor(opts) {
@@ -30431,7 +30761,7 @@ function createSkillsPlugin(opts) {
30431
30761
  };
30432
30762
  }
30433
30763
  function makeInstaller(skillLoader, projectRoot) {
30434
- const globalRoot = path6.join(os6.homedir(), ".wrongstack");
30764
+ const globalRoot = path6.join(os7.homedir(), ".wrongstack");
30435
30765
  return new SkillInstaller({
30436
30766
  manifestPath: path6.join(globalRoot, "installed-skills.json"),
30437
30767
  projectSkillsDir: path6.join(projectRoot, ".wrongstack", "skills"),
@@ -30782,6 +31112,6 @@ ${formatPlan(updated)}`
30782
31112
  };
30783
31113
  }
30784
31114
 
30785
- export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BudgetExceededError, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionRecovery, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertSafePath, atomicWrite, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildRecoveryStrategies, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeTaskProgress, consumeBtwNotes, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMcpControlTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createSyncPlugin, createToolOutputSerializer, decryptConfigSecrets, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, dispatchAgent, downloadGitHubTarball, emptyGoal, emptyPlan, encryptConfigSecrets, ensureDir, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, extractRunEnv, filesystemServer, findCriticalPath, flagsToConfigPatch, formatContextWindowModeList, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getPlanTemplate, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hashRequest, hookMatcherMatches, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, normalizeToLf, onResize, parseContinueDirective, parseSkillRef, pendingBtwCount, phaseForRole, projectHash, recordActualUsage, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveContextWindowPolicy, resolveModelMatrix, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTodosCheckpoint, scoreAgents, securitySlashCommand, sentinelServer, setBtwNote, setPlanItemStatus, setRawMode, slackServer, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, wrapAsState, writeErr, writeOut, zaiVisionServer };
31115
+ export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BudgetExceededError, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionRecovery, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertSafePath, atomicWrite, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildRecoveryStrategies, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeTaskProgress, consumeBtwNotes, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMcpControlTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createSyncPlugin, createToolOutputSerializer, decryptConfigSecrets, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, dispatchAgent, downloadGitHubTarball, emptyGoal, emptyPlan, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, extractRunEnv, filesystemServer, findCriticalPath, flagsToConfigPatch, formatContextWindowModeList, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getPlanTemplate, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hashRequest, hookMatcherMatches, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, normalizeToLf, normalizedEqual, onResize, parseContinueDirective, parseSkillRef, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveContextWindowPolicy, resolveModelMatrix, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTodosCheckpoint, scoreAgents, securitySlashCommand, sentinelServer, setBtwNote, setPlanItemStatus, setRawMode, shouldEnhance, slackServer, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, wrapAsState, writeErr, writeOut, zaiVisionServer };
30786
31116
  //# sourceMappingURL=index.js.map
30787
31117
  //# sourceMappingURL=index.js.map