@wrongstack/tools 0.295.0 → 0.295.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/auto-proceed-loop-guard.d.ts +31 -0
- package/dist/auto-proceed-loop-guard.d.ts.map +1 -1
- package/dist/auto-proceed-loop-guard.js +24 -1
- package/dist/auto-proceed-loop-guard.js.map +2 -2
- package/dist/bash.js +39 -23
- package/dist/bash.js.map +2 -2
- package/dist/builtin.js +278 -109
- package/dist/builtin.js.map +4 -4
- package/dist/codebase-index/generic-parser.d.ts.map +1 -1
- package/dist/codebase-index/index.js +48 -47
- package/dist/codebase-index/index.js.map +2 -2
- package/dist/codebase-index/indexer.d.ts.map +1 -1
- package/dist/codebase-index/worker.js +48 -47
- package/dist/codebase-index/worker.js.map +2 -2
- package/dist/codebase-index/writer.d.ts.map +1 -1
- package/dist/exec.js +39 -23
- package/dist/exec.js.map +2 -2
- package/dist/glob.d.ts.map +1 -1
- package/dist/glob.js +80 -30
- package/dist/glob.js.map +4 -4
- package/dist/grep.d.ts.map +1 -1
- package/dist/grep.js +87 -20
- package/dist/grep.js.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +281 -109
- package/dist/index.js.map +4 -4
- package/dist/kanban-evidence-bridge.d.ts +21 -0
- package/dist/kanban-evidence-bridge.d.ts.map +1 -0
- package/dist/kanban.d.ts +17 -1
- package/dist/kanban.d.ts.map +1 -1
- package/dist/kanban.js +164 -7
- package/dist/kanban.js.map +3 -3
- package/dist/pack.js +278 -109
- package/dist/pack.js.map +4 -4
- package/dist/process-registry-persistent.d.ts.map +1 -1
- package/dist/ps-slash.js +39 -23
- package/dist/ps-slash.js.map +2 -2
- package/dist/tool-tier.js +278 -109
- package/dist/tool-tier.js.map +4 -4
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +2 -14
- package/dist/tree.js.map +2 -2
- package/dist/win32.d.ts +10 -0
- package/dist/win32.d.ts.map +1 -0
- package/dist/win32.js +67 -0
- package/dist/win32.js.map +7 -0
- package/package.json +7 -3
package/dist/tool-tier.js
CHANGED
|
@@ -5067,6 +5067,7 @@ function emitStructuredLog(level, event, message, error) {
|
|
|
5067
5067
|
}
|
|
5068
5068
|
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
5069
5069
|
var STALE_THRESHOLD_MS = 3e4;
|
|
5070
|
+
var LOCK_STALE_MS = 3e4;
|
|
5070
5071
|
var LOCKFILE = ".process-registry.lock";
|
|
5071
5072
|
function generateInstanceId() {
|
|
5072
5073
|
const hostname2 = os2.hostname();
|
|
@@ -5095,21 +5096,26 @@ async function acquireLock(lockfilePath, timeoutMs = 5e3) {
|
|
|
5095
5096
|
try {
|
|
5096
5097
|
const content = await fs6.readFile(lockfilePath, "utf-8");
|
|
5097
5098
|
const parts = content.split(":");
|
|
5098
|
-
const
|
|
5099
|
-
const
|
|
5100
|
-
|
|
5099
|
+
const lockPid = parseInt(parts[0] ?? "0", 10);
|
|
5100
|
+
const lockTs = Number(parts[parts.length - 1]);
|
|
5101
|
+
const staleByAge = Number.isFinite(lockTs) && Date.now() - lockTs > LOCK_STALE_MS;
|
|
5102
|
+
let holderDead = false;
|
|
5103
|
+
if (process.platform !== "win32" && Number.isFinite(lockPid) && lockPid > 0) {
|
|
5101
5104
|
try {
|
|
5102
5105
|
process.kill(lockPid, 0);
|
|
5103
5106
|
} catch {
|
|
5104
|
-
|
|
5105
|
-
continue;
|
|
5107
|
+
holderDead = true;
|
|
5106
5108
|
}
|
|
5107
5109
|
}
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5110
|
+
if (holderDead || staleByAge) {
|
|
5111
|
+
await fs6.unlink(lockfilePath).catch(() => {
|
|
5112
|
+
});
|
|
5113
|
+
continue;
|
|
5112
5114
|
}
|
|
5115
|
+
} catch {
|
|
5116
|
+
await fs6.unlink(lockfilePath).catch(() => {
|
|
5117
|
+
});
|
|
5118
|
+
continue;
|
|
5113
5119
|
}
|
|
5114
5120
|
await new Promise((r) => setTimeout(r, 100));
|
|
5115
5121
|
continue;
|
|
@@ -5119,25 +5125,35 @@ async function acquireLock(lockfilePath, timeoutMs = 5e3) {
|
|
|
5119
5125
|
}
|
|
5120
5126
|
throw new Error(`Failed to acquire lock after ${timeoutMs}ms`);
|
|
5121
5127
|
}
|
|
5128
|
+
function freshRegistryData() {
|
|
5129
|
+
return {
|
|
5130
|
+
version: 1,
|
|
5131
|
+
instances: /* @__PURE__ */ new Map(),
|
|
5132
|
+
protectedPatterns: ["wrongstack", "node"],
|
|
5133
|
+
lastCleanup: Date.now()
|
|
5134
|
+
};
|
|
5135
|
+
}
|
|
5122
5136
|
async function readRegistryFile(filePath) {
|
|
5137
|
+
let content;
|
|
5123
5138
|
try {
|
|
5124
|
-
|
|
5125
|
-
const parsed = JSON.parse(content);
|
|
5126
|
-
if (parsed.instances && Array.isArray(parsed.instances)) {
|
|
5127
|
-
parsed.instances = new Map(parsed.instances);
|
|
5128
|
-
}
|
|
5129
|
-
return parsed;
|
|
5139
|
+
content = await fs6.readFile(filePath, "utf-8");
|
|
5130
5140
|
} catch (err) {
|
|
5131
|
-
if (isNodeError(err) && err.code === "ENOENT")
|
|
5132
|
-
return {
|
|
5133
|
-
version: 1,
|
|
5134
|
-
instances: /* @__PURE__ */ new Map(),
|
|
5135
|
-
protectedPatterns: ["wrongstack", "node"],
|
|
5136
|
-
lastCleanup: Date.now()
|
|
5137
|
-
};
|
|
5138
|
-
}
|
|
5141
|
+
if (isNodeError(err) && err.code === "ENOENT") return freshRegistryData();
|
|
5139
5142
|
throw err;
|
|
5140
5143
|
}
|
|
5144
|
+
try {
|
|
5145
|
+
const parsed = JSON.parse(content);
|
|
5146
|
+
if (!parsed || typeof parsed !== "object") return freshRegistryData();
|
|
5147
|
+
const base = freshRegistryData();
|
|
5148
|
+
return {
|
|
5149
|
+
version: 1,
|
|
5150
|
+
instances: Array.isArray(parsed.instances) ? new Map(parsed.instances) : base.instances,
|
|
5151
|
+
protectedPatterns: Array.isArray(parsed.protectedPatterns) ? parsed.protectedPatterns : base.protectedPatterns,
|
|
5152
|
+
lastCleanup: typeof parsed.lastCleanup === "number" ? parsed.lastCleanup : base.lastCleanup
|
|
5153
|
+
};
|
|
5154
|
+
} catch {
|
|
5155
|
+
return freshRegistryData();
|
|
5156
|
+
}
|
|
5141
5157
|
}
|
|
5142
5158
|
async function writeRegistryFile(filePath, data) {
|
|
5143
5159
|
const tmpPath = `${filePath}.tmp.${process.pid}`;
|
|
@@ -9130,11 +9146,12 @@ var IndexStore = class _IndexStore {
|
|
|
9130
9146
|
}
|
|
9131
9147
|
}
|
|
9132
9148
|
const refRows = this.stmt(
|
|
9133
|
-
`SELECT r.call_type, sf.file AS from_file, st.file AS to_file
|
|
9149
|
+
`SELECT r.call_type, sf.file AS from_file, st.file AS to_file, COUNT(*) AS n
|
|
9134
9150
|
FROM refs r
|
|
9135
9151
|
JOIN symbols sf ON sf.id = r.from_id
|
|
9136
9152
|
JOIN symbols st ON st.id = r.to_id
|
|
9137
|
-
WHERE r.to_id IS NOT NULL AND r.call_type != 'import'
|
|
9153
|
+
WHERE r.to_id IS NOT NULL AND r.call_type != 'import'
|
|
9154
|
+
GROUP BY r.call_type, sf.file, st.file`
|
|
9138
9155
|
).all();
|
|
9139
9156
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
9140
9157
|
for (const r of refRows) {
|
|
@@ -9147,14 +9164,16 @@ var IndexStore = class _IndexStore {
|
|
|
9147
9164
|
e = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9148
9165
|
edgeMap.set(key, e);
|
|
9149
9166
|
}
|
|
9150
|
-
|
|
9151
|
-
e.
|
|
9167
|
+
const n = Number(r.n) || 0;
|
|
9168
|
+
e.weight += n;
|
|
9169
|
+
e.types.set(r.call_type, (e.types.get(r.call_type) ?? 0) + n);
|
|
9152
9170
|
}
|
|
9153
9171
|
const importRows = this.stmt(
|
|
9154
|
-
`SELECT r.to_name, s.file AS from_file
|
|
9172
|
+
`SELECT r.to_name, s.file AS from_file, COUNT(*) AS n
|
|
9155
9173
|
FROM refs r
|
|
9156
9174
|
JOIN symbols s ON s.id = r.from_id
|
|
9157
|
-
WHERE r.call_type = 'import'
|
|
9175
|
+
WHERE r.call_type = 'import'
|
|
9176
|
+
GROUP BY r.to_name, s.file`
|
|
9158
9177
|
).all();
|
|
9159
9178
|
for (const r of importRows) {
|
|
9160
9179
|
const fromPkg = fileToPkg.get(r.from_file) ?? _IndexStore.derivePackage(r.from_file) ?? "(root)";
|
|
@@ -9166,8 +9185,9 @@ var IndexStore = class _IndexStore {
|
|
|
9166
9185
|
edge = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9167
9186
|
edgeMap.set(key, edge);
|
|
9168
9187
|
}
|
|
9169
|
-
|
|
9170
|
-
edge.
|
|
9188
|
+
const n = Number(r.n) || 0;
|
|
9189
|
+
edge.weight += n;
|
|
9190
|
+
edge.types.set("import", (edge.types.get("import") ?? 0) + n);
|
|
9171
9191
|
}
|
|
9172
9192
|
const edges = [];
|
|
9173
9193
|
for (const [key, e] of edgeMap) {
|
|
@@ -9232,11 +9252,12 @@ var IndexStore = class _IndexStore {
|
|
|
9232
9252
|
}
|
|
9233
9253
|
const indexedFiles = new Set(allFiles.map((f) => f.file));
|
|
9234
9254
|
const refRows = this.stmt(
|
|
9235
|
-
`SELECT r.from_id, r.to_id, r.call_type
|
|
9255
|
+
`SELECT r.from_id, r.to_id, r.call_type, COUNT(*) AS n
|
|
9236
9256
|
FROM refs r
|
|
9237
9257
|
WHERE (r.from_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders}))
|
|
9238
9258
|
OR r.to_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders})))
|
|
9239
|
-
AND r.to_id IS NOT NULL
|
|
9259
|
+
AND r.to_id IS NOT NULL
|
|
9260
|
+
GROUP BY r.from_id, r.to_id, r.call_type`
|
|
9240
9261
|
).all(...pkgFilePaths, ...pkgFilePaths);
|
|
9241
9262
|
const knownSymIds = new Set(pkgSyms.map((s) => s.id));
|
|
9242
9263
|
const crossRefIds = /* @__PURE__ */ new Set();
|
|
@@ -9271,14 +9292,16 @@ var IndexStore = class _IndexStore {
|
|
|
9271
9292
|
e = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9272
9293
|
edgeMap.set(key, e);
|
|
9273
9294
|
}
|
|
9274
|
-
|
|
9275
|
-
e.
|
|
9295
|
+
const n = Number(r.n) || 0;
|
|
9296
|
+
e.weight += n;
|
|
9297
|
+
e.types.set(r.call_type, (e.types.get(r.call_type) ?? 0) + n);
|
|
9276
9298
|
}
|
|
9277
9299
|
const importRows = this.stmt(
|
|
9278
|
-
`SELECT r.from_id, r.to_name
|
|
9300
|
+
`SELECT r.from_id, r.to_name, COUNT(*) AS n
|
|
9279
9301
|
FROM refs r
|
|
9280
9302
|
WHERE r.call_type = 'import'
|
|
9281
|
-
AND r.from_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders}))
|
|
9303
|
+
AND r.from_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders}))
|
|
9304
|
+
GROUP BY r.from_id, r.to_name`
|
|
9282
9305
|
).all(...pkgFilePaths);
|
|
9283
9306
|
for (const r of importRows) {
|
|
9284
9307
|
const fromFile = symToFile.get(r.from_id);
|
|
@@ -9293,8 +9316,9 @@ var IndexStore = class _IndexStore {
|
|
|
9293
9316
|
edge = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9294
9317
|
edgeMap.set(key, edge);
|
|
9295
9318
|
}
|
|
9296
|
-
|
|
9297
|
-
edge.
|
|
9319
|
+
const n = Number(r.n) || 0;
|
|
9320
|
+
edge.weight += n;
|
|
9321
|
+
edge.types.set("import", (edge.types.get("import") ?? 0) + n);
|
|
9298
9322
|
}
|
|
9299
9323
|
const edges = [];
|
|
9300
9324
|
for (const [key, e] of edgeMap) {
|
|
@@ -9341,22 +9365,25 @@ var IndexStore = class _IndexStore {
|
|
|
9341
9365
|
scope: s.scope,
|
|
9342
9366
|
external: s.file !== fileFilter
|
|
9343
9367
|
});
|
|
9344
|
-
const symIds = new Set(syms.map((s) => s.id));
|
|
9345
9368
|
const refRows = this.stmt(
|
|
9346
|
-
`SELECT
|
|
9347
|
-
FROM
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9369
|
+
`SELECT from_id, to_id, call_type, COUNT(*) AS n
|
|
9370
|
+
FROM (
|
|
9371
|
+
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
9372
|
+
FROM refs r
|
|
9373
|
+
JOIN symbols s ON s.id = r.from_id
|
|
9374
|
+
WHERE s.file = ?
|
|
9375
|
+
UNION
|
|
9376
|
+
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
9377
|
+
FROM refs r
|
|
9378
|
+
JOIN symbols s ON s.id = r.to_id
|
|
9379
|
+
WHERE s.file = ?
|
|
9380
|
+
)
|
|
9381
|
+
WHERE to_id IS NOT NULL
|
|
9382
|
+
GROUP BY from_id, to_id, call_type`
|
|
9355
9383
|
).all(fileFilter, fileFilter);
|
|
9356
9384
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
9357
9385
|
for (const r of refRows) {
|
|
9358
|
-
if (r.to_id
|
|
9359
|
-
if (!symIds.has(r.from_id) && !symIds.has(r.to_id)) continue;
|
|
9386
|
+
if (r.to_id == null) continue;
|
|
9360
9387
|
relatedIds.add(r.from_id);
|
|
9361
9388
|
relatedIds.add(r.to_id);
|
|
9362
9389
|
const key = `${r.from_id}\0${r.to_id}`;
|
|
@@ -9365,8 +9392,9 @@ var IndexStore = class _IndexStore {
|
|
|
9365
9392
|
e = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9366
9393
|
edgeMap.set(key, e);
|
|
9367
9394
|
}
|
|
9368
|
-
|
|
9369
|
-
e.
|
|
9395
|
+
const n = Number(r.n) || 0;
|
|
9396
|
+
e.weight += n;
|
|
9397
|
+
e.types.set(r.call_type, (e.types.get(r.call_type) ?? 0) + n);
|
|
9370
9398
|
}
|
|
9371
9399
|
const edges = [];
|
|
9372
9400
|
for (const [key, e] of edgeMap) {
|
|
@@ -9423,7 +9451,7 @@ import { expectDefined as expectDefined6 } from "@wrongstack/core/utils";
|
|
|
9423
9451
|
import * as fs14 from "node:fs/promises";
|
|
9424
9452
|
import * as path20 from "node:path";
|
|
9425
9453
|
import { availableParallelism } from "node:os";
|
|
9426
|
-
import { indexParallelBatchSize, isFrugalPerf } from "@wrongstack/core/utils";
|
|
9454
|
+
import { DEFAULT_WALK_IGNORE_DIRS, indexParallelBatchSize, isFrugalPerf } from "@wrongstack/core/utils";
|
|
9427
9455
|
|
|
9428
9456
|
// src/codebase-index/ts-parser.ts
|
|
9429
9457
|
import * as ts from "@typescript/typescript6";
|
|
@@ -10078,7 +10106,7 @@ import * as path16 from "node:path";
|
|
|
10078
10106
|
var C_LIKE = [
|
|
10079
10107
|
{ re: /\b(?:class|struct|enum|interface|union)\s+([A-Za-z_]\w*)/g, kind: "class" },
|
|
10080
10108
|
{
|
|
10081
|
-
re: /\b(?:public|private|protected|static|final|async|override|virtual|inline|export)?\s*(?:[\w
|
|
10109
|
+
re: /\b(?:public|private|protected|static|final|async|override|virtual|inline|export)?\s*(?:[\w:<>[\]\s*&]+)\s+([A-Za-z_]\w*)\s*\([^;{]*\)\s*(?:const)?\s*[{;]/g,
|
|
10082
10110
|
kind: "function"
|
|
10083
10111
|
},
|
|
10084
10112
|
{ re: /\b(?:namespace)\s+([A-Za-z_]\w*)/g, kind: "namespace" }
|
|
@@ -10109,7 +10137,7 @@ var LANG_PATTERNS = {
|
|
|
10109
10137
|
java: [
|
|
10110
10138
|
{ re: /\b(?:class|interface|enum|record)\s+([A-Za-z_]\w*)/g, kind: "class" },
|
|
10111
10139
|
{
|
|
10112
|
-
re: /\b(?:public|private|protected|static|final|abstract|synchronized|native|default|\s)+\s*[\w
|
|
10140
|
+
re: /\b(?:public|private|protected|static|final|abstract|synchronized|native|default|\s)+\s*[\w.<>,[\]\s]+\s+([A-Za-z_]\w*)\s*\(/g,
|
|
10113
10141
|
kind: "method"
|
|
10114
10142
|
}
|
|
10115
10143
|
],
|
|
@@ -10117,7 +10145,7 @@ var LANG_PATTERNS = {
|
|
|
10117
10145
|
{ re: /\b(?:class|interface|struct|enum|record)\s+([A-Za-z_]\w*)/g, kind: "class" },
|
|
10118
10146
|
{ re: /\bnamespace\s+([A-Za-z_.\w]+)/g, kind: "namespace" },
|
|
10119
10147
|
{
|
|
10120
|
-
re: /\b(?:public|private|protected|internal|static|async|override|virtual|\s)+\s*[\w
|
|
10148
|
+
re: /\b(?:public|private|protected|internal|static|async|override|virtual|\s)+\s*[\w.<>,[\]\s]+\s+([A-Za-z_]\w*)\s*\(/g,
|
|
10121
10149
|
kind: "method"
|
|
10122
10150
|
}
|
|
10123
10151
|
],
|
|
@@ -10322,8 +10350,7 @@ function parseGeneric2(opts) {
|
|
|
10322
10350
|
for (const pattern of patterns) {
|
|
10323
10351
|
const re = new RegExp(pattern.re.source, pattern.re.flags.includes("g") ? pattern.re.flags : `${pattern.re.flags}g`);
|
|
10324
10352
|
re.lastIndex = 0;
|
|
10325
|
-
|
|
10326
|
-
while ((match = re.exec(content)) !== null) {
|
|
10353
|
+
for (const match of content.matchAll(re)) {
|
|
10327
10354
|
if (symbols.length >= maxSymbols) break;
|
|
10328
10355
|
let name = (match[1] ?? match[2] ?? "").trim();
|
|
10329
10356
|
if (lang === "md" && match[2]) name = match[2].trim();
|
|
@@ -11279,17 +11306,7 @@ function throwIfAborted(signal) {
|
|
|
11279
11306
|
function isAbortError(err) {
|
|
11280
11307
|
return err instanceof DOMException && err.name === "AbortError";
|
|
11281
11308
|
}
|
|
11282
|
-
var DEFAULT_IGNORE =
|
|
11283
|
-
"node_modules",
|
|
11284
|
-
".git",
|
|
11285
|
-
"dist",
|
|
11286
|
-
"build",
|
|
11287
|
-
".next",
|
|
11288
|
-
"coverage",
|
|
11289
|
-
".turbo",
|
|
11290
|
-
"__snapshots__",
|
|
11291
|
-
".nyc_output"
|
|
11292
|
-
];
|
|
11309
|
+
var DEFAULT_IGNORE = DEFAULT_WALK_IGNORE_DIRS;
|
|
11293
11310
|
var DEFAULT_IGNORE_FILES = /* @__PURE__ */ new Set(["package-lock.json", "pnpm-lock.yaml", "pnpm-lock.yml"]);
|
|
11294
11311
|
var MAX_INDEX_FILE_BYTES = 5 * 1024 * 1024;
|
|
11295
11312
|
function isWithinProject(projectRoot, file) {
|
|
@@ -16053,7 +16070,7 @@ function runGit2(args, cwd, signal) {
|
|
|
16053
16070
|
// src/glob.ts
|
|
16054
16071
|
import * as fs20 from "node:fs/promises";
|
|
16055
16072
|
import * as path26 from "node:path";
|
|
16056
|
-
import { compileGlob as compileGlob2 } from "@wrongstack/core/utils";
|
|
16073
|
+
import { compileGlob as compileGlob2, DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS2 } from "@wrongstack/core/utils";
|
|
16057
16074
|
|
|
16058
16075
|
// src/_concurrency.ts
|
|
16059
16076
|
async function mapWithConcurrency(items, limit, fn) {
|
|
@@ -16074,7 +16091,7 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
16074
16091
|
|
|
16075
16092
|
// src/glob.ts
|
|
16076
16093
|
init_util();
|
|
16077
|
-
var DEFAULT_IGNORE2 =
|
|
16094
|
+
var DEFAULT_IGNORE2 = DEFAULT_WALK_IGNORE_DIRS2;
|
|
16078
16095
|
var WALK_CONCURRENCY = 16;
|
|
16079
16096
|
var globTool = {
|
|
16080
16097
|
name: "glob",
|
|
@@ -16114,7 +16131,7 @@ var globTool = {
|
|
|
16114
16131
|
const signal = opts?.signal;
|
|
16115
16132
|
const base = input.path ? await safeResolveReal(input.path, ctx) : ctx.cwd;
|
|
16116
16133
|
const limit = Math.max(1, Math.min(input.limit ?? 1e3, 5e3));
|
|
16117
|
-
const
|
|
16134
|
+
const isGitIgnored = await loadGitignoreMatcher(base);
|
|
16118
16135
|
const re = compileGlob2(input.pattern);
|
|
16119
16136
|
const results = [];
|
|
16120
16137
|
let truncated = false;
|
|
@@ -16154,12 +16171,13 @@ var globTool = {
|
|
|
16154
16171
|
for (const e of entries) {
|
|
16155
16172
|
const name = e.name;
|
|
16156
16173
|
if (DEFAULT_IGNORE2.includes(name)) continue;
|
|
16157
|
-
if (ignored.includes(name)) continue;
|
|
16158
16174
|
const rel = relPrefix ? `${relPrefix}/${name}` : name;
|
|
16159
16175
|
const full = path26.join(dir, name);
|
|
16160
16176
|
if (e.isDirectory()) {
|
|
16177
|
+
if (isGitIgnored(rel, true)) continue;
|
|
16161
16178
|
subdirs.push({ full, rel });
|
|
16162
16179
|
} else if (e.isFile()) {
|
|
16180
|
+
if (isGitIgnored(rel, false)) continue;
|
|
16163
16181
|
re.lastIndex = 0;
|
|
16164
16182
|
const relMatch = re.test(rel);
|
|
16165
16183
|
re.lastIndex = 0;
|
|
@@ -16171,10 +16189,12 @@ var globTool = {
|
|
|
16171
16189
|
try {
|
|
16172
16190
|
const st = await fs20.stat(full);
|
|
16173
16191
|
if (st.isDirectory()) {
|
|
16192
|
+
if (isGitIgnored(rel, true)) continue;
|
|
16174
16193
|
const real = await fs20.realpath(full);
|
|
16175
16194
|
await assertRealInsideRoot(real, ctx);
|
|
16176
16195
|
subdirs.push({ full, rel });
|
|
16177
16196
|
} else if (st.isFile()) {
|
|
16197
|
+
if (isGitIgnored(rel, false)) continue;
|
|
16178
16198
|
const real = await fs20.realpath(full);
|
|
16179
16199
|
await assertRealInsideRoot(real, ctx);
|
|
16180
16200
|
re.lastIndex = 0;
|
|
@@ -16198,14 +16218,6 @@ var globTool = {
|
|
|
16198
16218
|
return { files: results.map((r) => r.rel), truncated };
|
|
16199
16219
|
}
|
|
16200
16220
|
};
|
|
16201
|
-
async function readGitignore(dir) {
|
|
16202
|
-
try {
|
|
16203
|
-
const raw = await fs20.readFile(path26.join(dir, ".gitignore"), "utf8");
|
|
16204
|
-
return raw.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
16205
|
-
} catch {
|
|
16206
|
-
return [];
|
|
16207
|
-
}
|
|
16208
|
-
}
|
|
16209
16221
|
|
|
16210
16222
|
// src/grep.ts
|
|
16211
16223
|
import { expectDefined as expectDefined7 } from "@wrongstack/core/utils";
|
|
@@ -16213,7 +16225,7 @@ import { spawn as spawn10 } from "node:child_process";
|
|
|
16213
16225
|
import * as fs21 from "node:fs/promises";
|
|
16214
16226
|
import * as path27 from "node:path";
|
|
16215
16227
|
import { ToolValidationError as ToolValidationError4 } from "@wrongstack/core/types";
|
|
16216
|
-
import { buildChildEnv as buildChildEnv5, compileGlob as compileGlob3 } from "@wrongstack/core/utils";
|
|
16228
|
+
import { buildChildEnv as buildChildEnv5, compileGlob as compileGlob3, DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS3 } from "@wrongstack/core/utils";
|
|
16217
16229
|
|
|
16218
16230
|
// src/_regex.ts
|
|
16219
16231
|
var MAX_PATTERN_LEN = 256;
|
|
@@ -16262,7 +16274,7 @@ function capSubject(line) {
|
|
|
16262
16274
|
|
|
16263
16275
|
// src/grep.ts
|
|
16264
16276
|
init_util();
|
|
16265
|
-
var DEFAULT_IGNORE3 =
|
|
16277
|
+
var DEFAULT_IGNORE3 = DEFAULT_WALK_IGNORE_DIRS3;
|
|
16266
16278
|
var NATIVE_SCAN_CONCURRENCY = 32;
|
|
16267
16279
|
var NATIVE_READ_CHUNK_BYTES = 64 * 1024;
|
|
16268
16280
|
var NATIVE_MAX_FILE_BYTES = 1e6;
|
|
@@ -16379,6 +16391,10 @@ async function* runRgStream(input, base, mode, limit, signal) {
|
|
|
16379
16391
|
for (const ignored of DEFAULT_IGNORE3) {
|
|
16380
16392
|
args.push("--glob", `!${ignored}/**`, "--glob", `!**/${ignored}/**`);
|
|
16381
16393
|
}
|
|
16394
|
+
const gitignorePath = path27.join(base, ".gitignore");
|
|
16395
|
+
if (await fs21.access(gitignorePath).then(() => true, () => false)) {
|
|
16396
|
+
args.push("--ignore-file", gitignorePath);
|
|
16397
|
+
}
|
|
16382
16398
|
if (input.glob) args.push("--glob", input.glob);
|
|
16383
16399
|
args.push("--", input.pattern, base);
|
|
16384
16400
|
const matches = [];
|
|
@@ -16504,6 +16520,7 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
16504
16520
|
}
|
|
16505
16521
|
const re = compiled.regex;
|
|
16506
16522
|
const globRe = input.glob ? compileGlob3(input.glob) : null;
|
|
16523
|
+
const isGitIgnored = await loadGitignoreMatcher(base);
|
|
16507
16524
|
const matches = [];
|
|
16508
16525
|
const countOnlyFirstHit = mode === "count" && limit === 1;
|
|
16509
16526
|
const maxBytes = mode === "content" ? NATIVE_MAX_FILE_BYTES : Math.min(NATIVE_MAX_FILE_BYTES, 256 * 1024);
|
|
@@ -16591,7 +16608,7 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
16591
16608
|
} catch {
|
|
16592
16609
|
}
|
|
16593
16610
|
};
|
|
16594
|
-
const walk = async (dir) => {
|
|
16611
|
+
const walk = async (dir, relPrefix) => {
|
|
16595
16612
|
if (stopped || signal.aborted) return;
|
|
16596
16613
|
let entries;
|
|
16597
16614
|
try {
|
|
@@ -16605,17 +16622,24 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
16605
16622
|
if (stopped) return;
|
|
16606
16623
|
if (DEFAULT_IGNORE3.includes(e.name)) continue;
|
|
16607
16624
|
if (e.isSymbolicLink()) continue;
|
|
16625
|
+
const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
|
|
16608
16626
|
const full = path27.join(dir, e.name);
|
|
16609
16627
|
if (e.isDirectory()) {
|
|
16610
|
-
|
|
16628
|
+
if (isGitIgnored(rel, true)) continue;
|
|
16629
|
+
subdirs.push({ full, rel });
|
|
16611
16630
|
} else if (e.isFile()) {
|
|
16631
|
+
if (isGitIgnored(rel, false)) continue;
|
|
16612
16632
|
files.push({ full, name: e.name });
|
|
16613
16633
|
}
|
|
16614
16634
|
}
|
|
16615
16635
|
await mapWithConcurrency(files, NATIVE_SCAN_CONCURRENCY, ({ full, name }) => scanFile(full, name));
|
|
16616
|
-
await mapWithConcurrency(
|
|
16636
|
+
await mapWithConcurrency(
|
|
16637
|
+
subdirs,
|
|
16638
|
+
Math.min(16, NATIVE_SCAN_CONCURRENCY),
|
|
16639
|
+
({ full, rel }) => walk(full, rel)
|
|
16640
|
+
);
|
|
16617
16641
|
};
|
|
16618
|
-
await walk(base);
|
|
16642
|
+
await walk(base, "");
|
|
16619
16643
|
return {
|
|
16620
16644
|
matches,
|
|
16621
16645
|
count: total,
|
|
@@ -17345,9 +17369,35 @@ import {
|
|
|
17345
17369
|
updateGoalMetricOnTask,
|
|
17346
17370
|
updateTask,
|
|
17347
17371
|
updateTaskAssignment,
|
|
17348
|
-
verifyTaskCompletion
|
|
17372
|
+
verifyTaskCompletion,
|
|
17373
|
+
finalizeTaskCompletion,
|
|
17374
|
+
assessTaskAtomicity,
|
|
17375
|
+
proposeTaskDecomposition
|
|
17349
17376
|
} from "@wrongstack/kanban";
|
|
17350
17377
|
|
|
17378
|
+
// src/kanban-evidence-bridge.ts
|
|
17379
|
+
import { recordCompletedWorkEvidence } from "@wrongstack/core/utils";
|
|
17380
|
+
function kanbanEvidenceKey(boardId, taskId) {
|
|
17381
|
+
return `kanban:${boardId}:${taskId}`;
|
|
17382
|
+
}
|
|
17383
|
+
function kanbanEvidencePointer(boardId, taskId) {
|
|
17384
|
+
return `kanban://${boardId}/${taskId}#verificationReport`;
|
|
17385
|
+
}
|
|
17386
|
+
function recordKanbanVerificationEvidence(ctx, report) {
|
|
17387
|
+
try {
|
|
17388
|
+
const passed = report.checks.filter((check) => check.status === "passed").length;
|
|
17389
|
+
const completedAt = Date.parse(report.completedAt);
|
|
17390
|
+
recordCompletedWorkEvidence(ctx, {
|
|
17391
|
+
key: kanbanEvidenceKey(report.boardId, report.taskId),
|
|
17392
|
+
source: "verification",
|
|
17393
|
+
summary: `${report.taskTitle} \u2014 verification ${report.verdict} (${passed}/${report.checks.length} checks)`,
|
|
17394
|
+
...Number.isFinite(completedAt) ? { completedAt } : {},
|
|
17395
|
+
evidence: kanbanEvidencePointer(report.boardId, report.taskId)
|
|
17396
|
+
});
|
|
17397
|
+
} catch {
|
|
17398
|
+
}
|
|
17399
|
+
}
|
|
17400
|
+
|
|
17351
17401
|
// src/session-kanban.ts
|
|
17352
17402
|
import { GlobalMailbox } from "@wrongstack/core/coordination";
|
|
17353
17403
|
import {
|
|
@@ -17636,7 +17686,9 @@ var kanbanTool = {
|
|
|
17636
17686
|
"add_note",
|
|
17637
17687
|
"add_link",
|
|
17638
17688
|
"verify_completion",
|
|
17639
|
-
"split_atomic"
|
|
17689
|
+
"split_atomic",
|
|
17690
|
+
"assess_atomicity",
|
|
17691
|
+
"propose_decomposition"
|
|
17640
17692
|
]
|
|
17641
17693
|
},
|
|
17642
17694
|
boardId: { type: "string" },
|
|
@@ -17772,7 +17824,24 @@ var kanbanTool = {
|
|
|
17772
17824
|
includeCompletedTasks: { type: "boolean" },
|
|
17773
17825
|
preserveAssignment: { type: "boolean" },
|
|
17774
17826
|
preserveDependencies: { type: "boolean" },
|
|
17775
|
-
moveTasksToColumnId: { type: "string" }
|
|
17827
|
+
moveTasksToColumnId: { type: "string" },
|
|
17828
|
+
atomicityMode: { type: "string", enum: ["off", "assess", "enforce"] },
|
|
17829
|
+
atomicityDecomposition: { type: "string", enum: ["auto", "propose"] },
|
|
17830
|
+
gateEnforcement: { type: "string", enum: ["strict", "soft", "off"] },
|
|
17831
|
+
subtasks: {
|
|
17832
|
+
type: "array",
|
|
17833
|
+
minItems: 2,
|
|
17834
|
+
items: {
|
|
17835
|
+
type: "object",
|
|
17836
|
+
properties: {
|
|
17837
|
+
title: { type: "string" },
|
|
17838
|
+
description: { type: "string" },
|
|
17839
|
+
successCriteria: { type: "array", items: { type: "string" } },
|
|
17840
|
+
dependsOnIndex: { type: "array", items: { type: "number" } }
|
|
17841
|
+
},
|
|
17842
|
+
required: ["title"]
|
|
17843
|
+
}
|
|
17844
|
+
}
|
|
17776
17845
|
},
|
|
17777
17846
|
required: ["action"]
|
|
17778
17847
|
},
|
|
@@ -17812,7 +17881,14 @@ var kanbanTool = {
|
|
|
17812
17881
|
title: input.title,
|
|
17813
17882
|
...input.description !== void 0 ? { description: input.description } : {},
|
|
17814
17883
|
...input.tags !== void 0 ? { tags: input.tags } : {},
|
|
17815
|
-
...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {}
|
|
17884
|
+
...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {},
|
|
17885
|
+
...input.atomicityMode !== void 0 ? {
|
|
17886
|
+
atomicity: {
|
|
17887
|
+
mode: input.atomicityMode,
|
|
17888
|
+
decomposition: input.atomicityDecomposition ?? "propose"
|
|
17889
|
+
}
|
|
17890
|
+
} : {},
|
|
17891
|
+
...input.gateEnforcement !== void 0 ? { completionGate: { enforcement: input.gateEnforcement } } : {}
|
|
17816
17892
|
});
|
|
17817
17893
|
return { ok: true, message: `Board created: ${board.title}`, board };
|
|
17818
17894
|
}
|
|
@@ -17821,7 +17897,14 @@ var kanbanTool = {
|
|
|
17821
17897
|
const board = await updateBoard2(projectRoot, input.boardId, {
|
|
17822
17898
|
...input.title !== void 0 ? { title: input.title } : {},
|
|
17823
17899
|
...input.description !== void 0 ? { description: input.description } : {},
|
|
17824
|
-
...input.tags !== void 0 ? { tags: input.tags } : {}
|
|
17900
|
+
...input.tags !== void 0 ? { tags: input.tags } : {},
|
|
17901
|
+
...input.atomicityMode !== void 0 ? {
|
|
17902
|
+
atomicity: {
|
|
17903
|
+
mode: input.atomicityMode,
|
|
17904
|
+
decomposition: input.atomicityDecomposition ?? "propose"
|
|
17905
|
+
}
|
|
17906
|
+
} : {},
|
|
17907
|
+
...input.gateEnforcement !== void 0 ? { completionGate: { enforcement: input.gateEnforcement } } : {}
|
|
17825
17908
|
});
|
|
17826
17909
|
return board ? okBoard(board, "Board updated.") : fail("Board not found.");
|
|
17827
17910
|
}
|
|
@@ -18029,7 +18112,12 @@ var kanbanTool = {
|
|
|
18029
18112
|
case "add_task": {
|
|
18030
18113
|
if (!input.boardId || !input.title) return fail("add_task requires boardId and title.");
|
|
18031
18114
|
const result2 = await addTask(projectRoot, input.boardId, taskInput(input));
|
|
18032
|
-
|
|
18115
|
+
if (!result2) return fail("Board not found.");
|
|
18116
|
+
return okTask(
|
|
18117
|
+
result2.board,
|
|
18118
|
+
result2.task,
|
|
18119
|
+
`Task added.${atomicityNudge(result2.task)}`
|
|
18120
|
+
);
|
|
18033
18121
|
}
|
|
18034
18122
|
case "split_task": {
|
|
18035
18123
|
if (!input.boardId || !input.taskId || !input.childTitles?.length) {
|
|
@@ -18109,6 +18197,19 @@ var kanbanTool = {
|
|
|
18109
18197
|
"transition_task requires boardId, taskId, lifecycleStage, author, and transitionComment."
|
|
18110
18198
|
);
|
|
18111
18199
|
}
|
|
18200
|
+
if (input.lifecycleStage === "done") {
|
|
18201
|
+
const boardBefore = await getBoard2(projectRoot, input.boardId);
|
|
18202
|
+
const taskBefore = boardBefore ? await getTask(projectRoot, input.boardId, input.taskId) : null;
|
|
18203
|
+
if (boardBefore && taskBefore && !taskBefore.verificationReport && (taskBefore.atomic || Boolean(taskBefore.successCriteria?.length))) {
|
|
18204
|
+
const preGate = await verifyTaskCompletion(projectRoot, input.boardId, taskBefore.id, {
|
|
18205
|
+
persist: false
|
|
18206
|
+
});
|
|
18207
|
+
await updateTask(projectRoot, input.boardId, taskBefore.id, {
|
|
18208
|
+
verificationReport: preGate.report,
|
|
18209
|
+
successCriteria: preGate.task.successCriteria
|
|
18210
|
+
});
|
|
18211
|
+
}
|
|
18212
|
+
}
|
|
18112
18213
|
const result2 = await transitionTask(projectRoot, input.boardId, input.taskId, {
|
|
18113
18214
|
to: input.lifecycleStage,
|
|
18114
18215
|
actor: input.author,
|
|
@@ -18123,6 +18224,9 @@ var kanbanTool = {
|
|
|
18123
18224
|
} : {},
|
|
18124
18225
|
patch: taskPatch(input)
|
|
18125
18226
|
});
|
|
18227
|
+
if (result2 && input.lifecycleStage === "done" && result2.task.verificationReport) {
|
|
18228
|
+
recordKanbanVerificationEvidence(ctx, result2.task.verificationReport);
|
|
18229
|
+
}
|
|
18126
18230
|
return result2 ? okTask(result2.board, result2.task, `Task advanced to ${result2.transition.to}.`) : fail("Board or task not found.");
|
|
18127
18231
|
}
|
|
18128
18232
|
case "move_task": {
|
|
@@ -18236,7 +18340,31 @@ var kanbanTool = {
|
|
|
18236
18340
|
// is atomic inside updateTaskAssignment's mutateBoard lock.
|
|
18237
18341
|
input.expectedLeaseId !== void 0 ? { expectedLeaseId: input.expectedLeaseId } : {}
|
|
18238
18342
|
);
|
|
18239
|
-
|
|
18343
|
+
if (!board) return fail("Task not found.");
|
|
18344
|
+
if (assignmentStatus === "completed") {
|
|
18345
|
+
const envGate = readEnvGateEnforcement();
|
|
18346
|
+
const finalized = await finalizeTaskCompletion(projectRoot, board.id, input.taskId, {
|
|
18347
|
+
...board.completionGate === void 0 && envGate !== void 0 ? { enforcement: envGate } : {},
|
|
18348
|
+
...ctx.agentId !== void 0 ? { eventContext: { actor: ctx.agentId } } : {}
|
|
18349
|
+
});
|
|
18350
|
+
if (finalized) {
|
|
18351
|
+
if (finalized.gate.report) {
|
|
18352
|
+
recordKanbanVerificationEvidence(ctx, finalized.gate.report);
|
|
18353
|
+
}
|
|
18354
|
+
const gateSummary = {
|
|
18355
|
+
enforcement: finalized.gate.enforcement,
|
|
18356
|
+
allowed: finalized.gate.allowed,
|
|
18357
|
+
verdict: finalized.gate.verdict,
|
|
18358
|
+
issues: finalized.gate.issues.map((issue) => issue.message)
|
|
18359
|
+
};
|
|
18360
|
+
const gateMessage = finalized.gate.allowed ? `Completion gate ${finalized.gate.verdict === "skipped" ? "skipped" : "passed"}; task completed.` : finalized.gate.enforcement === "strict" ? `Completion gate BLOCKED (verdict: ${finalized.gate.verdict}); task parked in review. Issues: ${gateSummary.issues.join(" | ")}` : `Completion gate failed softly (verdict: ${finalized.gate.verdict}); task completed with warnings. Issues: ${gateSummary.issues.join(" | ")}`;
|
|
18361
|
+
return {
|
|
18362
|
+
...okTask(finalized.board, finalized.task, `Assignment updated. ${gateMessage}`),
|
|
18363
|
+
gate: gateSummary
|
|
18364
|
+
};
|
|
18365
|
+
}
|
|
18366
|
+
}
|
|
18367
|
+
return okBoard(board, "Assignment updated.");
|
|
18240
18368
|
}
|
|
18241
18369
|
case "heartbeat_assignment": {
|
|
18242
18370
|
if (!input.boardId || !input.taskId) {
|
|
@@ -18400,6 +18528,49 @@ var kanbanTool = {
|
|
|
18400
18528
|
});
|
|
18401
18529
|
return board ? okBoard(board, "Link added.") : fail("Task not found.");
|
|
18402
18530
|
}
|
|
18531
|
+
case "assess_atomicity": {
|
|
18532
|
+
if (!input.boardId || !input.taskId) {
|
|
18533
|
+
return fail("assess_atomicity requires boardId and taskId.");
|
|
18534
|
+
}
|
|
18535
|
+
const result2 = await assessTaskAtomicity(projectRoot, input.boardId, input.taskId, {
|
|
18536
|
+
assessedBy: "agent",
|
|
18537
|
+
...ctx.agentId !== void 0 ? { eventContext: { actor: ctx.agentId } } : {}
|
|
18538
|
+
});
|
|
18539
|
+
if (!result2) return fail("Task not found.");
|
|
18540
|
+
const failing = result2.assessment.criteria.filter((entry) => entry.score < 1).map((entry) => entry.reason);
|
|
18541
|
+
const guidance = result2.assessment.verdict === "needs_decomposition" ? ` This task should be split before dispatch \u2014 call propose_decomposition with 2+ subtasks (each with one verifiable success criterion). Reasons: ${failing.join(" | ")}` : result2.assessment.verdict === "composite" ? " Container task: work happens in its children; it is verified via subtask aggregation." : "";
|
|
18542
|
+
return okTask(
|
|
18543
|
+
result2.board,
|
|
18544
|
+
result2.task,
|
|
18545
|
+
`Atomicity verdict: ${result2.assessment.verdict} (score ${result2.assessment.score}).${guidance}`
|
|
18546
|
+
);
|
|
18547
|
+
}
|
|
18548
|
+
case "propose_decomposition": {
|
|
18549
|
+
if (!input.boardId || !input.taskId || !input.subtasks?.length) {
|
|
18550
|
+
return fail("propose_decomposition requires boardId, taskId, and subtasks (2+).");
|
|
18551
|
+
}
|
|
18552
|
+
if (input.subtasks.length < 2) {
|
|
18553
|
+
return fail("propose_decomposition requires at least two subtasks.");
|
|
18554
|
+
}
|
|
18555
|
+
const invalid = input.subtasks.find(
|
|
18556
|
+
(subtask) => typeof subtask?.title !== "string" || !subtask.title.trim()
|
|
18557
|
+
);
|
|
18558
|
+
if (invalid) return fail("Every proposed subtask needs a non-blank title.");
|
|
18559
|
+
const result2 = await proposeTaskDecomposition(
|
|
18560
|
+
projectRoot,
|
|
18561
|
+
input.boardId,
|
|
18562
|
+
input.taskId,
|
|
18563
|
+
{
|
|
18564
|
+
subtasks: input.subtasks,
|
|
18565
|
+
...input.note !== void 0 ? { rationale: input.note } : {},
|
|
18566
|
+
...ctx.agentId !== void 0 ? { proposedBy: ctx.agentId } : {}
|
|
18567
|
+
},
|
|
18568
|
+
ctx.agentId !== void 0 ? { actor: ctx.agentId } : {}
|
|
18569
|
+
);
|
|
18570
|
+
if (!result2) return fail("Task not found.");
|
|
18571
|
+
const message = result2.proposal.status === "applied" ? `Decomposition applied: ${result2.proposal.appliedChildTaskIds?.length ?? 0} child tasks created (parent marked atomic).` : 'Decomposition proposal recorded \u2014 awaiting approval (board policy is "propose"). It can be approved from the WebUI or via update_task.';
|
|
18572
|
+
return okTask(result2.board, result2.task, message);
|
|
18573
|
+
}
|
|
18403
18574
|
case "verify_completion": {
|
|
18404
18575
|
if (!input.boardId || !input.taskId) {
|
|
18405
18576
|
return fail("verify_completion requires boardId and taskId.");
|
|
@@ -18417,6 +18588,7 @@ var kanbanTool = {
|
|
|
18417
18588
|
board: verResult.board
|
|
18418
18589
|
};
|
|
18419
18590
|
}
|
|
18591
|
+
recordKanbanVerificationEvidence(ctx, verResult.report);
|
|
18420
18592
|
const freshTask = persistedBoard.tasks?.find((t) => t.id === input.taskId);
|
|
18421
18593
|
const deterministicVerdicts = ["passed", "failed", "needs_human", "incomplete"];
|
|
18422
18594
|
return {
|
|
@@ -18443,6 +18615,15 @@ var kanbanTool = {
|
|
|
18443
18615
|
}
|
|
18444
18616
|
}
|
|
18445
18617
|
};
|
|
18618
|
+
function atomicityNudge(task) {
|
|
18619
|
+
if (task.atomicityAssessment?.verdict !== "needs_decomposition") return "";
|
|
18620
|
+
const reasons = task.atomicityAssessment.criteria.filter((entry) => entry.score < 1).map((entry) => entry.reason).join(" | ");
|
|
18621
|
+
return ` Atomicity: needs_decomposition (score ${task.atomicityAssessment.score}) \u2014 call propose_decomposition with 2+ subtasks before dispatch. Reasons: ${reasons}`;
|
|
18622
|
+
}
|
|
18623
|
+
function readEnvGateEnforcement() {
|
|
18624
|
+
const raw = process.env["WRONGSTACK_KANBAN_GATE"]?.trim().toLowerCase();
|
|
18625
|
+
return raw === "strict" || raw === "soft" || raw === "off" ? raw : void 0;
|
|
18626
|
+
}
|
|
18446
18627
|
function fail(message) {
|
|
18447
18628
|
return { ok: false, message };
|
|
18448
18629
|
}
|
|
@@ -21664,22 +21845,10 @@ var toolUseTool = {
|
|
|
21664
21845
|
|
|
21665
21846
|
// src/tree.ts
|
|
21666
21847
|
init_util();
|
|
21667
|
-
import { expectDefined as expectDefined10 } from "@wrongstack/core/utils";
|
|
21848
|
+
import { DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS4, expectDefined as expectDefined10 } from "@wrongstack/core/utils";
|
|
21668
21849
|
import * as fs28 from "node:fs/promises";
|
|
21669
21850
|
import * as path32 from "node:path";
|
|
21670
|
-
var DEFAULT_IGNORE5 = [
|
|
21671
|
-
"node_modules",
|
|
21672
|
-
".git",
|
|
21673
|
-
"dist",
|
|
21674
|
-
"build",
|
|
21675
|
-
".next",
|
|
21676
|
-
"coverage",
|
|
21677
|
-
"__pycache__",
|
|
21678
|
-
".wrongstack",
|
|
21679
|
-
".ssh",
|
|
21680
|
-
".gnupg",
|
|
21681
|
-
".aws"
|
|
21682
|
-
];
|
|
21851
|
+
var DEFAULT_IGNORE5 = [...DEFAULT_WALK_IGNORE_DIRS4, ".wrongstack", ".ssh", ".gnupg", ".aws"];
|
|
21683
21852
|
var treeTool = {
|
|
21684
21853
|
name: "tree",
|
|
21685
21854
|
category: "Filesystem",
|