@wrongstack/core 0.9.4 → 0.9.19

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-subagent-runner-DaF_EgRG.d.ts → agent-subagent-runner-C4qt9e5Y.d.ts} +1 -1
  2. package/dist/{config-SkMIDN9L.d.ts → config-CWva0qoL.d.ts} +4 -0
  3. package/dist/coordination/index.d.ts +8 -7
  4. package/dist/coordination/index.js +672 -46
  5. package/dist/coordination/index.js.map +1 -1
  6. package/dist/defaults/index.d.ts +12 -11
  7. package/dist/defaults/index.js +780 -23
  8. package/dist/defaults/index.js.map +1 -1
  9. package/dist/execution/index.d.ts +7 -6
  10. package/dist/execution/index.js +1 -0
  11. package/dist/execution/index.js.map +1 -1
  12. package/dist/extension/index.d.ts +4 -3
  13. package/dist/{index-CP8638Wm.d.ts → index-aizK8olO.d.ts} +3 -2
  14. package/dist/{index-Bsha5K4D.d.ts → index-p95HQ22A.d.ts} +3 -2
  15. package/dist/index.d.ts +22 -16
  16. package/dist/index.js +861 -35
  17. package/dist/index.js.map +1 -1
  18. package/dist/infrastructure/index.d.ts +2 -2
  19. package/dist/kernel/index.d.ts +4 -3
  20. package/dist/{mcp-servers-BouUWYW6.d.ts → mcp-servers-BkVEqkRe.d.ts} +1 -1
  21. package/dist/{multi-agent-coordinator-DTXF2aAl.d.ts → multi-agent-coordinator-bRaI_aD1.d.ts} +1 -1
  22. package/dist/{null-fleet-bus-Chrc_3Pp.d.ts → null-fleet-bus-DKM3Iy9d.d.ts} +183 -3
  23. package/dist/{secret-scrubber-DttNiGYA.d.ts → permission-bPuzAy4x.d.ts} +1 -6
  24. package/dist/{permission-policy-BpCGYBud.d.ts → permission-policy-BUQSutpl.d.ts} +8 -1
  25. package/dist/{plan-templates-envSmNlZ.d.ts → plan-templates-fkQTyz3U.d.ts} +25 -1
  26. package/dist/sdd/index.d.ts +5 -4
  27. package/dist/sdd/index.js +1 -0
  28. package/dist/sdd/index.js.map +1 -1
  29. package/dist/secret-scrubber-3MHDDAtm.d.ts +6 -0
  30. package/dist/{secret-scrubber-QSeI0ADi.d.ts → secret-scrubber-7rSC_emZ.d.ts} +1 -1
  31. package/dist/security/index.d.ts +4 -3
  32. package/dist/security/index.js +37 -6
  33. package/dist/security/index.js.map +1 -1
  34. package/dist/storage/index.d.ts +3 -2
  35. package/dist/storage/index.js +88 -5
  36. package/dist/storage/index.js.map +1 -1
  37. package/dist/{tool-executor-CsktM3h9.d.ts → tool-executor-Boo3dekH.d.ts} +1 -1
  38. package/dist/types/index.d.ts +6 -5
  39. package/dist/types/index.js.map +1 -1
  40. package/dist/utils/index.d.ts +12 -1
  41. package/dist/utils/index.js +85 -1
  42. package/dist/utils/index.js.map +1 -1
  43. package/package.json +1 -1
  44. package/skills/api-design/SKILL.md +139 -0
  45. package/skills/audit-log/SKILL.md +87 -14
  46. package/skills/bug-hunter/SKILL.md +42 -19
  47. package/skills/docker-deploy/SKILL.md +155 -0
  48. package/skills/git-flow/SKILL.md +53 -1
  49. package/skills/multi-agent/SKILL.md +42 -0
  50. package/skills/node-modern/SKILL.md +57 -1
  51. package/skills/observability/SKILL.md +134 -0
  52. package/skills/prompt-engineering/SKILL.md +46 -19
  53. package/skills/react-modern/SKILL.md +92 -1
  54. package/skills/refactor-planner/SKILL.md +49 -1
  55. package/skills/sdd/SKILL.md +12 -1
  56. package/skills/security-scanner/SKILL.md +46 -1
  57. package/skills/skill-creator/SKILL.md +49 -52
  58. package/skills/testing/SKILL.md +170 -0
  59. package/skills/typescript-strict/SKILL.md +98 -1
@@ -170,9 +170,11 @@ function isEmptyMessage(msg) {
170
170
  var DefaultSessionStore = class {
171
171
  dir;
172
172
  events;
173
+ secretScrubber;
173
174
  constructor(opts) {
174
175
  this.dir = opts.dir;
175
176
  this.events = opts.events;
177
+ this.secretScrubber = opts.secretScrubber;
176
178
  }
177
179
  /** Join session ID to its absolute path within the store directory. */
178
180
  sessionPath(id, ext) {
@@ -197,7 +199,11 @@ var DefaultSessionStore = class {
197
199
  );
198
200
  }
199
201
  try {
200
- return new FileSessionWriter(id, handle, startedAt, meta, this.events, { dir: shardDir, filePath: file });
202
+ return new FileSessionWriter(id, handle, startedAt, meta, this.events, {
203
+ dir: shardDir,
204
+ filePath: file,
205
+ secretScrubber: this.secretScrubber
206
+ });
201
207
  } catch (err) {
202
208
  await handle.close().catch(() => {
203
209
  });
@@ -227,7 +233,7 @@ var DefaultSessionStore = class {
227
233
  provider: data.metadata.provider
228
234
  },
229
235
  this.events,
230
- { resumed: true, dir: this.dir, filePath: file }
236
+ { resumed: true, dir: this.dir, filePath: file, secretScrubber: this.secretScrubber }
231
237
  );
232
238
  return { writer, data };
233
239
  } catch (err) {
@@ -433,6 +439,7 @@ var FileSessionWriter = class {
433
439
  this.resumed = opts.resumed ?? false;
434
440
  this.manifestFile = opts.dir ? path7.join(opts.dir, `${id}.summary.json`) : "";
435
441
  this.filePath = opts.filePath ?? "";
442
+ this.secretScrubber = opts.secretScrubber;
436
443
  this.summary = {
437
444
  id,
438
445
  title: "(empty session)",
@@ -461,6 +468,29 @@ var FileSessionWriter = class {
461
468
  resumed;
462
469
  appendFailCount = 0;
463
470
  lastAppendWarnAt = 0;
471
+ secretScrubber;
472
+ /**
473
+ * Scrub secrets out of conversation-turn events before they are observed
474
+ * for the summary, written to the JSONL log, or surfaced on resume. Only
475
+ * `user_input` / `llm_response` carry free-form user/model text; other event
476
+ * types either have no secret-bearing content or are already scrubbed
477
+ * upstream (tool results). Returns the event unchanged when no scrubber is
478
+ * configured.
479
+ */
480
+ scrubEvent(event) {
481
+ const s = this.secretScrubber;
482
+ if (!s) return event;
483
+ if (event.type === "user_input") {
484
+ return {
485
+ ...event,
486
+ content: typeof event.content === "string" ? s.scrub(event.content) : s.scrubObject(event.content)
487
+ };
488
+ }
489
+ if (event.type === "llm_response") {
490
+ return { ...event, content: s.scrubObject(event.content) };
491
+ }
492
+ return event;
493
+ }
464
494
  promptIndex = 0;
465
495
  pendingFileSnapshots = [];
466
496
  /** Tracks open tool_use IDs during the current run to serialize on close for resume. */
@@ -493,9 +523,10 @@ var FileSessionWriter = class {
493
523
  this.initDone = true;
494
524
  await this.writeSessionStartLazy();
495
525
  }
496
- this.observeForSummary(event);
526
+ const scrubbed = this.scrubEvent(event);
527
+ this.observeForSummary(scrubbed);
497
528
  try {
498
- await this.handle.appendFile(`${JSON.stringify(event)}
529
+ await this.handle.appendFile(`${JSON.stringify(scrubbed)}
499
530
  `, "utf8");
500
531
  } catch (err) {
501
532
  this.appendFailCount++;
@@ -1349,6 +1380,40 @@ var DefaultConfigLoader = class {
1349
1380
  }
1350
1381
  return Object.freeze(cfg);
1351
1382
  }
1383
+ /**
1384
+ * Persist a sync config to ~/.wrongstack/sync.json, with the token encrypted
1385
+ * by the vault (if provided). The file is isolated from the main config
1386
+ * hierarchy to prevent accidental commits.
1387
+ */
1388
+ async persistSyncConfig(cfg) {
1389
+ let toWrite = { ...cfg };
1390
+ if (this.vault && toWrite.githubToken && !toWrite.githubToken.startsWith("enc:")) {
1391
+ toWrite = { ...toWrite, githubToken: this.vault.encrypt(toWrite.githubToken) };
1392
+ }
1393
+ await atomicWrite(this.paths.syncConfig, JSON.stringify(toWrite, null, 2), { mode: 384 });
1394
+ }
1395
+ /**
1396
+ * Read ~/.wrongstack/sync.json (encrypted GitHub token storage) and decrypt
1397
+ * the token if a vault is available. Returns null if the file doesn't exist.
1398
+ * This is separate from main config loading because sync.json is intentionally
1399
+ * isolated — it should never be part of project-local or env-driven config.
1400
+ */
1401
+ async loadSyncConfig() {
1402
+ try {
1403
+ const raw = await fsp.readFile(this.paths.syncConfig, "utf8");
1404
+ const parsed = safeParse(raw);
1405
+ if (!parsed.ok || !parsed.value) return null;
1406
+ if (this.vault) {
1407
+ const decrypted = decryptConfigSecrets({ sync: parsed.value }, this.vault);
1408
+ return decrypted.sync ?? null;
1409
+ }
1410
+ return parsed.value;
1411
+ } catch (err) {
1412
+ if (err.code === "ENOENT") return null;
1413
+ console.warn("[config] Failed to load sync config:", err);
1414
+ return null;
1415
+ }
1416
+ }
1352
1417
  async readJson(file) {
1353
1418
  let raw;
1354
1419
  try {
@@ -2904,7 +2969,25 @@ var CloudSync = class {
2904
2969
  baseTreeSha,
2905
2970
  `Sync ${cfg.categories.join(", ")} \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`
2906
2971
  );
2907
- await this.updateRef(token, owner, repoName, branch, commitSha);
2972
+ try {
2973
+ await this.updateRef(token, owner, repoName, branch, commitSha);
2974
+ } catch (err) {
2975
+ if (err instanceof Error && err.message.includes("422")) {
2976
+ const remote = await this.getRef(token, owner, repoName, branch);
2977
+ const currentSha = remote.object.sha;
2978
+ const rebasedCommitSha = await this.createCommit(
2979
+ token,
2980
+ owner,
2981
+ repoName,
2982
+ newTreeSha,
2983
+ currentSha,
2984
+ `Sync ${cfg.categories.join(", ")} \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`
2985
+ );
2986
+ await this.updateRef(token, owner, repoName, branch, rebasedCommitSha);
2987
+ } else {
2988
+ throw err;
2989
+ }
2990
+ }
2908
2991
  const syncState = {
2909
2992
  version: 1,
2910
2993
  sha: commitSha,