@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/index.js
CHANGED
|
@@ -5380,6 +5380,7 @@ function emitStructuredLog(level, event, message, error) {
|
|
|
5380
5380
|
}
|
|
5381
5381
|
var HEARTBEAT_INTERVAL_MS = 5e3;
|
|
5382
5382
|
var STALE_THRESHOLD_MS = 3e4;
|
|
5383
|
+
var LOCK_STALE_MS = 3e4;
|
|
5383
5384
|
var LOCKFILE = ".process-registry.lock";
|
|
5384
5385
|
function generateInstanceId() {
|
|
5385
5386
|
const hostname4 = os2.hostname();
|
|
@@ -5408,21 +5409,26 @@ async function acquireLock(lockfilePath, timeoutMs = 5e3) {
|
|
|
5408
5409
|
try {
|
|
5409
5410
|
const content = await fs6.readFile(lockfilePath, "utf-8");
|
|
5410
5411
|
const parts = content.split(":");
|
|
5411
|
-
const
|
|
5412
|
-
const
|
|
5413
|
-
|
|
5412
|
+
const lockPid = parseInt(parts[0] ?? "0", 10);
|
|
5413
|
+
const lockTs = Number(parts[parts.length - 1]);
|
|
5414
|
+
const staleByAge = Number.isFinite(lockTs) && Date.now() - lockTs > LOCK_STALE_MS;
|
|
5415
|
+
let holderDead = false;
|
|
5416
|
+
if (process.platform !== "win32" && Number.isFinite(lockPid) && lockPid > 0) {
|
|
5414
5417
|
try {
|
|
5415
5418
|
process.kill(lockPid, 0);
|
|
5416
5419
|
} catch {
|
|
5417
|
-
|
|
5418
|
-
continue;
|
|
5420
|
+
holderDead = true;
|
|
5419
5421
|
}
|
|
5420
5422
|
}
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5423
|
+
if (holderDead || staleByAge) {
|
|
5424
|
+
await fs6.unlink(lockfilePath).catch(() => {
|
|
5425
|
+
});
|
|
5426
|
+
continue;
|
|
5425
5427
|
}
|
|
5428
|
+
} catch {
|
|
5429
|
+
await fs6.unlink(lockfilePath).catch(() => {
|
|
5430
|
+
});
|
|
5431
|
+
continue;
|
|
5426
5432
|
}
|
|
5427
5433
|
await new Promise((r) => setTimeout(r, 100));
|
|
5428
5434
|
continue;
|
|
@@ -5432,25 +5438,35 @@ async function acquireLock(lockfilePath, timeoutMs = 5e3) {
|
|
|
5432
5438
|
}
|
|
5433
5439
|
throw new Error(`Failed to acquire lock after ${timeoutMs}ms`);
|
|
5434
5440
|
}
|
|
5441
|
+
function freshRegistryData() {
|
|
5442
|
+
return {
|
|
5443
|
+
version: 1,
|
|
5444
|
+
instances: /* @__PURE__ */ new Map(),
|
|
5445
|
+
protectedPatterns: ["wrongstack", "node"],
|
|
5446
|
+
lastCleanup: Date.now()
|
|
5447
|
+
};
|
|
5448
|
+
}
|
|
5435
5449
|
async function readRegistryFile(filePath) {
|
|
5450
|
+
let content;
|
|
5436
5451
|
try {
|
|
5437
|
-
|
|
5438
|
-
const parsed = JSON.parse(content);
|
|
5439
|
-
if (parsed.instances && Array.isArray(parsed.instances)) {
|
|
5440
|
-
parsed.instances = new Map(parsed.instances);
|
|
5441
|
-
}
|
|
5442
|
-
return parsed;
|
|
5452
|
+
content = await fs6.readFile(filePath, "utf-8");
|
|
5443
5453
|
} catch (err) {
|
|
5444
|
-
if (isNodeError(err) && err.code === "ENOENT")
|
|
5445
|
-
return {
|
|
5446
|
-
version: 1,
|
|
5447
|
-
instances: /* @__PURE__ */ new Map(),
|
|
5448
|
-
protectedPatterns: ["wrongstack", "node"],
|
|
5449
|
-
lastCleanup: Date.now()
|
|
5450
|
-
};
|
|
5451
|
-
}
|
|
5454
|
+
if (isNodeError(err) && err.code === "ENOENT") return freshRegistryData();
|
|
5452
5455
|
throw err;
|
|
5453
5456
|
}
|
|
5457
|
+
try {
|
|
5458
|
+
const parsed = JSON.parse(content);
|
|
5459
|
+
if (!parsed || typeof parsed !== "object") return freshRegistryData();
|
|
5460
|
+
const base = freshRegistryData();
|
|
5461
|
+
return {
|
|
5462
|
+
version: 1,
|
|
5463
|
+
instances: Array.isArray(parsed.instances) ? new Map(parsed.instances) : base.instances,
|
|
5464
|
+
protectedPatterns: Array.isArray(parsed.protectedPatterns) ? parsed.protectedPatterns : base.protectedPatterns,
|
|
5465
|
+
lastCleanup: typeof parsed.lastCleanup === "number" ? parsed.lastCleanup : base.lastCleanup
|
|
5466
|
+
};
|
|
5467
|
+
} catch {
|
|
5468
|
+
return freshRegistryData();
|
|
5469
|
+
}
|
|
5454
5470
|
}
|
|
5455
5471
|
async function writeRegistryFile(filePath, data) {
|
|
5456
5472
|
const tmpPath = `${filePath}.tmp.${process.pid}`;
|
|
@@ -9455,11 +9471,12 @@ var IndexStore = class _IndexStore {
|
|
|
9455
9471
|
}
|
|
9456
9472
|
}
|
|
9457
9473
|
const refRows = this.stmt(
|
|
9458
|
-
`SELECT r.call_type, sf.file AS from_file, st.file AS to_file
|
|
9474
|
+
`SELECT r.call_type, sf.file AS from_file, st.file AS to_file, COUNT(*) AS n
|
|
9459
9475
|
FROM refs r
|
|
9460
9476
|
JOIN symbols sf ON sf.id = r.from_id
|
|
9461
9477
|
JOIN symbols st ON st.id = r.to_id
|
|
9462
|
-
WHERE r.to_id IS NOT NULL AND r.call_type != 'import'
|
|
9478
|
+
WHERE r.to_id IS NOT NULL AND r.call_type != 'import'
|
|
9479
|
+
GROUP BY r.call_type, sf.file, st.file`
|
|
9463
9480
|
).all();
|
|
9464
9481
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
9465
9482
|
for (const r of refRows) {
|
|
@@ -9472,14 +9489,16 @@ var IndexStore = class _IndexStore {
|
|
|
9472
9489
|
e = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9473
9490
|
edgeMap.set(key, e);
|
|
9474
9491
|
}
|
|
9475
|
-
|
|
9476
|
-
e.
|
|
9492
|
+
const n = Number(r.n) || 0;
|
|
9493
|
+
e.weight += n;
|
|
9494
|
+
e.types.set(r.call_type, (e.types.get(r.call_type) ?? 0) + n);
|
|
9477
9495
|
}
|
|
9478
9496
|
const importRows = this.stmt(
|
|
9479
|
-
`SELECT r.to_name, s.file AS from_file
|
|
9497
|
+
`SELECT r.to_name, s.file AS from_file, COUNT(*) AS n
|
|
9480
9498
|
FROM refs r
|
|
9481
9499
|
JOIN symbols s ON s.id = r.from_id
|
|
9482
|
-
WHERE r.call_type = 'import'
|
|
9500
|
+
WHERE r.call_type = 'import'
|
|
9501
|
+
GROUP BY r.to_name, s.file`
|
|
9483
9502
|
).all();
|
|
9484
9503
|
for (const r of importRows) {
|
|
9485
9504
|
const fromPkg = fileToPkg.get(r.from_file) ?? _IndexStore.derivePackage(r.from_file) ?? "(root)";
|
|
@@ -9491,8 +9510,9 @@ var IndexStore = class _IndexStore {
|
|
|
9491
9510
|
edge = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9492
9511
|
edgeMap.set(key, edge);
|
|
9493
9512
|
}
|
|
9494
|
-
|
|
9495
|
-
edge.
|
|
9513
|
+
const n = Number(r.n) || 0;
|
|
9514
|
+
edge.weight += n;
|
|
9515
|
+
edge.types.set("import", (edge.types.get("import") ?? 0) + n);
|
|
9496
9516
|
}
|
|
9497
9517
|
const edges = [];
|
|
9498
9518
|
for (const [key, e] of edgeMap) {
|
|
@@ -9557,11 +9577,12 @@ var IndexStore = class _IndexStore {
|
|
|
9557
9577
|
}
|
|
9558
9578
|
const indexedFiles = new Set(allFiles.map((f) => f.file));
|
|
9559
9579
|
const refRows = this.stmt(
|
|
9560
|
-
`SELECT r.from_id, r.to_id, r.call_type
|
|
9580
|
+
`SELECT r.from_id, r.to_id, r.call_type, COUNT(*) AS n
|
|
9561
9581
|
FROM refs r
|
|
9562
9582
|
WHERE (r.from_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders}))
|
|
9563
9583
|
OR r.to_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders})))
|
|
9564
|
-
AND r.to_id IS NOT NULL
|
|
9584
|
+
AND r.to_id IS NOT NULL
|
|
9585
|
+
GROUP BY r.from_id, r.to_id, r.call_type`
|
|
9565
9586
|
).all(...pkgFilePaths, ...pkgFilePaths);
|
|
9566
9587
|
const knownSymIds = new Set(pkgSyms.map((s) => s.id));
|
|
9567
9588
|
const crossRefIds = /* @__PURE__ */ new Set();
|
|
@@ -9596,14 +9617,16 @@ var IndexStore = class _IndexStore {
|
|
|
9596
9617
|
e = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9597
9618
|
edgeMap.set(key, e);
|
|
9598
9619
|
}
|
|
9599
|
-
|
|
9600
|
-
e.
|
|
9620
|
+
const n = Number(r.n) || 0;
|
|
9621
|
+
e.weight += n;
|
|
9622
|
+
e.types.set(r.call_type, (e.types.get(r.call_type) ?? 0) + n);
|
|
9601
9623
|
}
|
|
9602
9624
|
const importRows = this.stmt(
|
|
9603
|
-
`SELECT r.from_id, r.to_name
|
|
9625
|
+
`SELECT r.from_id, r.to_name, COUNT(*) AS n
|
|
9604
9626
|
FROM refs r
|
|
9605
9627
|
WHERE r.call_type = 'import'
|
|
9606
|
-
AND r.from_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders}))
|
|
9628
|
+
AND r.from_id IN (SELECT id FROM symbols WHERE file IN (${filePlaceholders}))
|
|
9629
|
+
GROUP BY r.from_id, r.to_name`
|
|
9607
9630
|
).all(...pkgFilePaths);
|
|
9608
9631
|
for (const r of importRows) {
|
|
9609
9632
|
const fromFile = symToFile.get(r.from_id);
|
|
@@ -9618,8 +9641,9 @@ var IndexStore = class _IndexStore {
|
|
|
9618
9641
|
edge = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9619
9642
|
edgeMap.set(key, edge);
|
|
9620
9643
|
}
|
|
9621
|
-
|
|
9622
|
-
edge.
|
|
9644
|
+
const n = Number(r.n) || 0;
|
|
9645
|
+
edge.weight += n;
|
|
9646
|
+
edge.types.set("import", (edge.types.get("import") ?? 0) + n);
|
|
9623
9647
|
}
|
|
9624
9648
|
const edges = [];
|
|
9625
9649
|
for (const [key, e] of edgeMap) {
|
|
@@ -9666,22 +9690,25 @@ var IndexStore = class _IndexStore {
|
|
|
9666
9690
|
scope: s.scope,
|
|
9667
9691
|
external: s.file !== fileFilter
|
|
9668
9692
|
});
|
|
9669
|
-
const symIds = new Set(syms.map((s) => s.id));
|
|
9670
9693
|
const refRows = this.stmt(
|
|
9671
|
-
`SELECT
|
|
9672
|
-
FROM
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9694
|
+
`SELECT from_id, to_id, call_type, COUNT(*) AS n
|
|
9695
|
+
FROM (
|
|
9696
|
+
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
9697
|
+
FROM refs r
|
|
9698
|
+
JOIN symbols s ON s.id = r.from_id
|
|
9699
|
+
WHERE s.file = ?
|
|
9700
|
+
UNION
|
|
9701
|
+
SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
|
|
9702
|
+
FROM refs r
|
|
9703
|
+
JOIN symbols s ON s.id = r.to_id
|
|
9704
|
+
WHERE s.file = ?
|
|
9705
|
+
)
|
|
9706
|
+
WHERE to_id IS NOT NULL
|
|
9707
|
+
GROUP BY from_id, to_id, call_type`
|
|
9680
9708
|
).all(fileFilter, fileFilter);
|
|
9681
9709
|
const edgeMap = /* @__PURE__ */ new Map();
|
|
9682
9710
|
for (const r of refRows) {
|
|
9683
|
-
if (r.to_id
|
|
9684
|
-
if (!symIds.has(r.from_id) && !symIds.has(r.to_id)) continue;
|
|
9711
|
+
if (r.to_id == null) continue;
|
|
9685
9712
|
relatedIds.add(r.from_id);
|
|
9686
9713
|
relatedIds.add(r.to_id);
|
|
9687
9714
|
const key = `${r.from_id}\0${r.to_id}`;
|
|
@@ -9690,8 +9717,9 @@ var IndexStore = class _IndexStore {
|
|
|
9690
9717
|
e = { weight: 0, types: /* @__PURE__ */ new Map() };
|
|
9691
9718
|
edgeMap.set(key, e);
|
|
9692
9719
|
}
|
|
9693
|
-
|
|
9694
|
-
e.
|
|
9720
|
+
const n = Number(r.n) || 0;
|
|
9721
|
+
e.weight += n;
|
|
9722
|
+
e.types.set(r.call_type, (e.types.get(r.call_type) ?? 0) + n);
|
|
9695
9723
|
}
|
|
9696
9724
|
const edges = [];
|
|
9697
9725
|
for (const [key, e] of edgeMap) {
|
|
@@ -9748,7 +9776,7 @@ import { expectDefined as expectDefined6 } from "@wrongstack/core/utils";
|
|
|
9748
9776
|
import * as fs14 from "node:fs/promises";
|
|
9749
9777
|
import * as path20 from "node:path";
|
|
9750
9778
|
import { availableParallelism } from "node:os";
|
|
9751
|
-
import { indexParallelBatchSize, isFrugalPerf } from "@wrongstack/core/utils";
|
|
9779
|
+
import { DEFAULT_WALK_IGNORE_DIRS, indexParallelBatchSize, isFrugalPerf } from "@wrongstack/core/utils";
|
|
9752
9780
|
|
|
9753
9781
|
// src/codebase-index/ts-parser.ts
|
|
9754
9782
|
import * as ts from "@typescript/typescript6";
|
|
@@ -10406,7 +10434,7 @@ import * as path16 from "node:path";
|
|
|
10406
10434
|
var C_LIKE = [
|
|
10407
10435
|
{ re: /\b(?:class|struct|enum|interface|union)\s+([A-Za-z_]\w*)/g, kind: "class" },
|
|
10408
10436
|
{
|
|
10409
|
-
re: /\b(?:public|private|protected|static|final|async|override|virtual|inline|export)?\s*(?:[\w
|
|
10437
|
+
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,
|
|
10410
10438
|
kind: "function"
|
|
10411
10439
|
},
|
|
10412
10440
|
{ re: /\b(?:namespace)\s+([A-Za-z_]\w*)/g, kind: "namespace" }
|
|
@@ -10437,7 +10465,7 @@ var LANG_PATTERNS = {
|
|
|
10437
10465
|
java: [
|
|
10438
10466
|
{ re: /\b(?:class|interface|enum|record)\s+([A-Za-z_]\w*)/g, kind: "class" },
|
|
10439
10467
|
{
|
|
10440
|
-
re: /\b(?:public|private|protected|static|final|abstract|synchronized|native|default|\s)+\s*[\w
|
|
10468
|
+
re: /\b(?:public|private|protected|static|final|abstract|synchronized|native|default|\s)+\s*[\w.<>,[\]\s]+\s+([A-Za-z_]\w*)\s*\(/g,
|
|
10441
10469
|
kind: "method"
|
|
10442
10470
|
}
|
|
10443
10471
|
],
|
|
@@ -10445,7 +10473,7 @@ var LANG_PATTERNS = {
|
|
|
10445
10473
|
{ re: /\b(?:class|interface|struct|enum|record)\s+([A-Za-z_]\w*)/g, kind: "class" },
|
|
10446
10474
|
{ re: /\bnamespace\s+([A-Za-z_.\w]+)/g, kind: "namespace" },
|
|
10447
10475
|
{
|
|
10448
|
-
re: /\b(?:public|private|protected|internal|static|async|override|virtual|\s)+\s*[\w
|
|
10476
|
+
re: /\b(?:public|private|protected|internal|static|async|override|virtual|\s)+\s*[\w.<>,[\]\s]+\s+([A-Za-z_]\w*)\s*\(/g,
|
|
10449
10477
|
kind: "method"
|
|
10450
10478
|
}
|
|
10451
10479
|
],
|
|
@@ -10650,8 +10678,7 @@ function parseGeneric2(opts) {
|
|
|
10650
10678
|
for (const pattern of patterns) {
|
|
10651
10679
|
const re = new RegExp(pattern.re.source, pattern.re.flags.includes("g") ? pattern.re.flags : `${pattern.re.flags}g`);
|
|
10652
10680
|
re.lastIndex = 0;
|
|
10653
|
-
|
|
10654
|
-
while ((match = re.exec(content)) !== null) {
|
|
10681
|
+
for (const match of content.matchAll(re)) {
|
|
10655
10682
|
if (symbols.length >= maxSymbols) break;
|
|
10656
10683
|
let name = (match[1] ?? match[2] ?? "").trim();
|
|
10657
10684
|
if (lang === "md" && match[2]) name = match[2].trim();
|
|
@@ -11607,17 +11634,7 @@ function throwIfAborted(signal) {
|
|
|
11607
11634
|
function isAbortError(err) {
|
|
11608
11635
|
return err instanceof DOMException && err.name === "AbortError";
|
|
11609
11636
|
}
|
|
11610
|
-
var DEFAULT_IGNORE =
|
|
11611
|
-
"node_modules",
|
|
11612
|
-
".git",
|
|
11613
|
-
"dist",
|
|
11614
|
-
"build",
|
|
11615
|
-
".next",
|
|
11616
|
-
"coverage",
|
|
11617
|
-
".turbo",
|
|
11618
|
-
"__snapshots__",
|
|
11619
|
-
".nyc_output"
|
|
11620
|
-
];
|
|
11637
|
+
var DEFAULT_IGNORE = DEFAULT_WALK_IGNORE_DIRS;
|
|
11621
11638
|
var DEFAULT_IGNORE_FILES = /* @__PURE__ */ new Set(["package-lock.json", "pnpm-lock.yaml", "pnpm-lock.yml"]);
|
|
11622
11639
|
var MAX_INDEX_FILE_BYTES = 5 * 1024 * 1024;
|
|
11623
11640
|
function isWithinProject(projectRoot, file) {
|
|
@@ -16266,7 +16283,7 @@ function runGit2(args, cwd, signal) {
|
|
|
16266
16283
|
// src/glob.ts
|
|
16267
16284
|
import * as fs20 from "node:fs/promises";
|
|
16268
16285
|
import * as path26 from "node:path";
|
|
16269
|
-
import { compileGlob as compileGlob2 } from "@wrongstack/core/utils";
|
|
16286
|
+
import { compileGlob as compileGlob2, DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS2 } from "@wrongstack/core/utils";
|
|
16270
16287
|
|
|
16271
16288
|
// src/_concurrency.ts
|
|
16272
16289
|
async function mapWithConcurrency(items, limit, fn) {
|
|
@@ -16287,7 +16304,7 @@ async function mapWithConcurrency(items, limit, fn) {
|
|
|
16287
16304
|
|
|
16288
16305
|
// src/glob.ts
|
|
16289
16306
|
init_util();
|
|
16290
|
-
var DEFAULT_IGNORE2 =
|
|
16307
|
+
var DEFAULT_IGNORE2 = DEFAULT_WALK_IGNORE_DIRS2;
|
|
16291
16308
|
var WALK_CONCURRENCY = 16;
|
|
16292
16309
|
var globTool = {
|
|
16293
16310
|
name: "glob",
|
|
@@ -16327,7 +16344,7 @@ var globTool = {
|
|
|
16327
16344
|
const signal = opts?.signal;
|
|
16328
16345
|
const base = input.path ? await safeResolveReal(input.path, ctx) : ctx.cwd;
|
|
16329
16346
|
const limit = Math.max(1, Math.min(input.limit ?? 1e3, 5e3));
|
|
16330
|
-
const
|
|
16347
|
+
const isGitIgnored = await loadGitignoreMatcher(base);
|
|
16331
16348
|
const re = compileGlob2(input.pattern);
|
|
16332
16349
|
const results = [];
|
|
16333
16350
|
let truncated = false;
|
|
@@ -16367,12 +16384,13 @@ var globTool = {
|
|
|
16367
16384
|
for (const e of entries) {
|
|
16368
16385
|
const name = e.name;
|
|
16369
16386
|
if (DEFAULT_IGNORE2.includes(name)) continue;
|
|
16370
|
-
if (ignored.includes(name)) continue;
|
|
16371
16387
|
const rel = relPrefix ? `${relPrefix}/${name}` : name;
|
|
16372
16388
|
const full = path26.join(dir, name);
|
|
16373
16389
|
if (e.isDirectory()) {
|
|
16390
|
+
if (isGitIgnored(rel, true)) continue;
|
|
16374
16391
|
subdirs.push({ full, rel });
|
|
16375
16392
|
} else if (e.isFile()) {
|
|
16393
|
+
if (isGitIgnored(rel, false)) continue;
|
|
16376
16394
|
re.lastIndex = 0;
|
|
16377
16395
|
const relMatch = re.test(rel);
|
|
16378
16396
|
re.lastIndex = 0;
|
|
@@ -16384,10 +16402,12 @@ var globTool = {
|
|
|
16384
16402
|
try {
|
|
16385
16403
|
const st = await fs20.stat(full);
|
|
16386
16404
|
if (st.isDirectory()) {
|
|
16405
|
+
if (isGitIgnored(rel, true)) continue;
|
|
16387
16406
|
const real = await fs20.realpath(full);
|
|
16388
16407
|
await assertRealInsideRoot(real, ctx);
|
|
16389
16408
|
subdirs.push({ full, rel });
|
|
16390
16409
|
} else if (st.isFile()) {
|
|
16410
|
+
if (isGitIgnored(rel, false)) continue;
|
|
16391
16411
|
const real = await fs20.realpath(full);
|
|
16392
16412
|
await assertRealInsideRoot(real, ctx);
|
|
16393
16413
|
re.lastIndex = 0;
|
|
@@ -16411,14 +16431,6 @@ var globTool = {
|
|
|
16411
16431
|
return { files: results.map((r) => r.rel), truncated };
|
|
16412
16432
|
}
|
|
16413
16433
|
};
|
|
16414
|
-
async function readGitignore(dir) {
|
|
16415
|
-
try {
|
|
16416
|
-
const raw = await fs20.readFile(path26.join(dir, ".gitignore"), "utf8");
|
|
16417
|
-
return raw.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
16418
|
-
} catch {
|
|
16419
|
-
return [];
|
|
16420
|
-
}
|
|
16421
|
-
}
|
|
16422
16434
|
|
|
16423
16435
|
// src/grep.ts
|
|
16424
16436
|
import { expectDefined as expectDefined7 } from "@wrongstack/core/utils";
|
|
@@ -16426,7 +16438,7 @@ import { spawn as spawn10 } from "node:child_process";
|
|
|
16426
16438
|
import * as fs21 from "node:fs/promises";
|
|
16427
16439
|
import * as path27 from "node:path";
|
|
16428
16440
|
import { ToolValidationError as ToolValidationError4 } from "@wrongstack/core/types";
|
|
16429
|
-
import { buildChildEnv as buildChildEnv5, compileGlob as compileGlob3 } from "@wrongstack/core/utils";
|
|
16441
|
+
import { buildChildEnv as buildChildEnv5, compileGlob as compileGlob3, DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS3 } from "@wrongstack/core/utils";
|
|
16430
16442
|
|
|
16431
16443
|
// src/_regex.ts
|
|
16432
16444
|
var MAX_PATTERN_LEN = 256;
|
|
@@ -16475,7 +16487,7 @@ function capSubject(line) {
|
|
|
16475
16487
|
|
|
16476
16488
|
// src/grep.ts
|
|
16477
16489
|
init_util();
|
|
16478
|
-
var DEFAULT_IGNORE3 =
|
|
16490
|
+
var DEFAULT_IGNORE3 = DEFAULT_WALK_IGNORE_DIRS3;
|
|
16479
16491
|
var NATIVE_SCAN_CONCURRENCY = 32;
|
|
16480
16492
|
var NATIVE_READ_CHUNK_BYTES = 64 * 1024;
|
|
16481
16493
|
var NATIVE_MAX_FILE_BYTES = 1e6;
|
|
@@ -16592,6 +16604,10 @@ async function* runRgStream(input, base, mode, limit, signal) {
|
|
|
16592
16604
|
for (const ignored of DEFAULT_IGNORE3) {
|
|
16593
16605
|
args.push("--glob", `!${ignored}/**`, "--glob", `!**/${ignored}/**`);
|
|
16594
16606
|
}
|
|
16607
|
+
const gitignorePath = path27.join(base, ".gitignore");
|
|
16608
|
+
if (await fs21.access(gitignorePath).then(() => true, () => false)) {
|
|
16609
|
+
args.push("--ignore-file", gitignorePath);
|
|
16610
|
+
}
|
|
16595
16611
|
if (input.glob) args.push("--glob", input.glob);
|
|
16596
16612
|
args.push("--", input.pattern, base);
|
|
16597
16613
|
const matches = [];
|
|
@@ -16717,6 +16733,7 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
16717
16733
|
}
|
|
16718
16734
|
const re = compiled.regex;
|
|
16719
16735
|
const globRe = input.glob ? compileGlob3(input.glob) : null;
|
|
16736
|
+
const isGitIgnored = await loadGitignoreMatcher(base);
|
|
16720
16737
|
const matches = [];
|
|
16721
16738
|
const countOnlyFirstHit = mode === "count" && limit === 1;
|
|
16722
16739
|
const maxBytes = mode === "content" ? NATIVE_MAX_FILE_BYTES : Math.min(NATIVE_MAX_FILE_BYTES, 256 * 1024);
|
|
@@ -16804,7 +16821,7 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
16804
16821
|
} catch {
|
|
16805
16822
|
}
|
|
16806
16823
|
};
|
|
16807
|
-
const walk2 = async (dir) => {
|
|
16824
|
+
const walk2 = async (dir, relPrefix) => {
|
|
16808
16825
|
if (stopped || signal.aborted) return;
|
|
16809
16826
|
let entries;
|
|
16810
16827
|
try {
|
|
@@ -16818,17 +16835,24 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
16818
16835
|
if (stopped) return;
|
|
16819
16836
|
if (DEFAULT_IGNORE3.includes(e.name)) continue;
|
|
16820
16837
|
if (e.isSymbolicLink()) continue;
|
|
16838
|
+
const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
|
|
16821
16839
|
const full = path27.join(dir, e.name);
|
|
16822
16840
|
if (e.isDirectory()) {
|
|
16823
|
-
|
|
16841
|
+
if (isGitIgnored(rel, true)) continue;
|
|
16842
|
+
subdirs.push({ full, rel });
|
|
16824
16843
|
} else if (e.isFile()) {
|
|
16844
|
+
if (isGitIgnored(rel, false)) continue;
|
|
16825
16845
|
files.push({ full, name: e.name });
|
|
16826
16846
|
}
|
|
16827
16847
|
}
|
|
16828
16848
|
await mapWithConcurrency(files, NATIVE_SCAN_CONCURRENCY, ({ full, name }) => scanFile(full, name));
|
|
16829
|
-
await mapWithConcurrency(
|
|
16849
|
+
await mapWithConcurrency(
|
|
16850
|
+
subdirs,
|
|
16851
|
+
Math.min(16, NATIVE_SCAN_CONCURRENCY),
|
|
16852
|
+
({ full, rel }) => walk2(full, rel)
|
|
16853
|
+
);
|
|
16830
16854
|
};
|
|
16831
|
-
await walk2(base);
|
|
16855
|
+
await walk2(base, "");
|
|
16832
16856
|
return {
|
|
16833
16857
|
matches,
|
|
16834
16858
|
count: total,
|
|
@@ -17558,9 +17582,35 @@ import {
|
|
|
17558
17582
|
updateGoalMetricOnTask,
|
|
17559
17583
|
updateTask,
|
|
17560
17584
|
updateTaskAssignment,
|
|
17561
|
-
verifyTaskCompletion
|
|
17585
|
+
verifyTaskCompletion,
|
|
17586
|
+
finalizeTaskCompletion,
|
|
17587
|
+
assessTaskAtomicity,
|
|
17588
|
+
proposeTaskDecomposition
|
|
17562
17589
|
} from "@wrongstack/kanban";
|
|
17563
17590
|
|
|
17591
|
+
// src/kanban-evidence-bridge.ts
|
|
17592
|
+
import { recordCompletedWorkEvidence } from "@wrongstack/core/utils";
|
|
17593
|
+
function kanbanEvidenceKey(boardId, taskId) {
|
|
17594
|
+
return `kanban:${boardId}:${taskId}`;
|
|
17595
|
+
}
|
|
17596
|
+
function kanbanEvidencePointer(boardId, taskId) {
|
|
17597
|
+
return `kanban://${boardId}/${taskId}#verificationReport`;
|
|
17598
|
+
}
|
|
17599
|
+
function recordKanbanVerificationEvidence(ctx, report) {
|
|
17600
|
+
try {
|
|
17601
|
+
const passed = report.checks.filter((check) => check.status === "passed").length;
|
|
17602
|
+
const completedAt = Date.parse(report.completedAt);
|
|
17603
|
+
recordCompletedWorkEvidence(ctx, {
|
|
17604
|
+
key: kanbanEvidenceKey(report.boardId, report.taskId),
|
|
17605
|
+
source: "verification",
|
|
17606
|
+
summary: `${report.taskTitle} \u2014 verification ${report.verdict} (${passed}/${report.checks.length} checks)`,
|
|
17607
|
+
...Number.isFinite(completedAt) ? { completedAt } : {},
|
|
17608
|
+
evidence: kanbanEvidencePointer(report.boardId, report.taskId)
|
|
17609
|
+
});
|
|
17610
|
+
} catch {
|
|
17611
|
+
}
|
|
17612
|
+
}
|
|
17613
|
+
|
|
17564
17614
|
// src/session-kanban.ts
|
|
17565
17615
|
import { watch } from "node:fs";
|
|
17566
17616
|
import { basename as basename11, dirname as dirname13 } from "node:path";
|
|
@@ -18296,7 +18346,9 @@ var kanbanTool = {
|
|
|
18296
18346
|
"add_note",
|
|
18297
18347
|
"add_link",
|
|
18298
18348
|
"verify_completion",
|
|
18299
|
-
"split_atomic"
|
|
18349
|
+
"split_atomic",
|
|
18350
|
+
"assess_atomicity",
|
|
18351
|
+
"propose_decomposition"
|
|
18300
18352
|
]
|
|
18301
18353
|
},
|
|
18302
18354
|
boardId: { type: "string" },
|
|
@@ -18432,7 +18484,24 @@ var kanbanTool = {
|
|
|
18432
18484
|
includeCompletedTasks: { type: "boolean" },
|
|
18433
18485
|
preserveAssignment: { type: "boolean" },
|
|
18434
18486
|
preserveDependencies: { type: "boolean" },
|
|
18435
|
-
moveTasksToColumnId: { type: "string" }
|
|
18487
|
+
moveTasksToColumnId: { type: "string" },
|
|
18488
|
+
atomicityMode: { type: "string", enum: ["off", "assess", "enforce"] },
|
|
18489
|
+
atomicityDecomposition: { type: "string", enum: ["auto", "propose"] },
|
|
18490
|
+
gateEnforcement: { type: "string", enum: ["strict", "soft", "off"] },
|
|
18491
|
+
subtasks: {
|
|
18492
|
+
type: "array",
|
|
18493
|
+
minItems: 2,
|
|
18494
|
+
items: {
|
|
18495
|
+
type: "object",
|
|
18496
|
+
properties: {
|
|
18497
|
+
title: { type: "string" },
|
|
18498
|
+
description: { type: "string" },
|
|
18499
|
+
successCriteria: { type: "array", items: { type: "string" } },
|
|
18500
|
+
dependsOnIndex: { type: "array", items: { type: "number" } }
|
|
18501
|
+
},
|
|
18502
|
+
required: ["title"]
|
|
18503
|
+
}
|
|
18504
|
+
}
|
|
18436
18505
|
},
|
|
18437
18506
|
required: ["action"]
|
|
18438
18507
|
},
|
|
@@ -18472,7 +18541,14 @@ var kanbanTool = {
|
|
|
18472
18541
|
title: input.title,
|
|
18473
18542
|
...input.description !== void 0 ? { description: input.description } : {},
|
|
18474
18543
|
...input.tags !== void 0 ? { tags: input.tags } : {},
|
|
18475
|
-
...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {}
|
|
18544
|
+
...input.generatedBy !== void 0 ? { generatedBy: input.generatedBy } : {},
|
|
18545
|
+
...input.atomicityMode !== void 0 ? {
|
|
18546
|
+
atomicity: {
|
|
18547
|
+
mode: input.atomicityMode,
|
|
18548
|
+
decomposition: input.atomicityDecomposition ?? "propose"
|
|
18549
|
+
}
|
|
18550
|
+
} : {},
|
|
18551
|
+
...input.gateEnforcement !== void 0 ? { completionGate: { enforcement: input.gateEnforcement } } : {}
|
|
18476
18552
|
});
|
|
18477
18553
|
return { ok: true, message: `Board created: ${board.title}`, board };
|
|
18478
18554
|
}
|
|
@@ -18481,7 +18557,14 @@ var kanbanTool = {
|
|
|
18481
18557
|
const board = await updateBoard2(projectRoot, input.boardId, {
|
|
18482
18558
|
...input.title !== void 0 ? { title: input.title } : {},
|
|
18483
18559
|
...input.description !== void 0 ? { description: input.description } : {},
|
|
18484
|
-
...input.tags !== void 0 ? { tags: input.tags } : {}
|
|
18560
|
+
...input.tags !== void 0 ? { tags: input.tags } : {},
|
|
18561
|
+
...input.atomicityMode !== void 0 ? {
|
|
18562
|
+
atomicity: {
|
|
18563
|
+
mode: input.atomicityMode,
|
|
18564
|
+
decomposition: input.atomicityDecomposition ?? "propose"
|
|
18565
|
+
}
|
|
18566
|
+
} : {},
|
|
18567
|
+
...input.gateEnforcement !== void 0 ? { completionGate: { enforcement: input.gateEnforcement } } : {}
|
|
18485
18568
|
});
|
|
18486
18569
|
return board ? okBoard(board, "Board updated.") : fail("Board not found.");
|
|
18487
18570
|
}
|
|
@@ -18689,7 +18772,12 @@ var kanbanTool = {
|
|
|
18689
18772
|
case "add_task": {
|
|
18690
18773
|
if (!input.boardId || !input.title) return fail("add_task requires boardId and title.");
|
|
18691
18774
|
const result2 = await addTask(projectRoot, input.boardId, taskInput(input));
|
|
18692
|
-
|
|
18775
|
+
if (!result2) return fail("Board not found.");
|
|
18776
|
+
return okTask(
|
|
18777
|
+
result2.board,
|
|
18778
|
+
result2.task,
|
|
18779
|
+
`Task added.${atomicityNudge(result2.task)}`
|
|
18780
|
+
);
|
|
18693
18781
|
}
|
|
18694
18782
|
case "split_task": {
|
|
18695
18783
|
if (!input.boardId || !input.taskId || !input.childTitles?.length) {
|
|
@@ -18769,6 +18857,19 @@ var kanbanTool = {
|
|
|
18769
18857
|
"transition_task requires boardId, taskId, lifecycleStage, author, and transitionComment."
|
|
18770
18858
|
);
|
|
18771
18859
|
}
|
|
18860
|
+
if (input.lifecycleStage === "done") {
|
|
18861
|
+
const boardBefore = await getBoard2(projectRoot, input.boardId);
|
|
18862
|
+
const taskBefore = boardBefore ? await getTask(projectRoot, input.boardId, input.taskId) : null;
|
|
18863
|
+
if (boardBefore && taskBefore && !taskBefore.verificationReport && (taskBefore.atomic || Boolean(taskBefore.successCriteria?.length))) {
|
|
18864
|
+
const preGate = await verifyTaskCompletion(projectRoot, input.boardId, taskBefore.id, {
|
|
18865
|
+
persist: false
|
|
18866
|
+
});
|
|
18867
|
+
await updateTask(projectRoot, input.boardId, taskBefore.id, {
|
|
18868
|
+
verificationReport: preGate.report,
|
|
18869
|
+
successCriteria: preGate.task.successCriteria
|
|
18870
|
+
});
|
|
18871
|
+
}
|
|
18872
|
+
}
|
|
18772
18873
|
const result2 = await transitionTask(projectRoot, input.boardId, input.taskId, {
|
|
18773
18874
|
to: input.lifecycleStage,
|
|
18774
18875
|
actor: input.author,
|
|
@@ -18783,6 +18884,9 @@ var kanbanTool = {
|
|
|
18783
18884
|
} : {},
|
|
18784
18885
|
patch: taskPatch(input)
|
|
18785
18886
|
});
|
|
18887
|
+
if (result2 && input.lifecycleStage === "done" && result2.task.verificationReport) {
|
|
18888
|
+
recordKanbanVerificationEvidence(ctx, result2.task.verificationReport);
|
|
18889
|
+
}
|
|
18786
18890
|
return result2 ? okTask(result2.board, result2.task, `Task advanced to ${result2.transition.to}.`) : fail("Board or task not found.");
|
|
18787
18891
|
}
|
|
18788
18892
|
case "move_task": {
|
|
@@ -18896,7 +19000,31 @@ var kanbanTool = {
|
|
|
18896
19000
|
// is atomic inside updateTaskAssignment's mutateBoard lock.
|
|
18897
19001
|
input.expectedLeaseId !== void 0 ? { expectedLeaseId: input.expectedLeaseId } : {}
|
|
18898
19002
|
);
|
|
18899
|
-
|
|
19003
|
+
if (!board) return fail("Task not found.");
|
|
19004
|
+
if (assignmentStatus === "completed") {
|
|
19005
|
+
const envGate = readEnvGateEnforcement();
|
|
19006
|
+
const finalized = await finalizeTaskCompletion(projectRoot, board.id, input.taskId, {
|
|
19007
|
+
...board.completionGate === void 0 && envGate !== void 0 ? { enforcement: envGate } : {},
|
|
19008
|
+
...ctx.agentId !== void 0 ? { eventContext: { actor: ctx.agentId } } : {}
|
|
19009
|
+
});
|
|
19010
|
+
if (finalized) {
|
|
19011
|
+
if (finalized.gate.report) {
|
|
19012
|
+
recordKanbanVerificationEvidence(ctx, finalized.gate.report);
|
|
19013
|
+
}
|
|
19014
|
+
const gateSummary = {
|
|
19015
|
+
enforcement: finalized.gate.enforcement,
|
|
19016
|
+
allowed: finalized.gate.allowed,
|
|
19017
|
+
verdict: finalized.gate.verdict,
|
|
19018
|
+
issues: finalized.gate.issues.map((issue) => issue.message)
|
|
19019
|
+
};
|
|
19020
|
+
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(" | ")}`;
|
|
19021
|
+
return {
|
|
19022
|
+
...okTask(finalized.board, finalized.task, `Assignment updated. ${gateMessage}`),
|
|
19023
|
+
gate: gateSummary
|
|
19024
|
+
};
|
|
19025
|
+
}
|
|
19026
|
+
}
|
|
19027
|
+
return okBoard(board, "Assignment updated.");
|
|
18900
19028
|
}
|
|
18901
19029
|
case "heartbeat_assignment": {
|
|
18902
19030
|
if (!input.boardId || !input.taskId) {
|
|
@@ -19060,6 +19188,49 @@ var kanbanTool = {
|
|
|
19060
19188
|
});
|
|
19061
19189
|
return board ? okBoard(board, "Link added.") : fail("Task not found.");
|
|
19062
19190
|
}
|
|
19191
|
+
case "assess_atomicity": {
|
|
19192
|
+
if (!input.boardId || !input.taskId) {
|
|
19193
|
+
return fail("assess_atomicity requires boardId and taskId.");
|
|
19194
|
+
}
|
|
19195
|
+
const result2 = await assessTaskAtomicity(projectRoot, input.boardId, input.taskId, {
|
|
19196
|
+
assessedBy: "agent",
|
|
19197
|
+
...ctx.agentId !== void 0 ? { eventContext: { actor: ctx.agentId } } : {}
|
|
19198
|
+
});
|
|
19199
|
+
if (!result2) return fail("Task not found.");
|
|
19200
|
+
const failing = result2.assessment.criteria.filter((entry) => entry.score < 1).map((entry) => entry.reason);
|
|
19201
|
+
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." : "";
|
|
19202
|
+
return okTask(
|
|
19203
|
+
result2.board,
|
|
19204
|
+
result2.task,
|
|
19205
|
+
`Atomicity verdict: ${result2.assessment.verdict} (score ${result2.assessment.score}).${guidance}`
|
|
19206
|
+
);
|
|
19207
|
+
}
|
|
19208
|
+
case "propose_decomposition": {
|
|
19209
|
+
if (!input.boardId || !input.taskId || !input.subtasks?.length) {
|
|
19210
|
+
return fail("propose_decomposition requires boardId, taskId, and subtasks (2+).");
|
|
19211
|
+
}
|
|
19212
|
+
if (input.subtasks.length < 2) {
|
|
19213
|
+
return fail("propose_decomposition requires at least two subtasks.");
|
|
19214
|
+
}
|
|
19215
|
+
const invalid = input.subtasks.find(
|
|
19216
|
+
(subtask) => typeof subtask?.title !== "string" || !subtask.title.trim()
|
|
19217
|
+
);
|
|
19218
|
+
if (invalid) return fail("Every proposed subtask needs a non-blank title.");
|
|
19219
|
+
const result2 = await proposeTaskDecomposition(
|
|
19220
|
+
projectRoot,
|
|
19221
|
+
input.boardId,
|
|
19222
|
+
input.taskId,
|
|
19223
|
+
{
|
|
19224
|
+
subtasks: input.subtasks,
|
|
19225
|
+
...input.note !== void 0 ? { rationale: input.note } : {},
|
|
19226
|
+
...ctx.agentId !== void 0 ? { proposedBy: ctx.agentId } : {}
|
|
19227
|
+
},
|
|
19228
|
+
ctx.agentId !== void 0 ? { actor: ctx.agentId } : {}
|
|
19229
|
+
);
|
|
19230
|
+
if (!result2) return fail("Task not found.");
|
|
19231
|
+
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.';
|
|
19232
|
+
return okTask(result2.board, result2.task, message);
|
|
19233
|
+
}
|
|
19063
19234
|
case "verify_completion": {
|
|
19064
19235
|
if (!input.boardId || !input.taskId) {
|
|
19065
19236
|
return fail("verify_completion requires boardId and taskId.");
|
|
@@ -19077,6 +19248,7 @@ var kanbanTool = {
|
|
|
19077
19248
|
board: verResult.board
|
|
19078
19249
|
};
|
|
19079
19250
|
}
|
|
19251
|
+
recordKanbanVerificationEvidence(ctx, verResult.report);
|
|
19080
19252
|
const freshTask = persistedBoard.tasks?.find((t) => t.id === input.taskId);
|
|
19081
19253
|
const deterministicVerdicts = ["passed", "failed", "needs_human", "incomplete"];
|
|
19082
19254
|
return {
|
|
@@ -19103,6 +19275,15 @@ var kanbanTool = {
|
|
|
19103
19275
|
}
|
|
19104
19276
|
}
|
|
19105
19277
|
};
|
|
19278
|
+
function atomicityNudge(task) {
|
|
19279
|
+
if (task.atomicityAssessment?.verdict !== "needs_decomposition") return "";
|
|
19280
|
+
const reasons = task.atomicityAssessment.criteria.filter((entry) => entry.score < 1).map((entry) => entry.reason).join(" | ");
|
|
19281
|
+
return ` Atomicity: needs_decomposition (score ${task.atomicityAssessment.score}) \u2014 call propose_decomposition with 2+ subtasks before dispatch. Reasons: ${reasons}`;
|
|
19282
|
+
}
|
|
19283
|
+
function readEnvGateEnforcement() {
|
|
19284
|
+
const raw = process.env["WRONGSTACK_KANBAN_GATE"]?.trim().toLowerCase();
|
|
19285
|
+
return raw === "strict" || raw === "soft" || raw === "off" ? raw : void 0;
|
|
19286
|
+
}
|
|
19106
19287
|
function fail(message) {
|
|
19107
19288
|
return { ok: false, message };
|
|
19108
19289
|
}
|
|
@@ -22324,22 +22505,10 @@ var toolUseTool = {
|
|
|
22324
22505
|
|
|
22325
22506
|
// src/tree.ts
|
|
22326
22507
|
init_util();
|
|
22327
|
-
import { expectDefined as expectDefined10 } from "@wrongstack/core/utils";
|
|
22508
|
+
import { DEFAULT_WALK_IGNORE_DIRS as DEFAULT_WALK_IGNORE_DIRS4, expectDefined as expectDefined10 } from "@wrongstack/core/utils";
|
|
22328
22509
|
import * as fs28 from "node:fs/promises";
|
|
22329
22510
|
import * as path32 from "node:path";
|
|
22330
|
-
var DEFAULT_IGNORE5 = [
|
|
22331
|
-
"node_modules",
|
|
22332
|
-
".git",
|
|
22333
|
-
"dist",
|
|
22334
|
-
"build",
|
|
22335
|
-
".next",
|
|
22336
|
-
"coverage",
|
|
22337
|
-
"__pycache__",
|
|
22338
|
-
".wrongstack",
|
|
22339
|
-
".ssh",
|
|
22340
|
-
".gnupg",
|
|
22341
|
-
".aws"
|
|
22342
|
-
];
|
|
22511
|
+
var DEFAULT_IGNORE5 = [...DEFAULT_WALK_IGNORE_DIRS4, ".wrongstack", ".ssh", ".gnupg", ".aws"];
|
|
22343
22512
|
var treeTool = {
|
|
22344
22513
|
name: "tree",
|
|
22345
22514
|
category: "Filesystem",
|
|
@@ -24208,6 +24377,8 @@ export {
|
|
|
24208
24377
|
isIndexableFile,
|
|
24209
24378
|
isIndexing,
|
|
24210
24379
|
jsonTool,
|
|
24380
|
+
kanbanEvidenceKey,
|
|
24381
|
+
kanbanEvidencePointer,
|
|
24211
24382
|
kanbanTool,
|
|
24212
24383
|
languageInfoTool,
|
|
24213
24384
|
languagePackageTool,
|
|
@@ -24234,6 +24405,7 @@ export {
|
|
|
24234
24405
|
projectSessionTasksToKanban,
|
|
24235
24406
|
projectSessionTodosToKanban,
|
|
24236
24407
|
readTool,
|
|
24408
|
+
recordKanbanVerificationEvidence,
|
|
24237
24409
|
redactBrowserText,
|
|
24238
24410
|
registerBuiltinToolTier,
|
|
24239
24411
|
relatedMemoryTool,
|