@wrongstack/core 0.66.13 → 0.73.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/{agent-bridge-D-j6OOBT.d.ts → agent-bridge-C0Ze7Ldm.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-DRZ9-NnR.d.ts → agent-subagent-runner-BmITbs1Q.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 +188 -210
  6. package/dist/coordination/index.js.map +1 -1
  7. package/dist/defaults/index.d.ts +15 -15
  8. package/dist/defaults/index.js +121 -118
  9. package/dist/defaults/index.js.map +1 -1
  10. package/dist/{events-CIplI98R.d.ts → events-BBAlxBuw.d.ts} +8 -0
  11. package/dist/execution/index.d.ts +8 -8
  12. package/dist/execution/index.js +69 -99
  13. package/dist/execution/index.js.map +1 -1
  14. package/dist/extension/index.d.ts +5 -5
  15. package/dist/{index-DKUvyTvV.d.ts → index-BN6i2Nfg.d.ts} +4 -4
  16. package/dist/{index-b5uhfTSl.d.ts → index-yQbZ2NQx.d.ts} +6 -6
  17. package/dist/index.d.ts +29 -27
  18. package/dist/index.js +222 -129
  19. package/dist/index.js.map +1 -1
  20. package/dist/infrastructure/index.d.ts +4 -4
  21. package/dist/kernel/index.d.ts +7 -7
  22. package/dist/kernel/index.js.map +1 -1
  23. package/dist/{mcp-servers-DwoNBf6r.d.ts → mcp-servers-T0O6UN_w.d.ts} +1 -1
  24. package/dist/{mode-CV077NjV.d.ts → mode-BO4SEUIv.d.ts} +7 -0
  25. package/dist/models/index.d.ts +1 -1
  26. package/dist/models/index.js +18 -9
  27. package/dist/models/index.js.map +1 -1
  28. package/dist/{multi-agent-coordinator-CWnH-CiX.d.ts → multi-agent-coordinator-BSBbZt0e.d.ts} +1 -1
  29. package/dist/{null-fleet-bus-VApKRxcp.d.ts → null-fleet-bus-BCIRT_nV.d.ts} +37 -33
  30. package/dist/observability/index.d.ts +1 -1
  31. package/dist/{parallel-eternal-engine-0UwotoSx.d.ts → parallel-eternal-engine-CjAYGaCw.d.ts} +3 -3
  32. package/dist/{path-resolver-DVkEcIw8.d.ts → path-resolver-BnqXa9Ze.d.ts} +1 -1
  33. package/dist/{permission-C1A5whY5.d.ts → permission-V5BLOrY6.d.ts} +0 -4
  34. package/dist/{permission-policy-B2dK-T5N.d.ts → permission-policy-CBVx-d-8.d.ts} +1 -5
  35. package/dist/{plan-templates-Bprrzhbu.d.ts → plan-templates-DBgrTGPu.d.ts} +2 -2
  36. package/dist/{provider-runner-mXvXGSIw.d.ts → provider-runner-n3KkHT_w.d.ts} +1 -1
  37. package/dist/sdd/index.d.ts +6 -6
  38. package/dist/sdd/index.js +68 -98
  39. package/dist/sdd/index.js.map +1 -1
  40. package/dist/security/index.d.ts +2 -2
  41. package/dist/security/index.js +0 -8
  42. package/dist/security/index.js.map +1 -1
  43. package/dist/skills/index.js +1 -0
  44. package/dist/skills/index.js.map +1 -1
  45. package/dist/storage/index.d.ts +3 -3
  46. package/dist/storage/index.js +26 -2
  47. package/dist/storage/index.js.map +1 -1
  48. package/dist/{system-prompt-b61lOd49.d.ts → system-prompt-CA11g6Jo.d.ts} +1 -1
  49. package/dist/types/index.d.ts +13 -13
  50. package/dist/types/index.js +19 -10
  51. package/dist/types/index.js.map +1 -1
  52. package/dist/utils/index.d.ts +1 -1
  53. package/dist/utils/index.js +2 -1
  54. package/dist/utils/index.js.map +1 -1
  55. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2677,7 +2677,8 @@ When reviewing code:
2677
2677
  - Verify test coverage for critical paths
2678
2678
  - Ensure naming conventions are followed`,
2679
2679
  tags: ["review", "quality", "security"],
2680
- toolPreferences: ["read", "grep", "git", "diff", "test"]
2680
+ toolPreferences: ["read", "grep", "git", "diff", "test"],
2681
+ suggestedSkills: ["bug-hunter", "security-scanner", "typescript-strict", "testing"]
2681
2682
  },
2682
2683
  {
2683
2684
  id: "code-auditor",
@@ -2694,7 +2695,8 @@ When auditing code for security:
2694
2695
  - Assess input validation and output encoding
2695
2696
  - Look for timing attacks and information leakage`,
2696
2697
  tags: ["security", "audit", "compliance"],
2697
- toolPreferences: ["grep", "read", "audit", "bash"]
2698
+ toolPreferences: ["grep", "read", "audit", "bash"],
2699
+ suggestedSkills: ["security-scanner", "bug-hunter", "audit-log"]
2698
2700
  },
2699
2701
  {
2700
2702
  id: "architect",
@@ -2712,7 +2714,8 @@ When designing or reviewing architecture:
2712
2714
  - Assess API design and contract stability
2713
2715
  - Consider operational aspects (monitoring, logging, deployment)`,
2714
2716
  tags: ["architecture", "design", "scalability"],
2715
- toolPreferences: ["read", "glob", "tree", "diff"]
2717
+ toolPreferences: ["read", "glob", "tree", "diff"],
2718
+ suggestedSkills: ["api-design", "refactor-planner", "node-modern", "docker-deploy"]
2716
2719
  },
2717
2720
  {
2718
2721
  id: "debugger",
@@ -2730,7 +2733,8 @@ When investigating bugs:
2730
2733
  - Use binary search to isolate the root cause
2731
2734
  - Verify fixes with tests before considering done`,
2732
2735
  tags: ["debug", "investigation", "error-resolution"],
2733
- toolPreferences: ["read", "grep", "bash", "logs", "test"]
2736
+ toolPreferences: ["read", "grep", "bash", "logs", "test"],
2737
+ suggestedSkills: ["bug-hunter", "audit-log", "observability"]
2734
2738
  },
2735
2739
  {
2736
2740
  id: "tester",
@@ -2748,7 +2752,8 @@ When testing or writing tests:
2748
2752
  - Check for integration test gaps
2749
2753
  - Verify test isolation and cleanup`,
2750
2754
  tags: ["testing", "qa", "quality"],
2751
- toolPreferences: ["read", "grep", "test", "bash"]
2755
+ toolPreferences: ["read", "grep", "test", "bash"],
2756
+ suggestedSkills: ["testing", "bug-hunter", "typescript-strict"]
2752
2757
  },
2753
2758
  {
2754
2759
  id: "devops",
@@ -2766,7 +2771,8 @@ When working on infrastructure:
2766
2771
  - Assess secrets management
2767
2772
  - Check for resource limits and quotas`,
2768
2773
  tags: ["devops", "infrastructure", "operations"],
2769
- toolPreferences: ["read", "bash", "grep", "logs", "git"]
2774
+ toolPreferences: ["read", "bash", "grep", "logs", "git"],
2775
+ suggestedSkills: ["docker-deploy", "observability", "security-scanner"]
2770
2776
  },
2771
2777
  {
2772
2778
  id: "refactorer",
@@ -2784,7 +2790,8 @@ When refactoring code:
2784
2790
  - Don't mix formatting changes with logic changes
2785
2791
  - Keep performance in mind \u2014 don't regress`,
2786
2792
  tags: ["refactor", "modernization", "improvement"],
2787
- toolPreferences: ["read", "edit", "test", "git", "grep"]
2793
+ toolPreferences: ["read", "edit", "test", "git", "grep"],
2794
+ suggestedSkills: ["refactor-planner", "typescript-strict", "node-modern", "testing"]
2788
2795
  },
2789
2796
  {
2790
2797
  id: "brief",
@@ -2814,7 +2821,8 @@ Get to the point \u2014 read files, run commands, make changes.
2814
2821
  - One-liner sufficient? One liner.
2815
2822
  - Max 3 sentences per paragraph.`,
2816
2823
  tags: ["fast", "concise", "direct"],
2817
- toolPreferences: ["read", "edit", "bash"]
2824
+ toolPreferences: ["read", "edit", "bash"],
2825
+ suggestedSkills: []
2818
2826
  },
2819
2827
  {
2820
2828
  id: "teach",
@@ -2879,7 +2887,8 @@ You follow these principles, but always with explanation:
2879
2887
 
2880
2888
  Remember: your job is to make the user a better developer, not just to complete tasks faster.`,
2881
2889
  tags: ["teaching", "mentor", "learning"],
2882
- toolPreferences: ["read", "edit", "explain"]
2890
+ toolPreferences: ["read", "edit", "explain"],
2891
+ suggestedSkills: ["prompt-engineering", "skill-creator", "node-modern", "typescript-strict"]
2883
2892
  }
2884
2893
  ];
2885
2894
 
@@ -3512,7 +3521,7 @@ ${errorDetails}`,
3512
3521
  const decision = await this.opts.permissionPolicy.evaluate(tool, use.input, ctx);
3513
3522
  let effectivePermission = decision.permission;
3514
3523
  const policy = this.opts.permissionPolicy;
3515
- const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true || policy.getForceAllYolo?.() === true;
3524
+ const yolo = policy.getYolo?.() === true || policy.getYoloDestructive?.() === true;
3516
3525
  if (toolDangerousCaps.length > 0 && effectivePermission === "auto" && !yolo) {
3517
3526
  effectivePermission = "confirm";
3518
3527
  }
@@ -4654,7 +4663,8 @@ function isGlob(p) {
4654
4663
  return false;
4655
4664
  }
4656
4665
  function globToRegex(pat) {
4657
- let i = 0, re = "^";
4666
+ let i = 0;
4667
+ let re = "^";
4658
4668
  while (i < pat.length) {
4659
4669
  const c = pat[i];
4660
4670
  if (c === "*") {
@@ -5922,8 +5932,17 @@ var BEHAVIOR_DEFAULTS = {
5922
5932
  modelsRegistry: true,
5923
5933
  skills: true
5924
5934
  },
5935
+ indexing: {
5936
+ onSessionStart: true,
5937
+ onEdit: true,
5938
+ watchExternal: true,
5939
+ debounceMs: 400
5940
+ },
5925
5941
  session: { ...DEFAULT_SESSION_LOGGING_CONFIG }
5926
5942
  };
5943
+ function envBool(v) {
5944
+ return !/^(0|false|no|off)$/i.test(v.trim());
5945
+ }
5927
5946
  var ENV_MAP = {
5928
5947
  WRONGSTACK_PROVIDER: (c, v) => {
5929
5948
  c.provider = v;
@@ -5948,8 +5967,23 @@ var ENV_MAP = {
5948
5967
  WRONGSTACK_LOG_LEVEL: (c, v) => {
5949
5968
  if (!c.log) c.log = { level: "info" };
5950
5969
  c.log.level = v;
5970
+ },
5971
+ WRONGSTACK_INDEX_ON_START: (c, v) => {
5972
+ c.indexing = { ...defaultIndexing, ...c.indexing, onSessionStart: envBool(v) };
5973
+ },
5974
+ WRONGSTACK_INDEX_ON_EDIT: (c, v) => {
5975
+ c.indexing = { ...defaultIndexing, ...c.indexing, onEdit: envBool(v) };
5976
+ },
5977
+ WRONGSTACK_INDEX_WATCH: (c, v) => {
5978
+ c.indexing = { ...defaultIndexing, ...c.indexing, watchExternal: envBool(v) };
5951
5979
  }
5952
5980
  };
5981
+ var defaultIndexing = {
5982
+ onSessionStart: true,
5983
+ onEdit: true,
5984
+ watchExternal: true,
5985
+ debounceMs: 400
5986
+ };
5953
5987
  function isPrimitiveArray(a) {
5954
5988
  return a.every((v) => v === null || typeof v !== "object");
5955
5989
  }
@@ -7174,14 +7208,6 @@ var DefaultPermissionPolicy = class {
7174
7208
  getConfirmDestructive() {
7175
7209
  return this.confirmDestructive;
7176
7210
  }
7177
- /** @deprecated Use `setYoloDestructive`. */
7178
- setForceAllYolo(enabled) {
7179
- this.setYoloDestructive(enabled);
7180
- }
7181
- /** @deprecated Use `getYoloDestructive`. */
7182
- getForceAllYolo() {
7183
- return this.getYoloDestructive();
7184
- }
7185
7211
  async reload() {
7186
7212
  try {
7187
7213
  const raw = await fsp3.readFile(this.trustFile, "utf8");
@@ -12324,6 +12350,71 @@ Do not add prose, markdown, or code fences.`;
12324
12350
  };
12325
12351
  }
12326
12352
 
12353
+ // src/coordination/coordinator/error-classifier.ts
12354
+ function classifySubagentError(err, hints = {}) {
12355
+ const cause = err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : void 0;
12356
+ if (err instanceof ProviderError) {
12357
+ const baseMessage2 = err.describe();
12358
+ return providerErrorToSubagentError(err, baseMessage2, cause);
12359
+ }
12360
+ const baseMessage = err instanceof Error ? err.message : String(err);
12361
+ if (err instanceof BudgetExceededError) {
12362
+ const map = {
12363
+ iterations: "budget_iterations",
12364
+ tool_calls: "budget_tool_calls",
12365
+ tokens: "budget_tokens",
12366
+ cost: "budget_cost",
12367
+ timeout: "budget_timeout",
12368
+ idle_timeout: "budget_timeout"
12369
+ };
12370
+ return {
12371
+ kind: map[err.kind],
12372
+ message: baseMessage,
12373
+ retryable: false,
12374
+ cause
12375
+ };
12376
+ }
12377
+ if (hints.parentAborted) {
12378
+ return { kind: "aborted_by_parent", message: baseMessage, retryable: false, cause };
12379
+ }
12380
+ const lower = baseMessage.toLowerCase();
12381
+ if (/agent aborted$/i.test(baseMessage)) {
12382
+ return { kind: "aborted_by_parent", message: baseMessage, retryable: false, cause };
12383
+ }
12384
+ if (/agent exhausted iteration limit$/i.test(baseMessage)) {
12385
+ return { kind: "budget_iterations", message: baseMessage, retryable: false, cause };
12386
+ }
12387
+ if (/empty response$/i.test(baseMessage)) {
12388
+ return { kind: "empty_response", message: baseMessage, retryable: false, cause };
12389
+ }
12390
+ if (/^tool failed: /i.test(baseMessage)) {
12391
+ return { kind: "tool_failed", message: baseMessage, retryable: false, cause };
12392
+ }
12393
+ if (lower.includes("bridge transport") || /bridge.*(closed|disconnect)/i.test(baseMessage)) {
12394
+ return { kind: "bridge_failed", message: baseMessage, retryable: false, cause };
12395
+ }
12396
+ if (/context length|max.*tokens?.*exceeded|prompt is too long/i.test(baseMessage)) {
12397
+ return { kind: "context_overflow", message: baseMessage, retryable: false, cause };
12398
+ }
12399
+ return { kind: "unknown", message: baseMessage, retryable: false, cause };
12400
+ }
12401
+ function providerErrorToSubagentError(err, message, cause) {
12402
+ const status = err.status;
12403
+ if (status === 429 || err.body?.type === "rate_limit_error") {
12404
+ return { kind: "provider_rate_limit", message, retryable: true, backoffMs: 5e3, cause };
12405
+ }
12406
+ if (status === 401 || status === 403 || err.body?.type === "authentication_error") {
12407
+ return { kind: "provider_auth", message, retryable: false, cause };
12408
+ }
12409
+ if (status === 408 || status === 0) {
12410
+ return { kind: "provider_timeout", message, retryable: true, cause };
12411
+ }
12412
+ if (status >= 500 && status < 600) {
12413
+ return { kind: "provider_5xx", message, retryable: true, backoffMs: 3e3, cause };
12414
+ }
12415
+ return { kind: "unknown", message, retryable: err.retryable, cause };
12416
+ }
12417
+
12327
12418
  // src/coordination/fleet.ts
12328
12419
  var AUDIT_LOG_AGENT = {
12329
12420
  id: "audit-log",
@@ -12834,7 +12925,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
12834
12925
  }
12835
12926
  async spawn(subagent) {
12836
12927
  const id = subagent.id || randomUUID();
12837
- subagent = this.withNickname(subagent, id);
12928
+ const cfg = this.withNickname(subagent, id);
12838
12929
  if (this.subagents.has(id)) {
12839
12930
  throw new Error(`Subagent id "${id}" already exists \u2014 refusing to overwrite`);
12840
12931
  }
@@ -12849,12 +12940,12 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
12849
12940
  maxConcurrent: this.config.maxConcurrent ?? 16
12850
12941
  };
12851
12942
  this.subagents.set(id, {
12852
- config: { ...subagent, id },
12943
+ config: { ...cfg, id },
12853
12944
  context,
12854
12945
  status: "idle",
12855
12946
  abortController: new AbortController()
12856
12947
  });
12857
- this.emit("subagent.started", { subagent: { ...subagent, id } });
12948
+ this.emit("subagent.started", { subagent: { ...cfg, id } });
12858
12949
  this.fleetBus?.emit({
12859
12950
  subagentId: id,
12860
12951
  ts: Date.now(),
@@ -13391,101 +13482,6 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
13391
13482
  return false;
13392
13483
  }
13393
13484
  };
13394
- function classifySubagentError(err, hints = {}) {
13395
- const cause = err instanceof Error ? { name: err.name, message: err.message, stack: err.stack } : void 0;
13396
- if (err instanceof ProviderError) {
13397
- const baseMessage2 = err.describe();
13398
- return providerErrorToSubagentError(err, baseMessage2, cause);
13399
- }
13400
- const baseMessage = err instanceof Error ? err.message : String(err);
13401
- if (err instanceof BudgetExceededError) {
13402
- const map = {
13403
- iterations: "budget_iterations",
13404
- tool_calls: "budget_tool_calls",
13405
- tokens: "budget_tokens",
13406
- cost: "budget_cost",
13407
- timeout: "budget_timeout",
13408
- idle_timeout: "budget_timeout"
13409
- };
13410
- return {
13411
- kind: map[err.kind],
13412
- message: baseMessage,
13413
- // Budgets are user-configured ceilings, not transient failures —
13414
- // retrying with the same budget will hit the same ceiling. The
13415
- // orchestrator must raise the budget or narrow the task first.
13416
- retryable: false,
13417
- cause
13418
- };
13419
- }
13420
- if (hints.parentAborted) {
13421
- return {
13422
- kind: "aborted_by_parent",
13423
- message: baseMessage,
13424
- retryable: false,
13425
- cause
13426
- };
13427
- }
13428
- const lower = baseMessage.toLowerCase();
13429
- if (/agent aborted$/i.test(baseMessage)) {
13430
- return {
13431
- kind: "aborted_by_parent",
13432
- message: baseMessage,
13433
- retryable: false,
13434
- cause
13435
- };
13436
- }
13437
- if (/agent exhausted iteration limit$/i.test(baseMessage)) {
13438
- return { kind: "budget_iterations", message: baseMessage, retryable: false, cause };
13439
- }
13440
- if (/empty response$/i.test(baseMessage)) {
13441
- return { kind: "empty_response", message: baseMessage, retryable: false, cause };
13442
- }
13443
- if (/^tool failed: /i.test(baseMessage)) {
13444
- return { kind: "tool_failed", message: baseMessage, retryable: false, cause };
13445
- }
13446
- if (lower.includes("bridge transport") || /bridge.*(closed|disconnect)/i.test(baseMessage)) {
13447
- return { kind: "bridge_failed", message: baseMessage, retryable: false, cause };
13448
- }
13449
- if (/context length|max.*tokens?.*exceeded|prompt is too long/i.test(baseMessage)) {
13450
- return { kind: "context_overflow", message: baseMessage, retryable: false, cause };
13451
- }
13452
- return {
13453
- kind: "unknown",
13454
- message: baseMessage,
13455
- retryable: false,
13456
- cause
13457
- };
13458
- }
13459
- function providerErrorToSubagentError(err, message, cause) {
13460
- const status = err.status;
13461
- if (status === 429 || err.body?.type === "rate_limit_error") {
13462
- return {
13463
- kind: "provider_rate_limit",
13464
- message,
13465
- retryable: true,
13466
- // Conservative default: 5s. Provider-specific code can override
13467
- // by emitting an error whose body carries an explicit hint.
13468
- backoffMs: 5e3,
13469
- cause
13470
- };
13471
- }
13472
- if (status === 401 || status === 403 || err.body?.type === "authentication_error") {
13473
- return { kind: "provider_auth", message, retryable: false, cause };
13474
- }
13475
- if (status === 408 || status === 0) {
13476
- return { kind: "provider_timeout", message, retryable: true, cause };
13477
- }
13478
- if (status >= 500 && status < 600) {
13479
- return {
13480
- kind: "provider_5xx",
13481
- message,
13482
- retryable: true,
13483
- backoffMs: 3e3,
13484
- cause
13485
- };
13486
- }
13487
- return { kind: "unknown", message, retryable: err.retryable, cause };
13488
- }
13489
13485
 
13490
13486
  // src/execution/parallel-eternal-engine.ts
13491
13487
  function sleep2(ms) {
@@ -14634,6 +14630,10 @@ A scratchpad shared with the rest of the fleet is mounted at \`${parts.sharedScr
14634
14630
  - Use stable filenames (one file per concern); overwrite instead of appending so the Director sees the latest state.`
14635
14631
  );
14636
14632
  }
14633
+ if (parts.skills && parts.skills.trim().length > 0) {
14634
+ sections.push(`Domain knowledge:
14635
+ ${parts.skills.trim()}`);
14636
+ }
14637
14637
  if (parts.override && parts.override.trim().length > 0) {
14638
14638
  sections.push(parts.override.trim());
14639
14639
  }
@@ -15368,7 +15368,7 @@ function isValidMatrixKey(key) {
15368
15368
  return matrixKeyKind(key) !== "unknown";
15369
15369
  }
15370
15370
 
15371
- // src/coordination/director.ts
15371
+ // src/coordination/director/director-errors.ts
15372
15372
  var FleetSpawnBudgetError = class extends Error {
15373
15373
  kind;
15374
15374
  limit;
@@ -15410,6 +15410,8 @@ var FleetContextOverflowError = class extends Error {
15410
15410
  this.observed = observed;
15411
15411
  }
15412
15412
  };
15413
+
15414
+ // src/coordination/director.ts
15413
15415
  var Director = class _Director {
15414
15416
  /** Alias for the ICoordinator contract. `id` is retained for backward compatibility. */
15415
15417
  get coordinatorId() {
@@ -16476,6 +16478,7 @@ var Director = class _Director {
16476
16478
  role: config.prompt,
16477
16479
  task: taskBrief,
16478
16480
  sharedScratchpad: this.sharedScratchpadPath ?? void 0,
16481
+ skills: config.skillContent,
16479
16482
  override: config.systemPromptOverride
16480
16483
  });
16481
16484
  }
@@ -20781,6 +20784,7 @@ var MAX_TARBALL_SIZE = 50 * 1024 * 1024;
20781
20784
  async function downloadGitHubTarball(parsed) {
20782
20785
  const url = `https://api.github.com/repos/${parsed.owner}/${parsed.repo}/tarball/${parsed.ref}`;
20783
20786
  const response = await fetch(url, {
20787
+ signal: AbortSignal.timeout(3e4),
20784
20788
  headers: {
20785
20789
  Accept: "application/vnd.github+json",
20786
20790
  "User-Agent": "wrongstack-skill-installer"
@@ -21616,7 +21620,6 @@ var SessionRecovery = class {
21616
21620
  }
21617
21621
  return null;
21618
21622
  } catch {
21619
- continue;
21620
21623
  }
21621
21624
  }
21622
21625
  return null;
@@ -21847,7 +21850,7 @@ var ToolAuditLog = class {
21847
21850
  await fsp3.appendFile(fp, line, "utf8");
21848
21851
  const count = (this.unSyncedWrites.get(sessionId) ?? 0) + 1;
21849
21852
  this.unSyncedWrites.set(sessionId, count);
21850
- if (this.fsyncEvery !== Infinity && count % this.fsyncEvery === 0) {
21853
+ if (this.fsyncEvery !== Number.POSITIVE_INFINITY && count % this.fsyncEvery === 0) {
21851
21854
  await this.sync(sessionId, fp);
21852
21855
  }
21853
21856
  }
@@ -22286,6 +22289,7 @@ var CloudSync = class {
22286
22289
  async githubFetch(token, owner, repo, method, pathSegment, body) {
22287
22290
  const url = `https://api.github.com/repos/${owner}/${repo}${pathSegment}`;
22288
22291
  const res = await fetch(url, {
22292
+ signal: AbortSignal.timeout(15e3),
22289
22293
  method,
22290
22294
  headers: {
22291
22295
  Authorization: `Bearer ${token}`,
@@ -26418,7 +26422,7 @@ var InputBuilder = class {
26418
26422
  meta: { label: paragraphLabel(text) }
26419
26423
  });
26420
26424
  this.refs.push(ref);
26421
- const lines = text.split("\n").length;
26425
+ const lines = text.split(/\r?\n|\r/).length;
26422
26426
  return `[pasted #${ref.seq}, ${lines} lines]`;
26423
26427
  }
26424
26428
  /**
@@ -26475,14 +26479,16 @@ var InputBuilder = class {
26475
26479
  if (text.length >= this.pasteCharThreshold) return true;
26476
26480
  let lines = 1;
26477
26481
  for (let i = 0; i < text.length; i++) {
26478
- if (text.charCodeAt(i) === 10) lines++;
26482
+ const c = text.charCodeAt(i);
26483
+ if (c === 10) lines++;
26484
+ else if (c === 13 && text.charCodeAt(i + 1) !== 10) lines++;
26479
26485
  if (lines >= this.pasteLineThreshold) return true;
26480
26486
  }
26481
26487
  return false;
26482
26488
  }
26483
26489
  };
26484
26490
  function paragraphLabel(text) {
26485
- const lines = text.split("\n").length;
26491
+ const lines = text.split(/\r?\n|\r/).length;
26486
26492
  const bytes = Buffer.byteLength(text, "utf8");
26487
26493
  if (bytes < 1024) return `${lines} lines, ${bytes} B`;
26488
26494
  return `${lines} lines, ${(bytes / 1024).toFixed(1)} KB`;
@@ -26493,23 +26499,34 @@ var PROMPT = `You are WrongStack, a command-line AI coding agent.
26493
26499
 
26494
26500
  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.
26495
26501
 
26502
+ 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.
26503
+
26496
26504
  ## Core principles
26497
26505
 
26498
26506
  1. **Read before you write.** Always inspect the relevant files before proposing changes. Assumptions about code you haven't read are bugs in waiting.
26499
26507
  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.
26500
26508
  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.
26501
26509
  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.
26502
- 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.
26510
+ 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.)
26503
26511
  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.
26504
26512
  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.
26505
26513
  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.
26506
- 9. **Recover explicitly.** When a tool fails, state: (1) what failed, (2) what you tried, (3) what you'll attempt next. Never silently skip.
26514
+ 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.
26515
+ 10. **Recover explicitly.** When a tool fails, distinguish the failure type and respond accordingly:
26516
+
26517
+ | Failure type | Examples | Strategy |
26518
+ |---|---|---|
26519
+ | **Transient** | Timeout, rate limit, network hiccup | Retry once with adjusted params, then report |
26520
+ | **Permanent** | Syntax error, missing file, type error, permission denied | Do NOT retry \u2014 diagnose and report the root cause |
26521
+ | **Validation** | Invalid argument, out-of-range value, schema mismatch | State what was rejected and what range/format is accepted |
26522
+
26523
+ Never silently skip a failure \u2014 always report it, even when you choose not to retry.
26507
26524
 
26508
26525
  ## Decision heuristics
26509
26526
 
26510
26527
  - **Task is ambiguous** (unclear which file, conflicting requirements) \u2192 ask before proceeding
26511
26528
  - **Task is clear, approach is unknown** \u2192 try one approach, report what happened
26512
- - **Tool fails** \u2192 retry once with adjusted params, then report failure
26529
+ - **Tool fails** \u2192 classify the failure (transient/permanent/validation), then apply the appropriate recovery
26513
26530
  - **Permission prompt shown** \u2192 wait for user, do not act unilaterally
26514
26531
  - **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.
26515
26532
  - **Context window filling up** \u2192 use context_manager proactively; don't wait to be told
@@ -26540,6 +26557,8 @@ var DefaultSystemPromptBuilder = class {
26540
26557
  */
26541
26558
  envCacheByRoot = /* @__PURE__ */ new Map();
26542
26559
  skillCache;
26560
+ /** Cached full skill bodies (after frontmatter), built once per session. */
26561
+ skillBodyCache;
26543
26562
  async build(ctx) {
26544
26563
  if (this.opts.skillLoader && !this.skillCache) {
26545
26564
  try {
@@ -26547,8 +26566,8 @@ var DefaultSystemPromptBuilder = class {
26547
26566
  if (entries.length > 0) {
26548
26567
  const lines = [];
26549
26568
  for (const e of entries) {
26550
- const scopeTag = e.scope.length > 0 ? ` \u2014 ${e.scope.slice(0, 4).join(", ")}` : "";
26551
- lines.push(`- **${e.name}**${scopeTag} (${e.trigger})`);
26569
+ const shortTrigger = compactTrigger(e.trigger);
26570
+ lines.push(`- **${e.name}** (${shortTrigger})`);
26552
26571
  }
26553
26572
  this.skillCache = lines.join("\n");
26554
26573
  }
@@ -26580,6 +26599,24 @@ var DefaultSystemPromptBuilder = class {
26580
26599
  cache_control: { type: "ephemeral" }
26581
26600
  });
26582
26601
  }
26602
+ if (this.opts.modeStore && this.opts.skillLoader) {
26603
+ try {
26604
+ const activeMode = await this.opts.modeStore.getActiveMode();
26605
+ if (activeMode?.suggestedSkills && activeMode.suggestedSkills.length > 0) {
26606
+ const skills = await this.opts.skillLoader.list();
26607
+ const loadedNames = new Set(skills.map((s) => s.name));
26608
+ const available = activeMode.suggestedSkills.filter((n) => loadedNames.has(n));
26609
+ if (available.length > 0) {
26610
+ blocks.push({
26611
+ type: "text",
26612
+ text: `Mode "${activeMode.id}" works best with these skills: ${available.join(", ")}. Their full instructions are in the Active Skills block above.`,
26613
+ cache_control: { type: "ephemeral" }
26614
+ });
26615
+ }
26616
+ }
26617
+ } catch {
26618
+ }
26619
+ }
26583
26620
  if (layer6.trim()) {
26584
26621
  blocks.push({
26585
26622
  type: "text",
@@ -26810,7 +26847,13 @@ summarize it, and let the tool result hold only the summary.`);
26810
26847
  );
26811
26848
  }
26812
26849
  if (this.skillCache) {
26813
- lines.push("", "## Skills in scope for this session", this.skillCache);
26850
+ lines.push(
26851
+ "",
26852
+ "## Skills in scope for this session",
26853
+ this.skillCache,
26854
+ "",
26855
+ "Full skill instructions are injected in the Active Skills block below."
26856
+ );
26814
26857
  }
26815
26858
  const text = lines.join("\n");
26816
26859
  this.envCacheByRoot.set(ctx.projectRoot, text);
@@ -26827,6 +26870,40 @@ ${mem}`);
26827
26870
  } catch {
26828
26871
  }
26829
26872
  }
26873
+ if (this.opts.skillLoader && this.skillBodyCache === void 0) {
26874
+ try {
26875
+ const skills = await this.opts.skillLoader.list();
26876
+ if (skills.length > 0) {
26877
+ const bodies = [];
26878
+ for (const s of skills) {
26879
+ try {
26880
+ const raw = await this.opts.skillLoader.readBody(s.name);
26881
+ const body = stripFrontmatter(raw);
26882
+ if (body.trim()) {
26883
+ bodies.push(`## Skill: ${s.name}
26884
+
26885
+ ${body.trim()}`);
26886
+ }
26887
+ } catch {
26888
+ }
26889
+ }
26890
+ if (bodies.length > 0) {
26891
+ this.skillBodyCache = bodies.join("\n\n---\n\n");
26892
+ } else {
26893
+ this.skillBodyCache = "";
26894
+ }
26895
+ } else {
26896
+ this.skillBodyCache = "";
26897
+ }
26898
+ } catch {
26899
+ this.skillBodyCache = "";
26900
+ }
26901
+ }
26902
+ if (this.skillBodyCache) {
26903
+ parts.push(`# Active Skills
26904
+
26905
+ ${this.skillBodyCache}`);
26906
+ }
26830
26907
  return parts.join("\n\n");
26831
26908
  }
26832
26909
  async buildMode() {
@@ -26916,6 +26993,22 @@ ${mem}`);
26916
26993
  return langs.size === 0 ? "unknown" : Array.from(langs).join(", ");
26917
26994
  }
26918
26995
  };
26996
+ function stripFrontmatter(raw) {
26997
+ if (!raw.startsWith("---")) return raw;
26998
+ const end = raw.indexOf("\n---", 4);
26999
+ if (end === -1) return raw;
27000
+ let body = raw.slice(end + 4);
27001
+ if (body.startsWith("\n")) body = body.slice(1);
27002
+ return body;
27003
+ }
27004
+ function compactTrigger(trigger) {
27005
+ let s = trigger.replace(/^Use this skill when /i, "").replace(/^Use this skill for /i, "").replace(/^Use when /i, "").replace(/\.$/, "");
27006
+ if (s.length > 72) {
27007
+ const cut = s.lastIndexOf(" ", 68);
27008
+ s = cut > 50 ? s.slice(0, cut) + "\u2026" : s.slice(0, 68) + "\u2026";
27009
+ }
27010
+ return s;
27011
+ }
26919
27012
 
26920
27013
  // src/registry/tool-registry.ts
26921
27014
  var ToolRegistry = class _ToolRegistry {