@wrongstack/core 0.309.0 → 0.309.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.
- package/dist/coordination/director.d.ts +7 -0
- package/dist/coordination/explore-companion.d.ts +9 -6
- package/dist/coordination/index.js +331 -59
- package/dist/coordination/mutation-engine.d.ts +5 -3
- package/dist/core/index.js +39 -9
- package/dist/defaults/index.js +479 -101
- package/dist/execution/index.js +27 -9
- package/dist/hq/index.js +45 -5
- package/dist/index.js +640 -131
- package/dist/infrastructure/index.js +22 -3
- package/dist/observability/index.js +1 -1
- package/dist/plugin/index.js +113 -12
- package/dist/prompts/index.js +360 -3
- package/dist/security/auto-approve-policy.d.ts +2 -2
- package/dist/security/index.js +177 -50
- package/dist/security/permission-helpers.d.ts +11 -0
- package/dist/security/permission-policy.d.ts +10 -1
- package/dist/security/yolo-risk.d.ts +17 -0
- package/dist/session-catalog/index.js +32 -2
- package/dist/session-catalog/project-server.js +32 -2
- package/dist/skills/index.js +39 -6
- package/dist/storage/index.js +44 -3
- package/dist/types/tool.d.ts +15 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +54 -4
- package/dist/utils/terminal-sanitize.d.ts +41 -0
- package/dist/utils/tool-subject.d.ts +1 -1
- package/instructions/agents/chaos-monkey.md +5 -1
- package/package.json +4 -4
package/dist/execution/index.js
CHANGED
|
@@ -17098,11 +17098,13 @@ var CHAOS_MONKEY_AGENT = {
|
|
|
17098
17098
|
tools: [...TOOLS.build],
|
|
17099
17099
|
skillNames: ["testing", "typescript-strict"],
|
|
17100
17100
|
spawnBudgetExempt: true,
|
|
17101
|
-
//
|
|
17102
|
-
//
|
|
17103
|
-
//
|
|
17104
|
-
//
|
|
17105
|
-
|
|
17101
|
+
// Run in the live checkout: mutation targets are usually freshly
|
|
17102
|
+
// written and uncommitted — a worktree spawned from HEAD would not
|
|
17103
|
+
// contain them and every mutant would drift. The mutation_test tool
|
|
17104
|
+
// honors this value as its default; callers can still override per
|
|
17105
|
+
// call via its `chaosWorktree` input when targets are committed and
|
|
17106
|
+
// isolation is wanted.
|
|
17107
|
+
worktree: "off",
|
|
17106
17108
|
// Report travels via submit_result + final text, not the leader's stream.
|
|
17107
17109
|
textStream: "silent",
|
|
17108
17110
|
toolStream: "silent"
|
|
@@ -20441,6 +20443,10 @@ var DefaultSkillLoader = class {
|
|
|
20441
20443
|
);
|
|
20442
20444
|
for (const e of entries) {
|
|
20443
20445
|
if (!await entryIsDirectory(dir, e)) continue;
|
|
20446
|
+
if (!isValidSkillNameFormat(e.name)) {
|
|
20447
|
+
this.skipped.push({ dir, entry: e.name, reason: "invalid-name-format" });
|
|
20448
|
+
continue;
|
|
20449
|
+
}
|
|
20444
20450
|
const skillFile = path15.join(dir, e.name, "SKILL.md");
|
|
20445
20451
|
let raw;
|
|
20446
20452
|
try {
|
|
@@ -21510,9 +21516,21 @@ function renderCommandLine(command, args) {
|
|
|
21510
21516
|
});
|
|
21511
21517
|
return [command, ...rendered].join(" ");
|
|
21512
21518
|
}
|
|
21513
|
-
function
|
|
21519
|
+
function renderSubjectFields(obj, fields) {
|
|
21520
|
+
const parts = [];
|
|
21521
|
+
for (const field of fields) {
|
|
21522
|
+
const value = obj[field];
|
|
21523
|
+
if (value === void 0 || value === null || value === "" || value === false) continue;
|
|
21524
|
+
const str = String(value);
|
|
21525
|
+
parts.push(`${field}=${/\s/.test(str) ? `"${str.replace(/"/g, '\\"')}"` : str}`);
|
|
21526
|
+
}
|
|
21527
|
+
return parts.join(" ");
|
|
21528
|
+
}
|
|
21529
|
+
function subjectForToolInput(toolName, input, subjectKey, subjectFields) {
|
|
21514
21530
|
if (!input || typeof input !== "object") return void 0;
|
|
21515
21531
|
const obj = input;
|
|
21532
|
+
const extra = subjectFields && subjectFields.length > 0 ? renderSubjectFields(obj, subjectFields) : "";
|
|
21533
|
+
const withExtra = (base) => extra ? `${base} ${extra}` : base;
|
|
21516
21534
|
if (subjectKey) {
|
|
21517
21535
|
const value = obj[subjectKey];
|
|
21518
21536
|
if (Array.isArray(value)) {
|
|
@@ -21528,9 +21546,9 @@ function subjectForToolInput(toolName, input, subjectKey) {
|
|
|
21528
21546
|
if (subjectKey === "command") {
|
|
21529
21547
|
const rendered = renderCommandLine(value, obj["args"]);
|
|
21530
21548
|
if (value === "commit" && obj["dry_run"] === true) {
|
|
21531
|
-
return `${escapeGlobSubject(rendered)}:dry-run`;
|
|
21549
|
+
return `${escapeGlobSubject(withExtra(rendered))}:dry-run`;
|
|
21532
21550
|
}
|
|
21533
|
-
return escapeGlobSubject(rendered);
|
|
21551
|
+
return escapeGlobSubject(withExtra(rendered));
|
|
21534
21552
|
}
|
|
21535
21553
|
if (subjectKey === "directory" && obj["dry_run"] === true) {
|
|
21536
21554
|
return `${escapeGlobSubject(value)}:dry-run`;
|
|
@@ -22781,7 +22799,7 @@ var ToolExecutor = class _ToolExecutor {
|
|
|
22781
22799
|
return { result, tool, durationMs: Date.now() - start };
|
|
22782
22800
|
}
|
|
22783
22801
|
if (effectivePermission === "confirm") {
|
|
22784
|
-
const suggestedPattern = boundary.decision === "confirm" ? `kanban-boundary:${boundary.path ?? tool.name}` : subjectForToolInput(tool.name, use.input, tool.subjectKey) ?? tool.name;
|
|
22802
|
+
const suggestedPattern = boundary.decision === "confirm" ? `kanban-boundary:${boundary.path ?? tool.name}` : subjectForToolInput(tool.name, use.input, tool.subjectKey, tool.subjectFields) ?? tool.name;
|
|
22785
22803
|
if (this.opts.confirmAwaiter) {
|
|
22786
22804
|
const awaiter = this.opts.confirmAwaiter;
|
|
22787
22805
|
const choice = await new Promise(
|
package/dist/hq/index.js
CHANGED
|
@@ -702,6 +702,14 @@ var PATTERNS = [
|
|
|
702
702
|
anchor: "sk-ant-"
|
|
703
703
|
},
|
|
704
704
|
{ type: "openai_key", regex: /(?<![A-Za-z0-9])sk-(?:proj-)?[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g, anchor: "sk-" },
|
|
705
|
+
{
|
|
706
|
+
// `xai` is a first-class provider in this codebase, but its key shape was
|
|
707
|
+
// absent here — so the one credential format WrongStack itself hands users
|
|
708
|
+
// was the one the scrubber could not recognize (audit 2026-08-20).
|
|
709
|
+
type: "xai_key",
|
|
710
|
+
regex: /(?<![A-Za-z0-9])xai-[A-Za-z0-9]{20,}(?![A-Za-z0-9])/g,
|
|
711
|
+
anchor: "xai-"
|
|
712
|
+
},
|
|
705
713
|
{ type: "github_pat", regex: /(?<![A-Za-z0-9])ghp_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g, anchor: "ghp_" },
|
|
706
714
|
{ type: "github_pat_v2", regex: /(?<![A-Za-z0-9])github_pat_[A-Za-z0-9_]{50,}(?![A-Za-z0-9])/g, anchor: "github_pat_" },
|
|
707
715
|
{ type: "aws_access_key", regex: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}(?![A-Za-z0-9])/g, anchor: "AKIA" },
|
|
@@ -792,8 +800,8 @@ var PATTERNS = [
|
|
|
792
800
|
// replacement so the separator between adjacent secrets is preserved
|
|
793
801
|
// rather than collapsed. Capture groups are therefore: 1=leading
|
|
794
802
|
// delimiter, 2=key name, 3=value.
|
|
795
|
-
regex: /(^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?=\s|$)/g,
|
|
796
|
-
anchor: ["KEY", "TOKEN", "SECRET", "PASSWORD", "PWD"]
|
|
803
|
+
regex: /(^|\s)([A-Z_]{4,}(?:KEY|TOKEN|SECRET|PASSWORD|PWD|PASSPHRASE))\s*[:=]\s*['"]?([A-Za-z0-9_/+=-]{20,512})['"]?(?=\s|$)/g,
|
|
804
|
+
anchor: ["KEY", "TOKEN", "SECRET", "PASSWORD", "PWD", "PASSPHRASE"]
|
|
797
805
|
},
|
|
798
806
|
{
|
|
799
807
|
type: "json_credential_key",
|
|
@@ -910,6 +918,27 @@ var JSON_CREDENTIAL_REGEX = PATTERNS.find((p) => p.type === "json_credential_key
|
|
|
910
918
|
var COMBINED_REPLACEMENTS = SIMPLE_PATTERNS.map((p) => `[REDACTED:${p.type}]`);
|
|
911
919
|
var SCRUB_CHUNK_BYTES = 64 * 1024;
|
|
912
920
|
var SCRUB_OVERLAP_BYTES = 1024;
|
|
921
|
+
var PEM_PRIVATE_KEY_BEGIN_RE = /-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP)? ?PRIVATE KEY-----/;
|
|
922
|
+
var PEM_END_MARKER = "-----END";
|
|
923
|
+
var MAX_PEM_BLOCK_BYTES = 64 * 1024;
|
|
924
|
+
var PEM_END_LINE_TOLERANCE = 64;
|
|
925
|
+
function extendChunkBoundaryPastPem(text, chunkStart, proposedEnd) {
|
|
926
|
+
const head = text.slice(chunkStart, proposedEnd);
|
|
927
|
+
const lastBegin = head.lastIndexOf("-----BEGIN ");
|
|
928
|
+
if (lastBegin === -1) return proposedEnd;
|
|
929
|
+
const fromBegin = text.slice(chunkStart + lastBegin);
|
|
930
|
+
const marker = PEM_PRIVATE_KEY_BEGIN_RE.exec(fromBegin);
|
|
931
|
+
if (!marker || marker.index !== 0) return proposedEnd;
|
|
932
|
+
const bodyStart = marker[0].length;
|
|
933
|
+
const cap = Math.min(text.length, chunkStart + lastBegin + MAX_PEM_BLOCK_BYTES);
|
|
934
|
+
const closeIdx = fromBegin.indexOf(PEM_END_MARKER, bodyStart);
|
|
935
|
+
if (closeIdx === -1 || chunkStart + lastBegin + closeIdx >= cap + PEM_END_LINE_TOLERANCE) {
|
|
936
|
+
return proposedEnd;
|
|
937
|
+
}
|
|
938
|
+
const lineEnd = fromBegin.indexOf("\n", closeIdx);
|
|
939
|
+
const end = lineEnd === -1 ? text.length : chunkStart + lastBegin + lineEnd + 1;
|
|
940
|
+
return Math.max(proposedEnd, end);
|
|
941
|
+
}
|
|
913
942
|
var PATTERN_ANCHORS = [
|
|
914
943
|
...new Set(
|
|
915
944
|
PATTERNS.flatMap(
|
|
@@ -946,6 +975,7 @@ var DefaultSecretScrubber = class {
|
|
|
946
975
|
}
|
|
947
976
|
}
|
|
948
977
|
end = safe === -1 ? end : safe + 1;
|
|
978
|
+
end = extendChunkBoundaryPastPem(text, i, end);
|
|
949
979
|
}
|
|
950
980
|
out.push(this.scrubOne(text.slice(i, end)));
|
|
951
981
|
i = end;
|
|
@@ -3080,6 +3110,15 @@ function deriveSessionStatus(agents) {
|
|
|
3080
3110
|
(a) => a.status === "running" || a.status === "streaming" || a.status === "waiting_user"
|
|
3081
3111
|
) ? "active" : "idle";
|
|
3082
3112
|
}
|
|
3113
|
+
function downgradeStaleAgentStatuses(agents, nowMs) {
|
|
3114
|
+
const cutoff = nowMs - HQ_STALE_SNAPSHOT_WINDOW_MS;
|
|
3115
|
+
return agents.map((agent) => {
|
|
3116
|
+
if (agent.status !== "running" && agent.status !== "streaming") return agent;
|
|
3117
|
+
const lastActivityAt = Date.parse(agent.lastActivityAt);
|
|
3118
|
+
if (!Number.isFinite(lastActivityAt) || lastActivityAt >= cutoff) return agent;
|
|
3119
|
+
return { ...agent, status: "idle" };
|
|
3120
|
+
});
|
|
3121
|
+
}
|
|
3083
3122
|
function startSessionTelemetryBridge(opts) {
|
|
3084
3123
|
const now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
3085
3124
|
const publisher = opts.publisher;
|
|
@@ -3100,6 +3139,7 @@ function startSessionTelemetryBridge(opts) {
|
|
|
3100
3139
|
let lastPublishedAtMs = Date.now();
|
|
3101
3140
|
let disposed = false;
|
|
3102
3141
|
function buildSnapshot() {
|
|
3142
|
+
const effectiveAgents = downgradeStaleAgentStatuses(agents, Date.parse(now()));
|
|
3103
3143
|
return {
|
|
3104
3144
|
sessionId: opts.sessionId,
|
|
3105
3145
|
clientKind: identity.kind,
|
|
@@ -3107,11 +3147,11 @@ function startSessionTelemetryBridge(opts) {
|
|
|
3107
3147
|
projectId: project.projectId,
|
|
3108
3148
|
projectName: opts.projectName ?? project.projectName,
|
|
3109
3149
|
projectRoot: opts.projectRoot,
|
|
3110
|
-
status: deriveSessionStatus(
|
|
3150
|
+
status: deriveSessionStatus(effectiveAgents),
|
|
3111
3151
|
startedAt,
|
|
3112
3152
|
lastActivityAt,
|
|
3113
|
-
agentCount:
|
|
3114
|
-
agents,
|
|
3153
|
+
agentCount: effectiveAgents.length,
|
|
3154
|
+
agents: effectiveAgents,
|
|
3115
3155
|
...identity.hostname !== void 0 ? { hostname: identity.hostname } : {},
|
|
3116
3156
|
...identity.pid !== void 0 ? { pid: identity.pid } : {},
|
|
3117
3157
|
...opts.gitBranch !== void 0 ? { gitBranch: opts.gitBranch } : {}
|