@wrongstack/tools 0.297.0 → 0.298.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.
- package/dist/_spawn-stream.d.ts +2 -0
- package/dist/_util.d.ts +29 -1
- package/dist/audit.js +113 -65
- package/dist/bash.js +5 -4
- package/dist/batch-tool-use.js +70 -7
- package/dist/browser/index.js +31 -1
- package/dist/builtin.js +841 -351
- package/dist/codebase-index/index.js +68 -16
- package/dist/codebase-index/project-server-protocol.d.ts +26 -0
- package/dist/codebase-index/project-server.js +60 -16
- package/dist/codebase-index/worker.js +36 -13
- package/dist/codebase-index/writer-search-helpers.d.ts +16 -0
- package/dist/codebase-index/writer.d.ts +13 -1
- package/dist/design.d.ts +1 -1
- package/dist/design.js +4 -3
- package/dist/diff.js +11 -1
- package/dist/e2e.js +9 -6
- package/dist/edit.js +9 -6
- package/dist/exec.js +560 -529
- package/dist/format.js +116 -65
- package/dist/git.js +22 -2
- package/dist/glob.js +11 -5
- package/dist/grep.js +160 -104
- package/dist/index.js +792 -290
- package/dist/install.js +120 -68
- package/dist/json.js +64 -18
- package/dist/kanban-board-inputs.d.ts +21 -4
- package/dist/kanban.js +20 -5
- package/dist/languages/index.js +128 -71
- package/dist/lint.js +113 -65
- package/dist/outdated.js +86 -26
- package/dist/pack.js +841 -351
- package/dist/patch.js +11 -1
- package/dist/plan.js +32 -10
- package/dist/read.js +77 -23
- package/dist/replace.js +11 -3
- package/dist/scaffold.js +9 -6
- package/dist/session-kanban.js +21 -5
- package/dist/task.js +3 -1
- package/dist/test.js +113 -65
- package/dist/todo.js +3 -1
- package/dist/tool-tier.js +841 -351
- package/dist/tool-use.d.ts +1 -1
- package/dist/tool-use.js +28 -4
- package/dist/tree.d.ts +1 -0
- package/dist/tree.js +44 -8
- package/dist/typecheck.js +113 -65
- package/dist/write.js +9 -6
- package/package.json +5 -4
- package/dist/_concurrency.d.ts.map +0 -1
- package/dist/_danger-detect.d.ts.map +0 -1
- package/dist/_edit-match.d.ts.map +0 -1
- package/dist/_env.d.ts.map +0 -1
- package/dist/_fetch-guard.d.ts.map +0 -1
- package/dist/_output-spool.d.ts.map +0 -1
- package/dist/_redact-command.d.ts.map +0 -1
- package/dist/_regex.d.ts.map +0 -1
- package/dist/_session-shell.d.ts.map +0 -1
- package/dist/_shell-pick.d.ts.map +0 -1
- package/dist/_spawn-stream.d.ts.map +0 -1
- package/dist/_syntax-check.d.ts.map +0 -1
- package/dist/_util.d.ts.map +0 -1
- package/dist/_win32-resolve.d.ts.map +0 -1
- package/dist/audit.d.ts.map +0 -1
- package/dist/audit.js.map +0 -7
- package/dist/auto-proceed-loop-guard.d.ts.map +0 -1
- package/dist/auto-proceed-loop-guard.js.map +0 -7
- package/dist/bash-kill-guard.d.ts.map +0 -1
- package/dist/bash.d.ts.map +0 -1
- package/dist/bash.js.map +0 -7
- package/dist/batch-tool-use.d.ts.map +0 -1
- package/dist/batch-tool-use.js.map +0 -7
- package/dist/browser/artifacts.d.ts.map +0 -1
- package/dist/browser/index.d.ts.map +0 -1
- package/dist/browser/index.js.map +0 -7
- package/dist/browser/manager.d.ts.map +0 -1
- package/dist/browser/network-guard-proxy.d.ts.map +0 -1
- package/dist/browser/security.d.ts.map +0 -1
- package/dist/browser/tools.d.ts.map +0 -1
- package/dist/browser/types.d.ts.map +0 -1
- package/dist/builtin.d.ts.map +0 -1
- package/dist/builtin.js.map +0 -7
- package/dist/circuit-breaker.d.ts.map +0 -1
- package/dist/circuit-breaker.js.map +0 -7
- package/dist/codebase-index/background-indexer.d.ts.map +0 -1
- package/dist/codebase-index/bm25.d.ts.map +0 -1
- package/dist/codebase-index/circuit-breaker.d.ts.map +0 -1
- package/dist/codebase-index/codebase-index-tool.d.ts.map +0 -1
- package/dist/codebase-index/codebase-search-tool.d.ts.map +0 -1
- package/dist/codebase-index/codebase-stats-tool.d.ts.map +0 -1
- package/dist/codebase-index/dead-code-scan.d.ts.map +0 -1
- package/dist/codebase-index/generic-parser.d.ts.map +0 -1
- package/dist/codebase-index/gitignore.d.ts.map +0 -1
- package/dist/codebase-index/go-parser.d.ts.map +0 -1
- package/dist/codebase-index/index-service.d.ts.map +0 -1
- package/dist/codebase-index/index.d.ts.map +0 -1
- package/dist/codebase-index/index.js.map +0 -7
- package/dist/codebase-index/indexer.d.ts.map +0 -1
- package/dist/codebase-index/json-parser.d.ts.map +0 -1
- package/dist/codebase-index/languages.d.ts.map +0 -1
- package/dist/codebase-index/lsp-kind.d.ts.map +0 -1
- package/dist/codebase-index/parser-dispatch.d.ts.map +0 -1
- package/dist/codebase-index/project-server-cache.d.ts.map +0 -1
- package/dist/codebase-index/project-server-client.d.ts.map +0 -1
- package/dist/codebase-index/project-server-endpoint.d.ts.map +0 -1
- package/dist/codebase-index/project-server-protocol.d.ts.map +0 -1
- package/dist/codebase-index/project-server.d.ts.map +0 -1
- package/dist/codebase-index/project-server.js.map +0 -7
- package/dist/codebase-index/py-parser.d.ts.map +0 -1
- package/dist/codebase-index/refs-extractor.d.ts.map +0 -1
- package/dist/codebase-index/rs-parser.d.ts.map +0 -1
- package/dist/codebase-index/schema.d.ts.map +0 -1
- package/dist/codebase-index/spawn-gate.d.ts.map +0 -1
- package/dist/codebase-index/sqlite-runtime.d.ts.map +0 -1
- package/dist/codebase-index/ts-parser.d.ts.map +0 -1
- package/dist/codebase-index/worker-protocol.d.ts.map +0 -1
- package/dist/codebase-index/worker.d.ts.map +0 -1
- package/dist/codebase-index/worker.js.map +0 -7
- package/dist/codebase-index/writer-admin.d.ts.map +0 -1
- package/dist/codebase-index/writer-bulk-insert.d.ts.map +0 -1
- package/dist/codebase-index/writer-graph-helpers.d.ts.map +0 -1
- package/dist/codebase-index/writer-graph-reader.d.ts.map +0 -1
- package/dist/codebase-index/writer-helpers.d.ts.map +0 -1
- package/dist/codebase-index/writer-pragmas.d.ts.map +0 -1
- package/dist/codebase-index/writer-ref-mapper.d.ts.map +0 -1
- package/dist/codebase-index/writer-schema.d.ts.map +0 -1
- package/dist/codebase-index/writer-search-helpers.d.ts.map +0 -1
- package/dist/codebase-index/writer-store-pool.d.ts.map +0 -1
- package/dist/codebase-index/writer.d.ts.map +0 -1
- package/dist/codebase-index/yaml-parser.d.ts.map +0 -1
- package/dist/design.d.ts.map +0 -1
- package/dist/design.js.map +0 -7
- package/dist/diff.d.ts.map +0 -1
- package/dist/diff.js.map +0 -7
- package/dist/document.d.ts.map +0 -1
- package/dist/document.js.map +0 -7
- package/dist/e2e.d.ts.map +0 -1
- package/dist/e2e.js.map +0 -7
- package/dist/edit.d.ts.map +0 -1
- package/dist/edit.js.map +0 -7
- package/dist/exec-kill-guard.d.ts.map +0 -1
- package/dist/exec.d.ts.map +0 -1
- package/dist/exec.js.map +0 -7
- package/dist/fetch.d.ts.map +0 -1
- package/dist/fetch.js.map +0 -7
- package/dist/format.d.ts.map +0 -1
- package/dist/format.js.map +0 -7
- package/dist/git.d.ts.map +0 -1
- package/dist/git.js.map +0 -7
- package/dist/glob.d.ts.map +0 -1
- package/dist/glob.js.map +0 -7
- package/dist/grep.d.ts.map +0 -1
- package/dist/grep.js.map +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -7
- package/dist/install.d.ts.map +0 -1
- package/dist/install.js.map +0 -7
- package/dist/json.d.ts.map +0 -1
- package/dist/json.js.map +0 -7
- package/dist/kanban-board-inputs.d.ts.map +0 -1
- package/dist/kanban-decomposition-actions.d.ts.map +0 -1
- package/dist/kanban-detail-actions.d.ts.map +0 -1
- package/dist/kanban-evidence-bridge.d.ts.map +0 -1
- package/dist/kanban-presence.d.ts.map +0 -1
- package/dist/kanban-split-task-handler.d.ts.map +0 -1
- package/dist/kanban-task-inputs.d.ts.map +0 -1
- package/dist/kanban-tool-results.d.ts.map +0 -1
- package/dist/kanban-tool-schema.d.ts.map +0 -1
- package/dist/kanban-tool-types.d.ts.map +0 -1
- package/dist/kanban.d.ts.map +0 -1
- package/dist/kanban.js.map +0 -7
- package/dist/languages/detect.d.ts.map +0 -1
- package/dist/languages/diagnostics.d.ts.map +0 -1
- package/dist/languages/execute-tool.d.ts.map +0 -1
- package/dist/languages/execute.d.ts.map +0 -1
- package/dist/languages/index.d.ts.map +0 -1
- package/dist/languages/index.js.map +0 -7
- package/dist/languages/legacy-bridge.d.ts.map +0 -1
- package/dist/languages/package-tool.d.ts.map +0 -1
- package/dist/languages/plan.d.ts.map +0 -1
- package/dist/languages/profile-helpers.d.ts.map +0 -1
- package/dist/languages/profiles/additional.d.ts.map +0 -1
- package/dist/languages/profiles/primary.d.ts.map +0 -1
- package/dist/languages/registry.d.ts.map +0 -1
- package/dist/languages/tool.d.ts.map +0 -1
- package/dist/languages/types.d.ts.map +0 -1
- package/dist/lint.d.ts.map +0 -1
- package/dist/lint.js.map +0 -7
- package/dist/logs.d.ts.map +0 -1
- package/dist/logs.js.map +0 -7
- package/dist/memory.d.ts.map +0 -1
- package/dist/memory.js.map +0 -7
- package/dist/mode.d.ts.map +0 -1
- package/dist/mode.js.map +0 -7
- package/dist/next-steps.d.ts.map +0 -1
- package/dist/next-steps.js.map +0 -7
- package/dist/outdated.d.ts.map +0 -1
- package/dist/outdated.js.map +0 -7
- package/dist/pack.d.ts.map +0 -1
- package/dist/pack.js.map +0 -7
- package/dist/patch.d.ts.map +0 -1
- package/dist/patch.js.map +0 -7
- package/dist/plan.d.ts.map +0 -1
- package/dist/plan.js.map +0 -7
- package/dist/process-guardian.d.ts.map +0 -1
- package/dist/process-registry-persistent.d.ts.map +0 -1
- package/dist/process-registry.d.ts.map +0 -1
- package/dist/process-registry.js.map +0 -7
- package/dist/ps-slash.d.ts.map +0 -1
- package/dist/ps-slash.js.map +0 -7
- package/dist/read.d.ts.map +0 -1
- package/dist/read.js.map +0 -7
- package/dist/replace.d.ts.map +0 -1
- package/dist/replace.js.map +0 -7
- package/dist/scaffold.d.ts.map +0 -1
- package/dist/scaffold.js.map +0 -7
- package/dist/search.d.ts.map +0 -1
- package/dist/search.js.map +0 -7
- package/dist/session-kanban.d.ts.map +0 -1
- package/dist/session-kanban.js.map +0 -7
- package/dist/set-working-dir.d.ts.map +0 -1
- package/dist/skill.d.ts.map +0 -1
- package/dist/skill.js.map +0 -7
- package/dist/spawn-background.d.ts.map +0 -1
- package/dist/task.d.ts.map +0 -1
- package/dist/task.js.map +0 -7
- package/dist/test.d.ts.map +0 -1
- package/dist/test.js.map +0 -7
- package/dist/todo.d.ts.map +0 -1
- package/dist/todo.js.map +0 -7
- package/dist/tool-diff.d.ts.map +0 -1
- package/dist/tool-diff.js.map +0 -7
- package/dist/tool-help.d.ts.map +0 -1
- package/dist/tool-help.js.map +0 -7
- package/dist/tool-icon-map.d.ts.map +0 -1
- package/dist/tool-icons.d.ts.map +0 -1
- package/dist/tool-icons.js.map +0 -7
- package/dist/tool-search.d.ts.map +0 -1
- package/dist/tool-search.js.map +0 -7
- package/dist/tool-summary.d.ts.map +0 -1
- package/dist/tool-summary.js.map +0 -7
- package/dist/tool-tier.d.ts.map +0 -1
- package/dist/tool-tier.js.map +0 -7
- package/dist/tool-use.d.ts.map +0 -1
- package/dist/tool-use.js.map +0 -7
- package/dist/tree.d.ts.map +0 -1
- package/dist/tree.js.map +0 -7
- package/dist/typecheck.d.ts.map +0 -1
- package/dist/typecheck.js.map +0 -7
- package/dist/win32.d.ts.map +0 -1
- package/dist/win32.js.map +0 -7
- package/dist/write.d.ts.map +0 -1
- package/dist/write.js.map +0 -7
package/dist/install.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/install.ts
|
|
2
|
-
import { join as
|
|
2
|
+
import { join as join8 } from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
detectEcosystem as detectPackageEcosystem,
|
|
5
5
|
recordPackageAction
|
|
@@ -85,11 +85,12 @@ function createOutputSpool(opts) {
|
|
|
85
85
|
return {
|
|
86
86
|
write(text) {
|
|
87
87
|
if (finalized || !text) return;
|
|
88
|
-
|
|
88
|
+
const textBytes = Buffer.byteLength(text, "utf8");
|
|
89
|
+
totalBytes += textBytes;
|
|
89
90
|
if (!stream && !failed) {
|
|
90
|
-
if (headBytes +
|
|
91
|
+
if (headBytes + textBytes <= threshold) {
|
|
91
92
|
head += text;
|
|
92
|
-
headBytes +=
|
|
93
|
+
headBytes += textBytes;
|
|
93
94
|
return;
|
|
94
95
|
}
|
|
95
96
|
head += text;
|
|
@@ -99,7 +100,7 @@ function createOutputSpool(opts) {
|
|
|
99
100
|
}
|
|
100
101
|
if (stream) {
|
|
101
102
|
if (stream.writableLength > SPOOL_WRITE_HWM_BYTES) {
|
|
102
|
-
droppedBytes +=
|
|
103
|
+
droppedBytes += textBytes;
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
105
106
|
stream.write(text);
|
|
@@ -121,6 +122,52 @@ function createOutputSpool(opts) {
|
|
|
121
122
|
};
|
|
122
123
|
}
|
|
123
124
|
|
|
125
|
+
// src/_win32-resolve.ts
|
|
126
|
+
import * as fs from "node:fs";
|
|
127
|
+
import * as path2 from "node:path";
|
|
128
|
+
function resolveWin32Command(cmd) {
|
|
129
|
+
if (process.platform !== "win32") return cmd;
|
|
130
|
+
if (cmd.includes("/") || cmd.includes("\\") || path2.extname(cmd.replace(/\//g, "\\"))) {
|
|
131
|
+
return cmd;
|
|
132
|
+
}
|
|
133
|
+
const pathext = (process.env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC").toLowerCase().split(";");
|
|
134
|
+
const pathDirs = (process.env["PATH"] ?? "").split(path2.delimiter);
|
|
135
|
+
for (const dir of pathDirs) {
|
|
136
|
+
const base = path2.join(dir, cmd);
|
|
137
|
+
for (const ext of pathext) {
|
|
138
|
+
const full = `${base}${ext}`;
|
|
139
|
+
try {
|
|
140
|
+
fs.accessSync(full, fs.constants.X_OK);
|
|
141
|
+
return full;
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return cmd;
|
|
147
|
+
}
|
|
148
|
+
var WIN32_SHELL_META = /[&|<>"\r\n\0]/;
|
|
149
|
+
function assertSafeWin32ShellArgs(args) {
|
|
150
|
+
for (const arg of args) {
|
|
151
|
+
if (typeof arg === "string" && WIN32_SHELL_META.test(arg)) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
'win32 cmd shim spawn: argument contains a shell metacharacter (one of & | < > ", or a newline) that could enable command injection through the .cmd/.bat wrapper - refusing to run. Offending argument: ' + JSON.stringify(arg)
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function buildWin32CmdShimInvocation(command, args = []) {
|
|
159
|
+
assertSafeWin32ShellArgs([command, ...args]);
|
|
160
|
+
const line = ["call", quoteWin32CmdArg(command), ...args.map(quoteWin32CmdArg)].join(" ");
|
|
161
|
+
return {
|
|
162
|
+
command: process.env["COMSPEC"] ?? "cmd.exe",
|
|
163
|
+
args: ["/d", "/c", line],
|
|
164
|
+
windowsVerbatimArguments: true
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function quoteWin32CmdArg(arg) {
|
|
168
|
+
return `"${arg}"`;
|
|
169
|
+
}
|
|
170
|
+
|
|
124
171
|
// src/process-registry.ts
|
|
125
172
|
import { spawn } from "node:child_process";
|
|
126
173
|
import * as os from "node:os";
|
|
@@ -745,60 +792,17 @@ function getProcessRegistry() {
|
|
|
745
792
|
return _registry;
|
|
746
793
|
}
|
|
747
794
|
|
|
748
|
-
// src/_win32-resolve.ts
|
|
749
|
-
import * as fs from "node:fs";
|
|
750
|
-
import * as path2 from "node:path";
|
|
751
|
-
function resolveWin32Command(cmd) {
|
|
752
|
-
if (process.platform !== "win32") return cmd;
|
|
753
|
-
if (cmd.includes("/") || cmd.includes("\\") || path2.extname(cmd.replace(/\//g, "\\"))) {
|
|
754
|
-
return cmd;
|
|
755
|
-
}
|
|
756
|
-
const pathext = (process.env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC").toLowerCase().split(";");
|
|
757
|
-
const pathDirs = (process.env["PATH"] ?? "").split(path2.delimiter);
|
|
758
|
-
for (const dir of pathDirs) {
|
|
759
|
-
const base = path2.join(dir, cmd);
|
|
760
|
-
for (const ext of pathext) {
|
|
761
|
-
const full = `${base}${ext}`;
|
|
762
|
-
try {
|
|
763
|
-
fs.accessSync(full, fs.constants.X_OK);
|
|
764
|
-
return full;
|
|
765
|
-
} catch {
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
return cmd;
|
|
770
|
-
}
|
|
771
|
-
var WIN32_SHELL_META = /[&|<>"\r\n\0]/;
|
|
772
|
-
function assertSafeWin32ShellArgs(args) {
|
|
773
|
-
for (const arg of args) {
|
|
774
|
-
if (typeof arg === "string" && WIN32_SHELL_META.test(arg)) {
|
|
775
|
-
throw new Error(
|
|
776
|
-
'win32 cmd shim spawn: argument contains a shell metacharacter (one of & | < > ", or a newline) that could enable command injection through the .cmd/.bat wrapper - refusing to run. Offending argument: ' + JSON.stringify(arg)
|
|
777
|
-
);
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
function buildWin32CmdShimInvocation(command, args = []) {
|
|
782
|
-
assertSafeWin32ShellArgs([command, ...args]);
|
|
783
|
-
const line = ["call", quoteWin32CmdArg(command), ...args.map(quoteWin32CmdArg)].join(" ");
|
|
784
|
-
return {
|
|
785
|
-
command: process.env["COMSPEC"] ?? "cmd.exe",
|
|
786
|
-
args: ["/d", "/c", line],
|
|
787
|
-
windowsVerbatimArguments: true
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
|
-
function quoteWin32CmdArg(arg) {
|
|
791
|
-
return `"${arg}"`;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
795
|
// src/_spawn-stream.ts
|
|
795
796
|
var isWin = process.platform === "win32";
|
|
796
797
|
async function* spawnStream(opts) {
|
|
797
798
|
const max = opts.maxBytes ?? 2e5;
|
|
798
799
|
const flushAt = opts.flushBytes ?? 4 * 1024;
|
|
799
800
|
const maxQueue = opts.maxQueueSize ?? 500;
|
|
801
|
+
const maxQueueBytes = opts.maxQueueBytes ?? 1024 * 1024;
|
|
800
802
|
let stdout = "";
|
|
801
803
|
let stderr = "";
|
|
804
|
+
let stdoutRetainedBytes = 0;
|
|
805
|
+
let stderrRetainedBytes = 0;
|
|
802
806
|
let pending = "";
|
|
803
807
|
let error;
|
|
804
808
|
const spool = createOutputSpool({ tool: opts.cmd, thresholdBytes: max });
|
|
@@ -840,6 +844,7 @@ async function* spawnStream(opts) {
|
|
|
840
844
|
});
|
|
841
845
|
}
|
|
842
846
|
const queue = [];
|
|
847
|
+
let queuedBytes = 0;
|
|
843
848
|
let waiter;
|
|
844
849
|
let paused = false;
|
|
845
850
|
const wake = () => {
|
|
@@ -850,7 +855,7 @@ async function* spawnStream(opts) {
|
|
|
850
855
|
}
|
|
851
856
|
};
|
|
852
857
|
const resume = () => {
|
|
853
|
-
if (paused && queue.length
|
|
858
|
+
if (paused && queue.length <= Math.floor(maxQueue / 2) && queuedBytes <= Math.floor(maxQueueBytes / 2)) {
|
|
854
859
|
paused = false;
|
|
855
860
|
child.stdout?.resume();
|
|
856
861
|
child.stderr?.resume();
|
|
@@ -860,11 +865,16 @@ async function* spawnStream(opts) {
|
|
|
860
865
|
const s = c.toString();
|
|
861
866
|
stdoutBytes += c.byteLength;
|
|
862
867
|
emitProcessOutput({ pid, stream: "stdout", chunk: c });
|
|
863
|
-
if (
|
|
868
|
+
if (stdoutRetainedBytes < max) {
|
|
869
|
+
const retained = utf8Prefix(s, max - stdoutRetainedBytes);
|
|
870
|
+
stdout += retained;
|
|
871
|
+
stdoutRetainedBytes += Buffer.byteLength(retained, "utf8");
|
|
872
|
+
}
|
|
864
873
|
spool.write(s);
|
|
865
|
-
queue.push({ kind: "out", data: s });
|
|
874
|
+
queue.push({ kind: "out", data: s, bytes: c.byteLength });
|
|
875
|
+
queuedBytes += c.byteLength;
|
|
866
876
|
wake();
|
|
867
|
-
if (!paused && queue.length >= maxQueue) {
|
|
877
|
+
if (!paused && (queue.length >= maxQueue || queuedBytes >= maxQueueBytes)) {
|
|
868
878
|
paused = true;
|
|
869
879
|
child.stdout?.pause();
|
|
870
880
|
child.stderr?.pause();
|
|
@@ -874,11 +884,16 @@ async function* spawnStream(opts) {
|
|
|
874
884
|
const s = c.toString();
|
|
875
885
|
stderrBytes += c.byteLength;
|
|
876
886
|
emitProcessOutput({ pid, stream: "stderr", chunk: c });
|
|
877
|
-
if (
|
|
887
|
+
if (stderrRetainedBytes < max) {
|
|
888
|
+
const retained = utf8Prefix(s, max - stderrRetainedBytes);
|
|
889
|
+
stderr += retained;
|
|
890
|
+
stderrRetainedBytes += Buffer.byteLength(retained, "utf8");
|
|
891
|
+
}
|
|
878
892
|
spool.write(s);
|
|
879
|
-
queue.push({ kind: "err", data: s });
|
|
893
|
+
queue.push({ kind: "err", data: s, bytes: c.byteLength });
|
|
894
|
+
queuedBytes += c.byteLength;
|
|
880
895
|
wake();
|
|
881
|
-
if (!paused && queue.length >= maxQueue) {
|
|
896
|
+
if (!paused && (queue.length >= maxQueue || queuedBytes >= maxQueueBytes)) {
|
|
882
897
|
paused = true;
|
|
883
898
|
child.stdout?.pause();
|
|
884
899
|
child.stderr?.pause();
|
|
@@ -888,7 +903,9 @@ async function* spawnStream(opts) {
|
|
|
888
903
|
child.stderr?.on("data", onErr);
|
|
889
904
|
child.on("error", (e) => {
|
|
890
905
|
error = e.message;
|
|
891
|
-
|
|
906
|
+
const bytes = Buffer.byteLength(e.message, "utf8");
|
|
907
|
+
queue.push({ kind: "error", data: e.message, bytes });
|
|
908
|
+
queuedBytes += bytes;
|
|
892
909
|
wake();
|
|
893
910
|
});
|
|
894
911
|
const completeTelemetry = (code, signal, timedOut = false) => {
|
|
@@ -909,7 +926,13 @@ async function* spawnStream(opts) {
|
|
|
909
926
|
if (typeof pid === "number") registry.unregister(pid);
|
|
910
927
|
const exitCode2 = code ?? (signal ? 1 : 0);
|
|
911
928
|
completeTelemetry(exitCode2, signal ?? void 0);
|
|
912
|
-
queue.push({
|
|
929
|
+
queue.push({
|
|
930
|
+
kind: "close",
|
|
931
|
+
data: "",
|
|
932
|
+
bytes: 0,
|
|
933
|
+
code: exitCode2,
|
|
934
|
+
...signal ? { signal } : {}
|
|
935
|
+
});
|
|
913
936
|
wake();
|
|
914
937
|
});
|
|
915
938
|
const onAbort = () => {
|
|
@@ -921,7 +944,7 @@ async function* spawnStream(opts) {
|
|
|
921
944
|
} catch {
|
|
922
945
|
}
|
|
923
946
|
}
|
|
924
|
-
queue.push({ kind: "close", data: "", code: 124 });
|
|
947
|
+
queue.push({ kind: "close", data: "", bytes: 0, code: 124 });
|
|
925
948
|
completeTelemetry(124, "SIGKILL", true);
|
|
926
949
|
wake();
|
|
927
950
|
};
|
|
@@ -939,6 +962,7 @@ async function* spawnStream(opts) {
|
|
|
939
962
|
});
|
|
940
963
|
}
|
|
941
964
|
const chunk = queue.shift();
|
|
965
|
+
queuedBytes -= chunk.bytes;
|
|
942
966
|
resume();
|
|
943
967
|
if (chunk.kind === "close") {
|
|
944
968
|
if (!spawnFailed) exitCode = chunk.code ?? 0;
|
|
@@ -965,7 +989,7 @@ async function* spawnStream(opts) {
|
|
|
965
989
|
stdout: spooled ? stdout + spoolNote(spooled) : stdout,
|
|
966
990
|
stderr,
|
|
967
991
|
exitCode,
|
|
968
|
-
truncated:
|
|
992
|
+
truncated: stdoutBytes > stdoutRetainedBytes || stderrBytes > stderrRetainedBytes,
|
|
969
993
|
error,
|
|
970
994
|
spoolPath: spooled?.path,
|
|
971
995
|
spoolBytes: spooled?.bytes
|
|
@@ -989,6 +1013,20 @@ async function* spawnStream(opts) {
|
|
|
989
1013
|
}
|
|
990
1014
|
}
|
|
991
1015
|
}
|
|
1016
|
+
function utf8Prefix(text, maxBytes) {
|
|
1017
|
+
if (maxBytes <= 0) return "";
|
|
1018
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
|
|
1019
|
+
let low = 0;
|
|
1020
|
+
let high = text.length;
|
|
1021
|
+
while (low < high) {
|
|
1022
|
+
const mid = Math.ceil((low + high) / 2);
|
|
1023
|
+
if (Buffer.byteLength(text.slice(0, mid), "utf8") <= maxBytes) low = mid;
|
|
1024
|
+
else high = mid - 1;
|
|
1025
|
+
}
|
|
1026
|
+
let end = low;
|
|
1027
|
+
if (end > 0 && /[\uD800-\uDBFF]/.test(text[end - 1])) end--;
|
|
1028
|
+
return text.slice(0, end);
|
|
1029
|
+
}
|
|
992
1030
|
|
|
993
1031
|
// src/_util.ts
|
|
994
1032
|
import * as path3 from "node:path";
|
|
@@ -2570,8 +2608,8 @@ async function scanDirectory(directory, depth, profiles, limits, state, extraIgn
|
|
|
2570
2608
|
collectFileEvidence(directory, fullPath, entry.name, profiles, state);
|
|
2571
2609
|
}
|
|
2572
2610
|
}
|
|
2573
|
-
function collectFileEvidence(directory, fullPath,
|
|
2574
|
-
const lower =
|
|
2611
|
+
function collectFileEvidence(directory, fullPath, basename5, profiles, state) {
|
|
2612
|
+
const lower = basename5.toLowerCase();
|
|
2575
2613
|
const extension = path4.extname(lower);
|
|
2576
2614
|
for (const profile of profiles) {
|
|
2577
2615
|
const detector = profile.detectors.find(
|
|
@@ -2582,7 +2620,7 @@ function collectFileEvidence(directory, fullPath, basename4, profiles, state) {
|
|
|
2582
2620
|
candidate.evidence.push({
|
|
2583
2621
|
kind: detector.kind,
|
|
2584
2622
|
path: fullPath,
|
|
2585
|
-
value:
|
|
2623
|
+
value: basename5,
|
|
2586
2624
|
weight: detector.weight
|
|
2587
2625
|
});
|
|
2588
2626
|
if (detector.kind === "manifest" || detector.kind === "config") {
|
|
@@ -3201,10 +3239,11 @@ var MAX_ARGUMENTS = 128;
|
|
|
3201
3239
|
var MAX_ARGUMENT_LENGTH = 4096;
|
|
3202
3240
|
var PACKAGE_NAME_RE = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+(?:@[a-z0-9*+._~^<>=|-]+)?$/i;
|
|
3203
3241
|
var COMPOSER_PACKAGE_RE = /^[a-z0-9_.-]+\/[a-z0-9_.-]+(?::[a-z0-9*+._~^<>=|-]+)?$/i;
|
|
3204
|
-
var GO_MODULE_RE = /^(?:[a-z0-9
|
|
3242
|
+
var GO_MODULE_RE = /^(?:[a-z0-9-]+\.)+[a-z0-9-]+\/[a-z0-9._~+/@-]+$/i;
|
|
3205
3243
|
var PYTHON_PACKAGE_RE = /^[a-z0-9._-]+(?:\[[a-z0-9._,-]+\])?==[a-z0-9*+._!~-]+$/i;
|
|
3206
3244
|
async function planLanguageOperation(options) {
|
|
3207
3245
|
validateOperationOptions(options.operation, options.operationOptions?.packages);
|
|
3246
|
+
validateFilterOption(options.operationOptions?.filter);
|
|
3208
3247
|
const detection = await detectLanguageWorkspaces(options);
|
|
3209
3248
|
const candidates = detection.workspaces.filter(
|
|
3210
3249
|
(workspace) => workspace.capabilities.includes(options.operation)
|
|
@@ -3377,6 +3416,15 @@ function workspaceDepth(workspaceRoot, projectRoot) {
|
|
|
3377
3416
|
const relative5 = path6.relative(path6.resolve(projectRoot), path6.resolve(workspaceRoot));
|
|
3378
3417
|
return relative5 === "" ? 0 : relative5.split(path6.sep).length;
|
|
3379
3418
|
}
|
|
3419
|
+
function validateFilterOption(filter) {
|
|
3420
|
+
if (filter === void 0) return;
|
|
3421
|
+
if (filter.startsWith("-") || filter.includes(" --")) {
|
|
3422
|
+
throw new Error(`Invalid test filter (parsed as a runner option): "${filter}"`);
|
|
3423
|
+
}
|
|
3424
|
+
if (filter.length > MAX_ARGUMENT_LENGTH || /[\r\n\0]/.test(filter)) {
|
|
3425
|
+
throw new Error("Invalid test filter (oversized or contains a control character)");
|
|
3426
|
+
}
|
|
3427
|
+
}
|
|
3380
3428
|
function validateOperationOptions(operation, packages) {
|
|
3381
3429
|
if (!operation.startsWith("package-") || !packages) return;
|
|
3382
3430
|
for (const value of packages) {
|
|
@@ -3759,6 +3807,10 @@ var installTool = {
|
|
|
3759
3807
|
description: "Install, update or manage packages using the detected package manager (pnpm/npm/yarn). Strongly preferred over raw shell commands for dependency management because it is structured and safer.",
|
|
3760
3808
|
usageHint: "ALWAYS USE THIS INSTEAD OF BASH FOR PACKAGE WORK:\n\n- Empty `packages` \u2192 normal `install` (respects lockfile).\n- Provide names \u2192 adds/updates specific packages.\n- `dry_run: true` for safe preview.\n- Set `save` appropriately.\nThis tool has proper capability declaration and is heavily recommended in the security posture of the project.",
|
|
3761
3809
|
permission: "confirm",
|
|
3810
|
+
// WS-046: gives permission decisions something to key on.
|
|
3811
|
+
// What gets installed is the subject — installing a package runs its
|
|
3812
|
+
// lifecycle scripts, so `express` and `evil-pkg` must not be interchangeable.
|
|
3813
|
+
subjectKey: "packages",
|
|
3762
3814
|
mutating: true,
|
|
3763
3815
|
riskTier: "standard",
|
|
3764
3816
|
icon: "package",
|
|
@@ -3928,10 +3980,10 @@ function resolveManifestPath(cwd, pkgManager) {
|
|
|
3928
3980
|
case "pnpm":
|
|
3929
3981
|
case "yarn":
|
|
3930
3982
|
case "npm":
|
|
3931
|
-
return
|
|
3983
|
+
return join8(cwd, "package.json");
|
|
3932
3984
|
/* v8 ignore next 2 -- pkgManager is always pnpm/yarn/npm; the default is defensive. */
|
|
3933
3985
|
default:
|
|
3934
|
-
return
|
|
3986
|
+
return join8(cwd, "package.json");
|
|
3935
3987
|
}
|
|
3936
3988
|
}
|
|
3937
3989
|
export {
|
package/dist/json.js
CHANGED
|
@@ -27,12 +27,13 @@ function ensureInsideRoot(absPath, ctx) {
|
|
|
27
27
|
function safeResolve(input, ctx) {
|
|
28
28
|
return ensureInsideRoot(resolvePath(input, ctx), ctx);
|
|
29
29
|
}
|
|
30
|
-
async function
|
|
31
|
-
if (ctx.allowOutsideProjectRoot) return;
|
|
30
|
+
async function resolveRealInsideRoot(absPath, ctx) {
|
|
31
|
+
if (ctx.allowOutsideProjectRoot) return absPath;
|
|
32
32
|
const realRoots = await Promise.all(
|
|
33
33
|
allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path.resolve(r)))
|
|
34
34
|
);
|
|
35
35
|
let probe = absPath;
|
|
36
|
+
const pendingTail = [];
|
|
36
37
|
for (; ; ) {
|
|
37
38
|
let real;
|
|
38
39
|
try {
|
|
@@ -40,13 +41,16 @@ async function assertRealInsideRoot(absPath, ctx) {
|
|
|
40
41
|
} catch (err) {
|
|
41
42
|
if (err.code === "ENOENT") {
|
|
42
43
|
const parent = path.dirname(probe);
|
|
43
|
-
if (parent === probe) return;
|
|
44
|
+
if (parent === probe) return absPath;
|
|
45
|
+
pendingTail.unshift(path.basename(probe));
|
|
44
46
|
probe = parent;
|
|
45
47
|
continue;
|
|
46
48
|
}
|
|
47
49
|
throw err;
|
|
48
50
|
}
|
|
49
|
-
if (isInsideAny(real, realRoots))
|
|
51
|
+
if (isInsideAny(real, realRoots)) {
|
|
52
|
+
return pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
|
|
53
|
+
}
|
|
50
54
|
throw new Error(
|
|
51
55
|
`Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
|
|
52
56
|
);
|
|
@@ -54,11 +58,28 @@ async function assertRealInsideRoot(absPath, ctx) {
|
|
|
54
58
|
}
|
|
55
59
|
async function safeResolveReal(input, ctx) {
|
|
56
60
|
const abs = safeResolve(input, ctx);
|
|
57
|
-
await
|
|
58
|
-
return abs;
|
|
61
|
+
return await resolveRealInsideRoot(abs, ctx);
|
|
59
62
|
}
|
|
60
63
|
|
|
61
64
|
// src/json.ts
|
|
65
|
+
var MAX_JSON_FILE_BYTES = 16 * 1024 * 1024;
|
|
66
|
+
var MAX_JSON_FILE_BYTES_HUMAN = "16 MiB";
|
|
67
|
+
var JsonFileTooLargeError = class extends Error {
|
|
68
|
+
constructor(filePath, size) {
|
|
69
|
+
super(
|
|
70
|
+
`json: "${filePath}" is ${size} bytes \u2014 exceeds the ${MAX_JSON_FILE_BYTES_HUMAN} file-size limit. Extract the relevant portion into a smaller file first, or use a shell tool to query it directly.`
|
|
71
|
+
);
|
|
72
|
+
this.name = "JsonFileTooLargeError";
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
async function readJsonFileBounded(filePath, ctx) {
|
|
76
|
+
const resolved = await safeResolveReal(filePath, ctx);
|
|
77
|
+
const stat2 = await fs.stat(resolved);
|
|
78
|
+
if (stat2.size > MAX_JSON_FILE_BYTES) {
|
|
79
|
+
throw new JsonFileTooLargeError(filePath, stat2.size);
|
|
80
|
+
}
|
|
81
|
+
return fs.readFile(resolved, "utf8");
|
|
82
|
+
}
|
|
62
83
|
var jsonTool = {
|
|
63
84
|
name: "json",
|
|
64
85
|
category: "Data",
|
|
@@ -66,6 +87,7 @@ var jsonTool = {
|
|
|
66
87
|
usageHint: 'VERY USEFUL FOR DATA INSPECTION:\n\n- `action: "parse"` (default): read/pretty-print/convert JSON, JSON5, or YAML from `file` or `data`.\n- `action: "query"`: JMESPath-like query (`a.b[0].c`, `items[*].name`, filters, functions).\n- `action: "validate"`: validate data against a JSON Schema (`schema` param).\n- `action: "transform"`: chain multiple JMESPath transforms (`transforms` param).\n- `action: "merge"`: deep merge `base` and `patch` objects (`conflictResolution` param).\nPrefer this over raw `read` + manual parsing when dealing with configuration or data files.',
|
|
67
88
|
permission: "auto",
|
|
68
89
|
mutating: false,
|
|
90
|
+
maxOutputBytes: 262144,
|
|
69
91
|
timeoutMs: 5e3,
|
|
70
92
|
capabilities: ["fs.read"],
|
|
71
93
|
icon: "json",
|
|
@@ -132,9 +154,15 @@ async function executeParse(input, ctx) {
|
|
|
132
154
|
let raw;
|
|
133
155
|
if (input.file) {
|
|
134
156
|
try {
|
|
135
|
-
raw = await
|
|
136
|
-
} catch {
|
|
137
|
-
return {
|
|
157
|
+
raw = await readJsonFileBounded(input.file, ctx);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
return {
|
|
160
|
+
data: null,
|
|
161
|
+
formatted: "",
|
|
162
|
+
type: "unknown",
|
|
163
|
+
action: "parse",
|
|
164
|
+
error: error instanceof JsonFileTooLargeError ? error.message : "Could not read file"
|
|
165
|
+
};
|
|
138
166
|
}
|
|
139
167
|
} else if (input.data) {
|
|
140
168
|
raw = input.data;
|
|
@@ -190,10 +218,16 @@ async function executeQuery(input, ctx) {
|
|
|
190
218
|
let parsed;
|
|
191
219
|
if (input.file) {
|
|
192
220
|
try {
|
|
193
|
-
const raw = await
|
|
221
|
+
const raw = await readJsonFileBounded(input.file, ctx);
|
|
194
222
|
parsed = JSON.parse(raw);
|
|
195
|
-
} catch {
|
|
196
|
-
return {
|
|
223
|
+
} catch (error) {
|
|
224
|
+
return {
|
|
225
|
+
data: null,
|
|
226
|
+
formatted: "",
|
|
227
|
+
type: "unknown",
|
|
228
|
+
action: "query",
|
|
229
|
+
error: error instanceof JsonFileTooLargeError ? error.message : "Could not read/parse file"
|
|
230
|
+
};
|
|
197
231
|
}
|
|
198
232
|
} else if (input.data) {
|
|
199
233
|
try {
|
|
@@ -232,10 +266,16 @@ async function executeValidate(input, ctx) {
|
|
|
232
266
|
let parsed;
|
|
233
267
|
if (input.file) {
|
|
234
268
|
try {
|
|
235
|
-
const raw = await
|
|
269
|
+
const raw = await readJsonFileBounded(input.file, ctx);
|
|
236
270
|
parsed = JSON.parse(raw);
|
|
237
|
-
} catch {
|
|
238
|
-
return {
|
|
271
|
+
} catch (error) {
|
|
272
|
+
return {
|
|
273
|
+
data: null,
|
|
274
|
+
formatted: "",
|
|
275
|
+
type: "unknown",
|
|
276
|
+
action: "validate",
|
|
277
|
+
error: error instanceof JsonFileTooLargeError ? error.message : "Could not read/parse file"
|
|
278
|
+
};
|
|
239
279
|
}
|
|
240
280
|
} else if (input.data) {
|
|
241
281
|
try {
|
|
@@ -274,10 +314,16 @@ async function executeTransform(input, ctx) {
|
|
|
274
314
|
let parsed;
|
|
275
315
|
if (input.file) {
|
|
276
316
|
try {
|
|
277
|
-
const raw = await
|
|
317
|
+
const raw = await readJsonFileBounded(input.file, ctx);
|
|
278
318
|
parsed = JSON.parse(raw);
|
|
279
|
-
} catch {
|
|
280
|
-
return {
|
|
319
|
+
} catch (error) {
|
|
320
|
+
return {
|
|
321
|
+
data: null,
|
|
322
|
+
formatted: "",
|
|
323
|
+
type: "unknown",
|
|
324
|
+
action: "transform",
|
|
325
|
+
error: error instanceof JsonFileTooLargeError ? error.message : "Could not read/parse file"
|
|
326
|
+
};
|
|
281
327
|
}
|
|
282
328
|
} else if (input.data) {
|
|
283
329
|
try {
|
|
@@ -8,8 +8,17 @@ export declare function boardCreateInput(input: KanbanToolInput, title: string):
|
|
|
8
8
|
mode: "assess" | "enforce" | "off";
|
|
9
9
|
decomposition: "auto" | "propose";
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
} | {
|
|
12
|
+
completionGate: {
|
|
13
|
+
enforcement: 'strict' | 'soft';
|
|
14
|
+
};
|
|
15
|
+
title: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
tags?: string[];
|
|
18
|
+
generatedBy?: string;
|
|
19
|
+
atomicity?: {
|
|
20
|
+
mode: "assess" | "enforce" | "off";
|
|
21
|
+
decomposition: "auto" | "propose";
|
|
13
22
|
};
|
|
14
23
|
};
|
|
15
24
|
export declare function boardUpdatePatch(input: KanbanToolInput): {
|
|
@@ -20,8 +29,16 @@ export declare function boardUpdatePatch(input: KanbanToolInput): {
|
|
|
20
29
|
mode: "assess" | "enforce" | "off";
|
|
21
30
|
decomposition: "auto" | "propose";
|
|
22
31
|
};
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
} | {
|
|
33
|
+
completionGate: {
|
|
34
|
+
enforcement: 'strict' | 'soft';
|
|
35
|
+
};
|
|
36
|
+
title?: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
tags?: string[];
|
|
39
|
+
atomicity?: {
|
|
40
|
+
mode: "assess" | "enforce" | "off";
|
|
41
|
+
decomposition: "auto" | "propose";
|
|
25
42
|
};
|
|
26
43
|
};
|
|
27
44
|
export declare function duplicateBoardOptions(input: KanbanToolInput): {
|
package/dist/kanban.js
CHANGED
|
@@ -345,6 +345,10 @@ async function handleKanbanDetailAction(projectRoot, input) {
|
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
// src/kanban-board-inputs.ts
|
|
348
|
+
function agentSettableGate(enforcement) {
|
|
349
|
+
if (enforcement === void 0 || enforcement === "off") return {};
|
|
350
|
+
return { completionGate: { enforcement } };
|
|
351
|
+
}
|
|
348
352
|
function boardCreateInput(input, title) {
|
|
349
353
|
return {
|
|
350
354
|
title,
|
|
@@ -357,7 +361,7 @@ function boardCreateInput(input, title) {
|
|
|
357
361
|
decomposition: input.atomicityDecomposition ?? "propose"
|
|
358
362
|
}
|
|
359
363
|
} : {},
|
|
360
|
-
...input.gateEnforcement
|
|
364
|
+
...agentSettableGate(input.gateEnforcement)
|
|
361
365
|
};
|
|
362
366
|
}
|
|
363
367
|
function boardUpdatePatch(input) {
|
|
@@ -371,7 +375,7 @@ function boardUpdatePatch(input) {
|
|
|
371
375
|
decomposition: input.atomicityDecomposition ?? "propose"
|
|
372
376
|
}
|
|
373
377
|
} : {},
|
|
374
|
-
...input.gateEnforcement
|
|
378
|
+
...agentSettableGate(input.gateEnforcement)
|
|
375
379
|
};
|
|
376
380
|
}
|
|
377
381
|
function duplicateBoardOptions(input) {
|
|
@@ -386,6 +390,7 @@ function duplicateBoardOptions(input) {
|
|
|
386
390
|
|
|
387
391
|
// src/kanban-task-inputs.ts
|
|
388
392
|
import { randomUUID } from "node:crypto";
|
|
393
|
+
import { clampSubagentCapabilities } from "@wrongstack/core/security";
|
|
389
394
|
function taskInput(input) {
|
|
390
395
|
const assignment = hasAssignmentInput(input) ? assignmentForTaskCreate(input) : void 0;
|
|
391
396
|
return {
|
|
@@ -483,6 +488,10 @@ function taskPatch(input) {
|
|
|
483
488
|
...input.actualHours !== void 0 ? { actualHours: input.actualHours } : {}
|
|
484
489
|
};
|
|
485
490
|
}
|
|
491
|
+
function clampRequestedCapabilities(requested) {
|
|
492
|
+
if (requested === void 0) return void 0;
|
|
493
|
+
return clampSubagentCapabilities(requested).granted;
|
|
494
|
+
}
|
|
486
495
|
function assignmentInput(input) {
|
|
487
496
|
return {
|
|
488
497
|
agentId: input.agentId,
|
|
@@ -493,7 +502,7 @@ function assignmentInput(input) {
|
|
|
493
502
|
fallbackProfile: input.fallbackProfile,
|
|
494
503
|
fallbackModels: input.fallbackModels,
|
|
495
504
|
tools: input.tools,
|
|
496
|
-
allowedCapabilities: input.allowedCapabilities,
|
|
505
|
+
allowedCapabilities: clampRequestedCapabilities(input.allowedCapabilities),
|
|
497
506
|
assignee: input.assignee,
|
|
498
507
|
leaseId: input.leaseId,
|
|
499
508
|
claimedAt: input.claimedAt,
|
|
@@ -520,7 +529,7 @@ function assignmentForTaskCreate(input) {
|
|
|
520
529
|
...input.fallbackProfile !== void 0 ? { fallbackProfile: input.fallbackProfile } : {},
|
|
521
530
|
...input.fallbackModels !== void 0 ? { fallbackModels: input.fallbackModels } : {},
|
|
522
531
|
...input.tools !== void 0 ? { tools: input.tools } : {},
|
|
523
|
-
...input.allowedCapabilities !== void 0 ? { allowedCapabilities: input.allowedCapabilities } : {},
|
|
532
|
+
...input.allowedCapabilities !== void 0 ? { allowedCapabilities: clampRequestedCapabilities(input.allowedCapabilities) } : {},
|
|
524
533
|
...input.leaseId !== void 0 ? { leaseId: input.leaseId } : {},
|
|
525
534
|
...input.claimedAt !== void 0 ? { claimedAt: input.claimedAt } : {},
|
|
526
535
|
...input.heartbeatAt !== void 0 ? { heartbeatAt: input.heartbeatAt } : {},
|
|
@@ -731,7 +740,13 @@ var KANBAN_INPUT_SCHEMA = {
|
|
|
731
740
|
moveTasksToColumnId: { type: "string" },
|
|
732
741
|
atomicityMode: { type: "string", enum: ["off", "assess", "enforce"] },
|
|
733
742
|
atomicityDecomposition: { type: "string", enum: ["auto", "propose"] },
|
|
734
|
-
gateEnforcement: {
|
|
743
|
+
gateEnforcement: {
|
|
744
|
+
type: "string",
|
|
745
|
+
// WS-023: `'off'` is deliberately absent. The agent whose work this gate
|
|
746
|
+
// checks must not be able to switch it off; it may only tighten. Turning
|
|
747
|
+
// a gate off stays a human decision, made through board config.
|
|
748
|
+
enum: ["strict", "soft"]
|
|
749
|
+
},
|
|
735
750
|
subtasks: {
|
|
736
751
|
type: "array",
|
|
737
752
|
minItems: 2,
|