pi-crew 0.9.64 → 0.9.66
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/CHANGELOG.md +31 -0
- package/README.md +46 -1
- package/dist/index.mjs +423 -330
- package/package.json +3 -2
- package/scripts/pty_probe.py +10 -8
- package/skills/real-test-pi-crew/SKILL.md +6 -6
- package/src/config/config.ts +19 -3
- package/src/config/types.ts +2 -0
- package/src/extension/team-tool/cancel.ts +34 -0
- package/src/extension/team-tool/dispatch/manage.ts +7 -4
- package/src/extension/team-tool/explain.ts +3 -1
- package/src/extension/team-tool/lifecycle-actions.ts +4 -1
- package/src/extension/team-tool-types.ts +2 -0
- package/src/observability/event-to-metric.ts +29 -0
- package/src/observability/metrics-primitives.ts +41 -3
- package/src/runtime/README.md +1 -1
- package/src/runtime/broker/crew-broker.ts +0 -16
- package/src/runtime/effectiveness.ts +23 -1
- package/src/runtime/merge-gate.ts +202 -0
- package/src/runtime/model/model-fallback.ts +11 -0
- package/src/runtime/model/provider-extensions.ts +31 -12
- package/src/runtime/output/output-validator.ts +34 -6
- package/src/runtime/output/progress-tracker.ts +3 -33
- package/src/runtime/scheduling/scheduler.ts +67 -19
- package/src/runtime/scratchpad/engine.ts +40 -2
- package/src/runtime/scratchpad/snapshot-hmac.ts +161 -0
- package/src/runtime/team-runner.ts +128 -203
- package/src/schema/team-tool-schema.ts +2 -0
- package/src/teams/discover-teams.ts +2 -0
- package/src/teams/team-config.ts +7 -0
- package/src/teams/team-serializer.ts +1 -0
- package/src/ui/mascot.ts +1 -14
- package/teams/default.team.md +1 -0
- package/teams/fast-fix.team.md +1 -0
- package/src/observability/event-bus.ts +0 -86
- package/src/plugins/plugin-define.ts +0 -6
- package/src/plugins/plugin-registry.ts +0 -32
- package/src/plugins/plugins/index.ts +0 -3
- package/src/plugins/plugins/nextjs.ts +0 -19
- package/src/plugins/plugins/vite.ts +0 -10
- package/src/plugins/plugins/vitest.ts +0 -9
- package/src/runtime/child-pi/child-pi-pool.ts +0 -68
- package/src/runtime/iteration-hooks.ts +0 -305
package/dist/index.mjs
CHANGED
|
@@ -10934,11 +10934,15 @@ function updateConfig(patch, options = {}) {
|
|
|
10934
10934
|
for (const unset of options.unsetPaths) unsetPath(raw, unset);
|
|
10935
10935
|
merged = parseConfig(raw);
|
|
10936
10936
|
}
|
|
10937
|
+
const normalizedCurrent = parseConfig(current);
|
|
10938
|
+
if (JSON.stringify(merged) === JSON.stringify(normalizedCurrent)) {
|
|
10939
|
+
return { path: filePath, config: merged, written: false };
|
|
10940
|
+
}
|
|
10937
10941
|
fs5.mkdirSync(path5.dirname(filePath), { recursive: true });
|
|
10938
10942
|
atomicWriteFile(filePath, `${JSON.stringify(merged, null, 2)}
|
|
10939
10943
|
`);
|
|
10940
10944
|
invalidateConfigCache();
|
|
10941
|
-
return { path: filePath, config: merged };
|
|
10945
|
+
return { path: filePath, config: merged, written: true };
|
|
10942
10946
|
});
|
|
10943
10947
|
}
|
|
10944
10948
|
function updateAutonomousConfig(patch) {
|
|
@@ -10953,11 +10957,15 @@ function updateAutonomousConfig(patch) {
|
|
|
10953
10957
|
throw new Error(`Could not update pi-crew config: ${message}`);
|
|
10954
10958
|
}
|
|
10955
10959
|
const currentAutonomous = current.autonomous && typeof current.autonomous === "object" && !Array.isArray(current.autonomous) ? current.autonomous : {};
|
|
10956
|
-
|
|
10960
|
+
const next = { ...current, autonomous: { ...currentAutonomous, ...patch } };
|
|
10961
|
+
if (JSON.stringify(next) === JSON.stringify(current)) {
|
|
10962
|
+
return { path: filePath, config: parseConfig(current), written: false };
|
|
10963
|
+
}
|
|
10964
|
+
current.autonomous = next.autonomous;
|
|
10957
10965
|
atomicWriteFile(filePath, `${JSON.stringify(current, null, 2)}
|
|
10958
10966
|
`);
|
|
10959
10967
|
invalidateConfigCache();
|
|
10960
|
-
return { path: filePath, config: parseConfig(current) };
|
|
10968
|
+
return { path: filePath, config: parseConfig(current), written: true };
|
|
10961
10969
|
});
|
|
10962
10970
|
}
|
|
10963
10971
|
var CONFIG_CACHE_TTL_MS, configCache, configCacheTtlMsOverride, KNOWN_TOP_LEVEL_KEYS, LIMIT_CEILINGS, DANGEROUS_OBJECT_KEYS;
|
|
@@ -11513,10 +11521,16 @@ function discoverProviderExtensions(settingsPath2) {
|
|
|
11513
11521
|
const npmBase = path9.join(baseDir, "npm", "node_modules");
|
|
11514
11522
|
for (const spec of settings.packages ?? []) {
|
|
11515
11523
|
if (typeof spec !== "string") continue;
|
|
11516
|
-
|
|
11517
|
-
|
|
11518
|
-
|
|
11524
|
+
let pkgDir;
|
|
11525
|
+
if (spec.startsWith("npm:")) {
|
|
11526
|
+
pkgDir = path9.join(npmBase, spec.slice(4));
|
|
11527
|
+
} else if (spec.startsWith("./") || spec.startsWith("../") || path9.isAbsolute(spec)) {
|
|
11528
|
+
pkgDir = path9.resolve(baseDir, spec);
|
|
11529
|
+
} else {
|
|
11530
|
+
continue;
|
|
11531
|
+
}
|
|
11519
11532
|
if (!fs9.existsSync(pkgDir)) continue;
|
|
11533
|
+
if (path9.resolve(pkgDir) === path9.resolve(packageRoot())) continue;
|
|
11520
11534
|
const entryPath = resolvePackageEntry(pkgDir);
|
|
11521
11535
|
if (entryPath) out.push({ spec, entryPath });
|
|
11522
11536
|
}
|
|
@@ -12442,6 +12456,8 @@ function parseTeamFile(filePath, source) {
|
|
|
12442
12456
|
defaultWorkflow: frontmatter.defaultWorkflow || frontmatter.workflow || void 0,
|
|
12443
12457
|
workspaceMode: frontmatter.workspaceMode?.trim() === "worktree" ? "worktree" : "single",
|
|
12444
12458
|
maxConcurrency: frontmatter.maxConcurrency ? Number.parseInt(frontmatter.maxConcurrency, 10) : void 0,
|
|
12459
|
+
// observability defaults ON ("luôn hoạt động"); explicit `observability: false` disables.
|
|
12460
|
+
observability: frontmatter.observability === void 0 ? true : frontmatter.observability !== "false",
|
|
12445
12461
|
routing: triggers || useWhen || avoidWhen || cost || category ? { triggers, useWhen, avoidWhen, cost, category } : void 0
|
|
12446
12462
|
};
|
|
12447
12463
|
} catch {
|
|
@@ -22404,7 +22420,18 @@ var init_model_fallback = __esm({
|
|
|
22404
22420
|
/context[_ ]?length[_ ]?exceeded/i,
|
|
22405
22421
|
/safety/i,
|
|
22406
22422
|
/is[_ ]?overloaded/i,
|
|
22407
|
-
/\b408\b
|
|
22423
|
+
/\b408\b/,
|
|
22424
|
+
//
|
|
22425
|
+
// EPIPE / broken-pipe. In the child-pi worker path this typically means
|
|
22426
|
+
// the child `pi` process exited (crash or early exit) while the parent
|
|
22427
|
+
// was still writing to its stdin — spawning a fresh child on the next
|
|
22428
|
+
// model in the fallback chain usually recovers. In the network path it
|
|
22429
|
+
// is a transient pipe close. Both are retryable on a different model.
|
|
22430
|
+
// See docs/failure-mode-inventory.md EPIPE gap; NON_RETRYABLE patterns
|
|
22431
|
+
// (auth/billing) are checked first, so an auth error mentioning EPIPE
|
|
22432
|
+
// stays non-retryable.
|
|
22433
|
+
/epipe/i,
|
|
22434
|
+
/broken pipe/i
|
|
22408
22435
|
];
|
|
22409
22436
|
NON_RETRYABLE_MODEL_FAILURE_PATTERNS = [
|
|
22410
22437
|
/auth(?:entication)?/i,
|
|
@@ -23842,10 +23869,12 @@ var init_team_tool_schema = __esm({
|
|
|
23842
23869
|
})
|
|
23843
23870
|
),
|
|
23844
23871
|
budgetTotal: Type.Optional(
|
|
23872
|
+
// Empty-string unset marker accepted (Tier-9: models emit "" when unset).
|
|
23845
23873
|
// 0 accepted as "unset/disabled" (models emit 0 for off); still rejects 1-999
|
|
23846
23874
|
// as the MISCONFIGURATION GUARD against typo'd silent-abort configs.
|
|
23847
23875
|
Type.Union(
|
|
23848
23876
|
[
|
|
23877
|
+
Type.Literal(""),
|
|
23849
23878
|
Type.Literal(0),
|
|
23850
23879
|
Type.Number({
|
|
23851
23880
|
minimum: 1e3
|
|
@@ -35626,23 +35655,46 @@ function parseIntervalMs(s) {
|
|
|
35626
35655
|
}
|
|
35627
35656
|
return ms;
|
|
35628
35657
|
}
|
|
35658
|
+
function cronFieldMatches(value, field, min, max, names) {
|
|
35659
|
+
let normalized = field.trim().toUpperCase();
|
|
35660
|
+
if (names) {
|
|
35661
|
+
for (const name of Object.keys(names).sort((a, b) => b.length - a.length)) {
|
|
35662
|
+
normalized = normalized.split(name).join(String(names[name]));
|
|
35663
|
+
}
|
|
35664
|
+
}
|
|
35665
|
+
if (min === 0 && max === 6) normalized = normalized.replace(/\b7\b/g, "0");
|
|
35666
|
+
const matched = /* @__PURE__ */ new Set();
|
|
35667
|
+
for (const rawPart of normalized.split(",")) {
|
|
35668
|
+
const part = rawPart.trim();
|
|
35669
|
+
if (part === "") return false;
|
|
35670
|
+
const stepMatch = part.match(/^(.*)\/(\d+)$/);
|
|
35671
|
+
const step = stepMatch ? Number.parseInt(stepMatch[2], 10) : 1;
|
|
35672
|
+
if (!Number.isFinite(step) || step < 1) return false;
|
|
35673
|
+
const rangeStr = stepMatch ? stepMatch[1] : part;
|
|
35674
|
+
let lo;
|
|
35675
|
+
let hi;
|
|
35676
|
+
if (rangeStr === "*") {
|
|
35677
|
+
lo = min;
|
|
35678
|
+
hi = max;
|
|
35679
|
+
} else if (/^\d+$/.test(rangeStr)) {
|
|
35680
|
+
lo = Number.parseInt(rangeStr, 10);
|
|
35681
|
+
hi = stepMatch ? max : lo;
|
|
35682
|
+
} else {
|
|
35683
|
+
const rm = rangeStr.match(/^(\d+)-(\d+)$/);
|
|
35684
|
+
if (!rm) return false;
|
|
35685
|
+
lo = Number.parseInt(rm[1], 10);
|
|
35686
|
+
hi = Number.parseInt(rm[2], 10);
|
|
35687
|
+
}
|
|
35688
|
+
for (let v = lo; v <= hi; v += step) {
|
|
35689
|
+
if (v >= min && v <= max) matched.add(v);
|
|
35690
|
+
}
|
|
35691
|
+
}
|
|
35692
|
+
return matched.has(value);
|
|
35693
|
+
}
|
|
35629
35694
|
function nextCronDate(spec, from) {
|
|
35630
35695
|
const parts = spec.split(/\s+/);
|
|
35631
35696
|
if (parts.length < 5) return { error: "Invalid cron expression" };
|
|
35632
35697
|
const [minStr, hourStr, domStr, monthStr, dowStr] = parts;
|
|
35633
|
-
function matchField(value, str, min, max) {
|
|
35634
|
-
if (str === "*") return true;
|
|
35635
|
-
const n = parseInt(str, 10);
|
|
35636
|
-
if (!Number.isNaN(n) && n >= min && n <= max && n === value) return true;
|
|
35637
|
-
if (/^\d+-\d+$/.test(str)) {
|
|
35638
|
-
const [a, b] = str.split("-").map(Number);
|
|
35639
|
-
return value >= a && value <= b;
|
|
35640
|
-
}
|
|
35641
|
-
if (str.includes(",")) {
|
|
35642
|
-
return str.split(",").some((part) => matchField(value, part.trim(), min, max));
|
|
35643
|
-
}
|
|
35644
|
-
return false;
|
|
35645
|
-
}
|
|
35646
35698
|
let cursor = new Date(from.getTime());
|
|
35647
35699
|
cursor.setSeconds(0, 0);
|
|
35648
35700
|
cursor = new Date(cursor.getTime() + 6e4);
|
|
@@ -35653,7 +35705,7 @@ function nextCronDate(spec, from) {
|
|
|
35653
35705
|
const dom = cursor.getUTCDate();
|
|
35654
35706
|
const month = cursor.getUTCMonth() + 1;
|
|
35655
35707
|
const dow = cursor.getUTCDay();
|
|
35656
|
-
if (
|
|
35708
|
+
if (cronFieldMatches(min, minStr, 0, 59) && cronFieldMatches(hour, hourStr, 0, 23) && cronFieldMatches(dom, domStr, 1, 31) && cronFieldMatches(month, monthStr, 1, 12, CRON_MONTH_NAMES) && cronFieldMatches(dow, dowStr, 0, 6, CRON_DOW_NAMES)) {
|
|
35657
35709
|
return cursor;
|
|
35658
35710
|
}
|
|
35659
35711
|
cursor = new Date(cursor.getTime() + 6e4);
|
|
@@ -35731,7 +35783,7 @@ function humanizeSchedule(spec) {
|
|
|
35731
35783
|
}
|
|
35732
35784
|
return "unknown schedule";
|
|
35733
35785
|
}
|
|
35734
|
-
var CrewScheduler;
|
|
35786
|
+
var CrewScheduler, CRON_DOW_NAMES, CRON_MONTH_NAMES;
|
|
35735
35787
|
var init_scheduler = __esm({
|
|
35736
35788
|
"src/runtime/scheduling/scheduler.ts"() {
|
|
35737
35789
|
"use strict";
|
|
@@ -35886,6 +35938,21 @@ var init_scheduler = __esm({
|
|
|
35886
35938
|
throw new Error(`Invalid schedule "${s}". Use "5m", "+10m", ISO timestamp, or cron expression.`);
|
|
35887
35939
|
}
|
|
35888
35940
|
};
|
|
35941
|
+
CRON_DOW_NAMES = { SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6 };
|
|
35942
|
+
CRON_MONTH_NAMES = {
|
|
35943
|
+
JAN: 1,
|
|
35944
|
+
FEB: 2,
|
|
35945
|
+
MAR: 3,
|
|
35946
|
+
APR: 4,
|
|
35947
|
+
MAY: 5,
|
|
35948
|
+
JUN: 6,
|
|
35949
|
+
JUL: 7,
|
|
35950
|
+
AUG: 8,
|
|
35951
|
+
SEP: 9,
|
|
35952
|
+
OCT: 10,
|
|
35953
|
+
NOV: 11,
|
|
35954
|
+
DEC: 12
|
|
35955
|
+
};
|
|
35889
35956
|
}
|
|
35890
35957
|
});
|
|
35891
35958
|
|
|
@@ -36511,8 +36578,13 @@ var cancel_exports = {};
|
|
|
36511
36578
|
__export(cancel_exports, {
|
|
36512
36579
|
abortOwned: () => abortOwned,
|
|
36513
36580
|
handleCancel: () => handleCancel,
|
|
36514
|
-
handleRetry: () => handleRetry
|
|
36581
|
+
handleRetry: () => handleRetry,
|
|
36582
|
+
retryShortCircuitsCompleted: () => retryShortCircuitsCompleted
|
|
36515
36583
|
});
|
|
36584
|
+
function retryShortCircuitsCompleted(runStatus, tasks, targetTaskId) {
|
|
36585
|
+
if (runStatus !== "completed") return false;
|
|
36586
|
+
return !tasks.some((task) => (targetTaskId ? task.id === targetTaskId : true) && RETRYABLE_STATUSES.has(task.status));
|
|
36587
|
+
}
|
|
36516
36588
|
function abortOwned(runId, taskIds, ctx, force) {
|
|
36517
36589
|
const runCwd = locateRunCwd(runId, ctx.cwd);
|
|
36518
36590
|
if (!runCwd) return { abortedIds: [], missingIds: taskIds ?? [], foreignIds: [] };
|
|
@@ -36585,6 +36657,13 @@ async function handleRetry(params, ctx, deps) {
|
|
|
36585
36657
|
);
|
|
36586
36658
|
}
|
|
36587
36659
|
const targetTaskId = typeof params.taskId === "string" ? params.taskId : void 0;
|
|
36660
|
+
if (retryShortCircuitsCompleted(loaded.manifest.status, loaded.tasks, targetTaskId)) {
|
|
36661
|
+
return result(
|
|
36662
|
+
`Run ${loaded.manifest.runId} is already completed; retry only applies to failed/cancelled runs.`,
|
|
36663
|
+
{ action: "retry", status: "error", runId: loaded.manifest.runId },
|
|
36664
|
+
true
|
|
36665
|
+
);
|
|
36666
|
+
}
|
|
36588
36667
|
return withRunLockSync(loaded.manifest, () => {
|
|
36589
36668
|
const retryableStatuses = /* @__PURE__ */ new Set(["failed", "cancelled"]);
|
|
36590
36669
|
const matchingTasks = loaded.tasks.filter((task) => {
|
|
@@ -36789,6 +36868,7 @@ async function handleCancel(params, ctx, deps) {
|
|
|
36789
36868
|
});
|
|
36790
36869
|
});
|
|
36791
36870
|
}
|
|
36871
|
+
var RETRYABLE_STATUSES;
|
|
36792
36872
|
var init_cancel = __esm({
|
|
36793
36873
|
"src/extension/team-tool/cancel.ts"() {
|
|
36794
36874
|
"use strict";
|
|
@@ -36808,6 +36888,7 @@ var init_cancel = __esm({
|
|
|
36808
36888
|
init_intent_policy();
|
|
36809
36889
|
init_param_error();
|
|
36810
36890
|
init_run_not_found();
|
|
36891
|
+
RETRYABLE_STATUSES = /* @__PURE__ */ new Set(["failed", "cancelled"]);
|
|
36811
36892
|
}
|
|
36812
36893
|
});
|
|
36813
36894
|
|
|
@@ -38785,7 +38866,9 @@ function handleWorktrees(params, ctx) {
|
|
|
38785
38866
|
{ action: "worktrees", status: "error" },
|
|
38786
38867
|
true
|
|
38787
38868
|
);
|
|
38788
|
-
const
|
|
38869
|
+
const runCwd = locateRunCwd(params.runId, ctx.cwd);
|
|
38870
|
+
if (!runCwd) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "worktrees", status: "error" }, true);
|
|
38871
|
+
const loaded = loadRunManifestById(runCwd, params.runId);
|
|
38789
38872
|
if (!loaded) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "worktrees", status: "error" }, true);
|
|
38790
38873
|
const withWorktrees = loaded.tasks.filter((task) => task.worktree);
|
|
38791
38874
|
const lines = [
|
|
@@ -39310,6 +39393,7 @@ var init_lifecycle_actions = __esm({
|
|
|
39310
39393
|
init_run_export();
|
|
39311
39394
|
init_run_import();
|
|
39312
39395
|
init_run_maintenance();
|
|
39396
|
+
init_team_tool2();
|
|
39313
39397
|
init_context();
|
|
39314
39398
|
init_intent_policy();
|
|
39315
39399
|
init_param_error();
|
|
@@ -39565,6 +39649,7 @@ function serializeTeam(team) {
|
|
|
39565
39649
|
team.defaultWorkflow ? `defaultWorkflow: ${team.defaultWorkflow}` : void 0,
|
|
39566
39650
|
team.workspaceMode ? `workspaceMode: ${team.workspaceMode}` : void 0,
|
|
39567
39651
|
team.maxConcurrency !== void 0 ? `maxConcurrency: ${team.maxConcurrency}` : void 0,
|
|
39652
|
+
team.observability !== void 0 ? `observability: ${team.observability}` : void 0,
|
|
39568
39653
|
line2("triggers", team.routing?.triggers),
|
|
39569
39654
|
line2("useWhen", team.routing?.useWhen),
|
|
39570
39655
|
line2("avoidWhen", team.routing?.avoidWhen),
|
|
@@ -41145,10 +41230,13 @@ async function handleManageDomain(params, ctx) {
|
|
|
41145
41230
|
unsetPaths
|
|
41146
41231
|
});
|
|
41147
41232
|
return result(
|
|
41148
|
-
[
|
|
41149
|
-
"
|
|
41150
|
-
|
|
41151
|
-
|
|
41233
|
+
[
|
|
41234
|
+
saved.written ? "Updated pi-crew config." : "Config unchanged (no effective changes).",
|
|
41235
|
+
`Path: ${saved.path}`,
|
|
41236
|
+
"Effective config:",
|
|
41237
|
+
JSON.stringify(saved.config, null, 2)
|
|
41238
|
+
].join("\n"),
|
|
41239
|
+
{ action: "config", status: "ok", written: saved.written }
|
|
41152
41240
|
);
|
|
41153
41241
|
} catch (error) {
|
|
41154
41242
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -47774,7 +47862,8 @@ function handleExplain(params, cwd) {
|
|
|
47774
47862
|
if (!params.runId) {
|
|
47775
47863
|
return result3("explain requires runId", { action: "explain", status: "error" }, true);
|
|
47776
47864
|
}
|
|
47777
|
-
const
|
|
47865
|
+
const runCwd = locateRunCwd(params.runId, cwd);
|
|
47866
|
+
const loaded = runCwd ? loadRunManifestById(runCwd, params.runId) : void 0;
|
|
47778
47867
|
if (!loaded) {
|
|
47779
47868
|
return result3(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "explain", status: "error" }, true);
|
|
47780
47869
|
}
|
|
@@ -47833,6 +47922,7 @@ var init_explain = __esm({
|
|
|
47833
47922
|
"src/extension/team-tool/explain.ts"() {
|
|
47834
47923
|
"use strict";
|
|
47835
47924
|
init_state_store();
|
|
47925
|
+
init_team_tool2();
|
|
47836
47926
|
init_run_not_found();
|
|
47837
47927
|
}
|
|
47838
47928
|
});
|
|
@@ -48455,6 +48545,9 @@ function taskHasObservableWorkerActivity(task) {
|
|
|
48455
48545
|
(task.agentProgress?.toolCount ?? 0) > 0 || task.usage || task.transcriptArtifact || task.modelAttempts?.some((attempt) => attempt.success) || task.jsonEvents
|
|
48456
48546
|
);
|
|
48457
48547
|
}
|
|
48548
|
+
function taskHasEmptyResult(task) {
|
|
48549
|
+
return Boolean(task.resultArtifact && task.resultArtifact.sizeBytes === 0);
|
|
48550
|
+
}
|
|
48458
48551
|
function resolveEffectivenessGuardMode(runtimeConfig, manifest) {
|
|
48459
48552
|
const configured = runtimeConfig?.effectivenessGuard;
|
|
48460
48553
|
if (configured === "off" || configured === "warn" || configured === "block" || configured === "fail") return configured;
|
|
@@ -48463,7 +48556,7 @@ function resolveEffectivenessGuardMode(runtimeConfig, manifest) {
|
|
|
48463
48556
|
}
|
|
48464
48557
|
function evaluateRunEffectiveness(input) {
|
|
48465
48558
|
const completedTasks = input.tasks.filter((task) => task.status === "completed");
|
|
48466
|
-
const noObservedWorkTasks = completedTasks.filter((task) => !taskHasObservableWorkerActivity(task));
|
|
48559
|
+
const noObservedWorkTasks = completedTasks.filter((task) => !taskHasObservableWorkerActivity(task) || taskHasEmptyResult(task));
|
|
48467
48560
|
const needsAttentionTasks = input.tasks.filter((task) => task.agentProgress?.activityState === "needs_attention");
|
|
48468
48561
|
const workerExecution = input.executeWorkers ? "enabled" : "disabled/scaffold";
|
|
48469
48562
|
const guardMode = resolveEffectivenessGuardMode(input.runtimeConfig, input.manifest);
|
|
@@ -49325,112 +49418,6 @@ var init_correlation = __esm({
|
|
|
49325
49418
|
}
|
|
49326
49419
|
});
|
|
49327
49420
|
|
|
49328
|
-
// src/plugins/plugin-registry.ts
|
|
49329
|
-
var PluginRegistry;
|
|
49330
|
-
var init_plugin_registry = __esm({
|
|
49331
|
-
"src/plugins/plugin-registry.ts"() {
|
|
49332
|
-
"use strict";
|
|
49333
|
-
PluginRegistry = class {
|
|
49334
|
-
plugins = [];
|
|
49335
|
-
register(plugin) {
|
|
49336
|
-
this.plugins.push(plugin);
|
|
49337
|
-
}
|
|
49338
|
-
activePlugins(allDeps) {
|
|
49339
|
-
return this.plugins.filter(
|
|
49340
|
-
(p) => p.enablers.some((enabler) => {
|
|
49341
|
-
if (enabler.endsWith("/")) {
|
|
49342
|
-
return allDeps.some((d) => d.startsWith(enabler));
|
|
49343
|
-
}
|
|
49344
|
-
return allDeps.includes(enabler);
|
|
49345
|
-
})
|
|
49346
|
-
);
|
|
49347
|
-
}
|
|
49348
|
-
allPlugins() {
|
|
49349
|
-
return [...this.plugins];
|
|
49350
|
-
}
|
|
49351
|
-
};
|
|
49352
|
-
}
|
|
49353
|
-
});
|
|
49354
|
-
|
|
49355
|
-
// src/plugins/plugin-define.ts
|
|
49356
|
-
function definePlugin(spec) {
|
|
49357
|
-
return spec;
|
|
49358
|
-
}
|
|
49359
|
-
var init_plugin_define = __esm({
|
|
49360
|
-
"src/plugins/plugin-define.ts"() {
|
|
49361
|
-
"use strict";
|
|
49362
|
-
}
|
|
49363
|
-
});
|
|
49364
|
-
|
|
49365
|
-
// src/plugins/plugins/nextjs.ts
|
|
49366
|
-
var NextJsPlugin;
|
|
49367
|
-
var init_nextjs = __esm({
|
|
49368
|
-
"src/plugins/plugins/nextjs.ts"() {
|
|
49369
|
-
"use strict";
|
|
49370
|
-
init_plugin_define();
|
|
49371
|
-
NextJsPlugin = definePlugin({
|
|
49372
|
-
name: "nextjs",
|
|
49373
|
-
enablers: ["next"],
|
|
49374
|
-
entryPatterns: [
|
|
49375
|
-
"src/app/**/*.{ts,tsx}",
|
|
49376
|
-
"src/pages/**/*.{ts,tsx}",
|
|
49377
|
-
"src/app/**/page.{ts,tsx}",
|
|
49378
|
-
"src/app/**/layout.{ts,tsx}",
|
|
49379
|
-
"src/app/**/route.{ts,tsx}",
|
|
49380
|
-
"middleware.{ts,js}",
|
|
49381
|
-
"next.config.{ts,js,mjs}"
|
|
49382
|
-
],
|
|
49383
|
-
configPatterns: ["next.config.{ts,js,mjs}"],
|
|
49384
|
-
toolingDependencies: ["next", "@next/font", "@next/mdx"],
|
|
49385
|
-
pathAliases: [["~", "src"]],
|
|
49386
|
-
virtualModulePrefixes: ["next:"]
|
|
49387
|
-
});
|
|
49388
|
-
}
|
|
49389
|
-
});
|
|
49390
|
-
|
|
49391
|
-
// src/plugins/plugins/vite.ts
|
|
49392
|
-
var VitePlugin;
|
|
49393
|
-
var init_vite = __esm({
|
|
49394
|
-
"src/plugins/plugins/vite.ts"() {
|
|
49395
|
-
"use strict";
|
|
49396
|
-
init_plugin_define();
|
|
49397
|
-
VitePlugin = definePlugin({
|
|
49398
|
-
name: "vite",
|
|
49399
|
-
enablers: ["vite", "rolldown-vite"],
|
|
49400
|
-
entryPatterns: ["src/main.{ts,tsx,js,jsx}", "src/index.{ts,tsx,js,jsx}", "index.html"],
|
|
49401
|
-
configPatterns: ["vite.config.{ts,js,mts,mjs}"],
|
|
49402
|
-
toolingDependencies: ["vite"],
|
|
49403
|
-
virtualModulePrefixes: ["virtual:"]
|
|
49404
|
-
});
|
|
49405
|
-
}
|
|
49406
|
-
});
|
|
49407
|
-
|
|
49408
|
-
// src/plugins/plugins/vitest.ts
|
|
49409
|
-
var VitestPlugin;
|
|
49410
|
-
var init_vitest = __esm({
|
|
49411
|
-
"src/plugins/plugins/vitest.ts"() {
|
|
49412
|
-
"use strict";
|
|
49413
|
-
init_plugin_define();
|
|
49414
|
-
VitestPlugin = definePlugin({
|
|
49415
|
-
name: "vitest",
|
|
49416
|
-
enablers: ["vitest"],
|
|
49417
|
-
entryPatterns: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}", "src/**/*.test.{ts,tsx}", "src/**/*.spec.{ts,tsx}"],
|
|
49418
|
-
configPatterns: ["vitest.config.{ts,js,mjs}", "vite.config.ts"],
|
|
49419
|
-
toolingDependencies: ["vitest"]
|
|
49420
|
-
});
|
|
49421
|
-
}
|
|
49422
|
-
});
|
|
49423
|
-
|
|
49424
|
-
// src/plugins/plugins/index.ts
|
|
49425
|
-
var init_plugins = __esm({
|
|
49426
|
-
"src/plugins/plugins/index.ts"() {
|
|
49427
|
-
"use strict";
|
|
49428
|
-
init_nextjs();
|
|
49429
|
-
init_vite();
|
|
49430
|
-
init_vitest();
|
|
49431
|
-
}
|
|
49432
|
-
});
|
|
49433
|
-
|
|
49434
49421
|
// src/runtime/task-health.ts
|
|
49435
49422
|
function scoreToGrade(score) {
|
|
49436
49423
|
if (score >= 90) return "A";
|
|
@@ -50470,6 +50457,166 @@ var init_group_join = __esm({
|
|
|
50470
50457
|
}
|
|
50471
50458
|
});
|
|
50472
50459
|
|
|
50460
|
+
// src/runtime/scheduling/task-graph-scheduler.ts
|
|
50461
|
+
function buildTaskGraphIndex(tasks) {
|
|
50462
|
+
const cached2 = taskGraphIndexCache.get(tasks);
|
|
50463
|
+
if (cached2) return cached2;
|
|
50464
|
+
const fresh = {
|
|
50465
|
+
doneSteps: new Set(
|
|
50466
|
+
tasks.filter((task) => task.status === "completed").map((task) => task.stepId).filter((id) => id !== void 0)
|
|
50467
|
+
),
|
|
50468
|
+
idMap: new Map(tasks.map((task) => [task.id, task])),
|
|
50469
|
+
stepToTaskId: new Map(
|
|
50470
|
+
tasks.map((task) => [task.stepId, task.id]).filter((entry) => entry[0] !== void 0)
|
|
50471
|
+
)
|
|
50472
|
+
};
|
|
50473
|
+
taskGraphIndexCache.set(tasks, fresh);
|
|
50474
|
+
return fresh;
|
|
50475
|
+
}
|
|
50476
|
+
function dependencySatisfied(task, doneStepIds, idMap, stepMap) {
|
|
50477
|
+
return task.dependsOn.every((dependency) => {
|
|
50478
|
+
if (doneStepIds.has(dependency)) return true;
|
|
50479
|
+
const taskId = stepMap.get(dependency) ?? dependency;
|
|
50480
|
+
return idMap.get(taskId)?.status === "completed";
|
|
50481
|
+
});
|
|
50482
|
+
}
|
|
50483
|
+
function withQueue(task, index) {
|
|
50484
|
+
let resolvedQueue;
|
|
50485
|
+
if (task.status === "queued") {
|
|
50486
|
+
const isReady = dependencySatisfied(task, index.doneSteps, index.idMap, index.stepToTaskId);
|
|
50487
|
+
resolvedQueue = isReady ? "ready" : "blocked";
|
|
50488
|
+
} else if (task.status === "running") {
|
|
50489
|
+
resolvedQueue = "running";
|
|
50490
|
+
} else if (task.status === "completed" || task.status === "skipped" || task.status === "needs_attention") {
|
|
50491
|
+
resolvedQueue = "done";
|
|
50492
|
+
} else {
|
|
50493
|
+
resolvedQueue = "blocked";
|
|
50494
|
+
}
|
|
50495
|
+
if (task.graph && task.graph.queue === resolvedQueue) {
|
|
50496
|
+
return task;
|
|
50497
|
+
}
|
|
50498
|
+
return {
|
|
50499
|
+
...task,
|
|
50500
|
+
graph: task.graph ? { ...task.graph, queue: resolvedQueue } : task.graph
|
|
50501
|
+
};
|
|
50502
|
+
}
|
|
50503
|
+
function ensureIndex(tasks, index) {
|
|
50504
|
+
return index ?? buildTaskGraphIndex(tasks);
|
|
50505
|
+
}
|
|
50506
|
+
function refreshTaskGraphQueues(tasks, index) {
|
|
50507
|
+
const resolved = ensureIndex(tasks, index);
|
|
50508
|
+
return tasks.map((task) => withQueue(task, resolved));
|
|
50509
|
+
}
|
|
50510
|
+
function taskGraphSnapshot(tasks, index) {
|
|
50511
|
+
const refreshed = refreshTaskGraphQueues(tasks, index);
|
|
50512
|
+
return {
|
|
50513
|
+
ready: refreshed.filter((task) => task.status === "queued" && task.graph?.queue === "ready").map((task) => task.id),
|
|
50514
|
+
blocked: refreshed.filter((task) => task.status === "queued" && task.graph?.queue === "blocked").map((task) => task.id),
|
|
50515
|
+
running: refreshed.filter((task) => task.status === "running").map((task) => task.id),
|
|
50516
|
+
done: refreshed.filter((task) => task.status === "completed" || task.status === "skipped").map((task) => task.id),
|
|
50517
|
+
failed: refreshed.filter((task) => task.status === "failed").map((task) => task.id),
|
|
50518
|
+
cancelled: refreshed.filter((task) => task.status === "cancelled").map((task) => task.id)
|
|
50519
|
+
};
|
|
50520
|
+
}
|
|
50521
|
+
var taskGraphIndexCache;
|
|
50522
|
+
var init_task_graph_scheduler = __esm({
|
|
50523
|
+
"src/runtime/scheduling/task-graph-scheduler.ts"() {
|
|
50524
|
+
"use strict";
|
|
50525
|
+
taskGraphIndexCache = /* @__PURE__ */ new WeakMap();
|
|
50526
|
+
}
|
|
50527
|
+
});
|
|
50528
|
+
|
|
50529
|
+
// src/runtime/merge-gate.ts
|
|
50530
|
+
function isNonTerminalTaskStatus(status) {
|
|
50531
|
+
return status === "queued" || status === "running" || status === "waiting";
|
|
50532
|
+
}
|
|
50533
|
+
function safeFinishedAt(task) {
|
|
50534
|
+
if (!task.finishedAt) return -Infinity;
|
|
50535
|
+
const ms = new Date(task.finishedAt).getTime();
|
|
50536
|
+
return Number.isNaN(ms) ? Infinity : ms;
|
|
50537
|
+
}
|
|
50538
|
+
function isMalformedFinishedAtReplacement(currentTime, updatedTime) {
|
|
50539
|
+
return !Number.isFinite(currentTime) && Number.isFinite(updatedTime);
|
|
50540
|
+
}
|
|
50541
|
+
function statusMergeKey(from, to) {
|
|
50542
|
+
return `${from}->${to}`;
|
|
50543
|
+
}
|
|
50544
|
+
function shouldMergeTaskUpdate(current, updated) {
|
|
50545
|
+
if (REJECTED_STATUS_MERGE_TRANSITIONS.has(statusMergeKey(current.status, updated.status))) return false;
|
|
50546
|
+
if (current.status === updated.status && updated.status === "running" && current.resultArtifact && !updated.resultArtifact)
|
|
50547
|
+
return false;
|
|
50548
|
+
if (current.status === updated.status && current.status === "completed" && current.resultArtifact && !updated.resultArtifact)
|
|
50549
|
+
return false;
|
|
50550
|
+
if (current.finishedAt !== void 0 && updated.finishedAt !== void 0) {
|
|
50551
|
+
const currentTime = safeFinishedAt(current);
|
|
50552
|
+
const updatedTime = safeFinishedAt(updated);
|
|
50553
|
+
if (!Number.isFinite(currentTime)) {
|
|
50554
|
+
console.warn(`[merge-gate] Task ${current.id} has malformed finishedAt: ${current.finishedAt}`);
|
|
50555
|
+
}
|
|
50556
|
+
if (isMalformedFinishedAtReplacement(currentTime, updatedTime)) {
|
|
50557
|
+
return true;
|
|
50558
|
+
}
|
|
50559
|
+
if (updatedTime < currentTime) return false;
|
|
50560
|
+
}
|
|
50561
|
+
if (!updated.finishedAt && !isNonTerminalTaskStatus(updated.status)) return false;
|
|
50562
|
+
const hasMeaningfulUpdate = updated.status !== current.status || updated.finishedAt !== current.finishedAt || updated.startedAt !== current.startedAt || Boolean(updated.resultArtifact) !== Boolean(current.resultArtifact) || Boolean(updated.resultArtifact) && updated.resultArtifact !== current.resultArtifact || Boolean(updated.error) || Boolean(updated.modelAttempts?.length) || Boolean(updated.usage) || Boolean(updated.attempts?.length) || updated.heartbeat?.lastSeenAt !== current.heartbeat?.lastSeenAt || updated.jsonEvents !== current.jsonEvents || updated.agentProgress?.lastActivityAt !== current.agentProgress?.lastActivityAt;
|
|
50563
|
+
return hasMeaningfulUpdate;
|
|
50564
|
+
}
|
|
50565
|
+
function mergeTaskUpdatesPreservingTerminal(base, results) {
|
|
50566
|
+
const indexById = /* @__PURE__ */ new Map();
|
|
50567
|
+
for (const task of base) indexById.set(task.id, task);
|
|
50568
|
+
let skipped = 0;
|
|
50569
|
+
for (const result4 of results) {
|
|
50570
|
+
for (const updated of result4.tasks) {
|
|
50571
|
+
const current = indexById.get(updated.id);
|
|
50572
|
+
if (!current) continue;
|
|
50573
|
+
if (!shouldMergeTaskUpdate(current, updated)) {
|
|
50574
|
+
console.debug("[merge-gate] Skipping stale merge for task", updated.id, {
|
|
50575
|
+
currentStatus: current.status,
|
|
50576
|
+
updatedStatus: updated.status,
|
|
50577
|
+
currentFinishedAt: current.finishedAt,
|
|
50578
|
+
updatedFinishedAt: updated.finishedAt
|
|
50579
|
+
});
|
|
50580
|
+
skipped += 1;
|
|
50581
|
+
continue;
|
|
50582
|
+
}
|
|
50583
|
+
indexById.set(updated.id, updated);
|
|
50584
|
+
}
|
|
50585
|
+
}
|
|
50586
|
+
const merged = base.map((task) => indexById.get(task.id) ?? task);
|
|
50587
|
+
void skipped;
|
|
50588
|
+
return refreshTaskGraphQueues(merged);
|
|
50589
|
+
}
|
|
50590
|
+
var REJECTED_STATUS_MERGE_TRANSITIONS, __test__shouldMergeTaskUpdate, __test__mergeTaskUpdates;
|
|
50591
|
+
var init_merge_gate = __esm({
|
|
50592
|
+
"src/runtime/merge-gate.ts"() {
|
|
50593
|
+
"use strict";
|
|
50594
|
+
init_contracts();
|
|
50595
|
+
init_task_graph_scheduler();
|
|
50596
|
+
REJECTED_STATUS_MERGE_TRANSITIONS = (() => {
|
|
50597
|
+
const rejected = /* @__PURE__ */ new Set();
|
|
50598
|
+
for (const from of TEAM_TASK_STATUSES) {
|
|
50599
|
+
if (!TEAM_TERMINAL_TASK_STATUSES.has(from)) continue;
|
|
50600
|
+
for (const to of TEAM_TASK_STATUSES) {
|
|
50601
|
+
if (!TEAM_TERMINAL_TASK_STATUSES.has(to)) rejected.add(statusMergeKey(from, to));
|
|
50602
|
+
}
|
|
50603
|
+
}
|
|
50604
|
+
rejected.add(statusMergeKey("waiting", "running"));
|
|
50605
|
+
const completedIntegrityFlips = [
|
|
50606
|
+
["completed", "failed"],
|
|
50607
|
+
["completed", "needs_attention"],
|
|
50608
|
+
["failed", "completed"],
|
|
50609
|
+
["cancelled", "completed"],
|
|
50610
|
+
["needs_attention", "completed"]
|
|
50611
|
+
];
|
|
50612
|
+
for (const [from, to] of completedIntegrityFlips) rejected.add(statusMergeKey(from, to));
|
|
50613
|
+
return rejected;
|
|
50614
|
+
})();
|
|
50615
|
+
__test__shouldMergeTaskUpdate = shouldMergeTaskUpdate;
|
|
50616
|
+
__test__mergeTaskUpdates = mergeTaskUpdatesPreservingTerminal;
|
|
50617
|
+
}
|
|
50618
|
+
});
|
|
50619
|
+
|
|
50473
50620
|
// src/runtime/model/runtime-policy.ts
|
|
50474
50621
|
function resolveTaskRuntimeKind(globalKind, role, isolationPolicy, env = process.env) {
|
|
50475
50622
|
if (globalKind === "scaffold") return "scaffold";
|
|
@@ -51822,75 +51969,6 @@ var init_task_graph = __esm({
|
|
|
51822
51969
|
}
|
|
51823
51970
|
});
|
|
51824
51971
|
|
|
51825
|
-
// src/runtime/scheduling/task-graph-scheduler.ts
|
|
51826
|
-
function buildTaskGraphIndex(tasks) {
|
|
51827
|
-
const cached2 = taskGraphIndexCache.get(tasks);
|
|
51828
|
-
if (cached2) return cached2;
|
|
51829
|
-
const fresh = {
|
|
51830
|
-
doneSteps: new Set(
|
|
51831
|
-
tasks.filter((task) => task.status === "completed").map((task) => task.stepId).filter((id) => id !== void 0)
|
|
51832
|
-
),
|
|
51833
|
-
idMap: new Map(tasks.map((task) => [task.id, task])),
|
|
51834
|
-
stepToTaskId: new Map(
|
|
51835
|
-
tasks.map((task) => [task.stepId, task.id]).filter((entry) => entry[0] !== void 0)
|
|
51836
|
-
)
|
|
51837
|
-
};
|
|
51838
|
-
taskGraphIndexCache.set(tasks, fresh);
|
|
51839
|
-
return fresh;
|
|
51840
|
-
}
|
|
51841
|
-
function dependencySatisfied(task, doneStepIds, idMap, stepMap) {
|
|
51842
|
-
return task.dependsOn.every((dependency) => {
|
|
51843
|
-
if (doneStepIds.has(dependency)) return true;
|
|
51844
|
-
const taskId = stepMap.get(dependency) ?? dependency;
|
|
51845
|
-
return idMap.get(taskId)?.status === "completed";
|
|
51846
|
-
});
|
|
51847
|
-
}
|
|
51848
|
-
function withQueue(task, index) {
|
|
51849
|
-
let resolvedQueue;
|
|
51850
|
-
if (task.status === "queued") {
|
|
51851
|
-
const isReady = dependencySatisfied(task, index.doneSteps, index.idMap, index.stepToTaskId);
|
|
51852
|
-
resolvedQueue = isReady ? "ready" : "blocked";
|
|
51853
|
-
} else if (task.status === "running") {
|
|
51854
|
-
resolvedQueue = "running";
|
|
51855
|
-
} else if (task.status === "completed" || task.status === "skipped" || task.status === "needs_attention") {
|
|
51856
|
-
resolvedQueue = "done";
|
|
51857
|
-
} else {
|
|
51858
|
-
resolvedQueue = "blocked";
|
|
51859
|
-
}
|
|
51860
|
-
if (task.graph && task.graph.queue === resolvedQueue) {
|
|
51861
|
-
return task;
|
|
51862
|
-
}
|
|
51863
|
-
return {
|
|
51864
|
-
...task,
|
|
51865
|
-
graph: task.graph ? { ...task.graph, queue: resolvedQueue } : task.graph
|
|
51866
|
-
};
|
|
51867
|
-
}
|
|
51868
|
-
function ensureIndex(tasks, index) {
|
|
51869
|
-
return index ?? buildTaskGraphIndex(tasks);
|
|
51870
|
-
}
|
|
51871
|
-
function refreshTaskGraphQueues(tasks, index) {
|
|
51872
|
-
const resolved = ensureIndex(tasks, index);
|
|
51873
|
-
return tasks.map((task) => withQueue(task, resolved));
|
|
51874
|
-
}
|
|
51875
|
-
function taskGraphSnapshot(tasks, index) {
|
|
51876
|
-
const refreshed = refreshTaskGraphQueues(tasks, index);
|
|
51877
|
-
return {
|
|
51878
|
-
ready: refreshed.filter((task) => task.status === "queued" && task.graph?.queue === "ready").map((task) => task.id),
|
|
51879
|
-
blocked: refreshed.filter((task) => task.status === "queued" && task.graph?.queue === "blocked").map((task) => task.id),
|
|
51880
|
-
running: refreshed.filter((task) => task.status === "running").map((task) => task.id),
|
|
51881
|
-
done: refreshed.filter((task) => task.status === "completed" || task.status === "skipped").map((task) => task.id),
|
|
51882
|
-
failed: refreshed.filter((task) => task.status === "failed").map((task) => task.id),
|
|
51883
|
-
cancelled: refreshed.filter((task) => task.status === "cancelled").map((task) => task.id)
|
|
51884
|
-
};
|
|
51885
|
-
}
|
|
51886
|
-
var taskGraphIndexCache;
|
|
51887
|
-
var init_task_graph_scheduler = __esm({
|
|
51888
|
-
"src/runtime/scheduling/task-graph-scheduler.ts"() {
|
|
51889
|
-
"use strict";
|
|
51890
|
-
taskGraphIndexCache = /* @__PURE__ */ new WeakMap();
|
|
51891
|
-
}
|
|
51892
|
-
});
|
|
51893
|
-
|
|
51894
51972
|
// src/extension/knowledge-injection.ts
|
|
51895
51973
|
import * as fs75 from "node:fs";
|
|
51896
51974
|
import * as path65 from "node:path";
|
|
@@ -54551,16 +54629,24 @@ function validateWorkerOutput(role, output) {
|
|
|
54551
54629
|
issues
|
|
54552
54630
|
};
|
|
54553
54631
|
}
|
|
54554
|
-
var ROLE_PATTERN_DEFS, makeUrlRe;
|
|
54632
|
+
var MARKDOWN_STRUCTURED, STRICT_ROLE_PATTERNS, ROLE_PATTERN_DEFS, makeUrlRe;
|
|
54555
54633
|
var init_output_validator = __esm({
|
|
54556
54634
|
"src/runtime/output/output-validator.ts"() {
|
|
54557
54635
|
"use strict";
|
|
54636
|
+
MARKDOWN_STRUCTURED = /^(?:#{1,6}\s|\*\*|[-*]\s|\d+\.\s)/m;
|
|
54637
|
+
STRICT_ROLE_PATTERNS = {
|
|
54638
|
+
explorer: /^(\S+:\d+|Defs:|Refs:|Callers:|Tests:|Sites:|No match\.|totals:)/m,
|
|
54639
|
+
executor: /^(\S+:\d+(-\d+)? — .{1,80}\.|verified:|too-big\.|needs-confirm\.|ambiguous\.|regressed\.)/m,
|
|
54640
|
+
reviewer: new RegExp("^([^:\\s]+:\\d+:\\s+\\p{Emoji_Presentation}|No issues\\.|totals:)", "mu"),
|
|
54641
|
+
"security-reviewer": new RegExp("^([^:\\s]+:\\d+:\\s+\\p{Emoji_Presentation}|No issues\\.|totals:)", "mu"),
|
|
54642
|
+
verifier: /^(PASS:|FAIL:)/m
|
|
54643
|
+
};
|
|
54558
54644
|
ROLE_PATTERN_DEFS = {
|
|
54559
|
-
explorer: () =>
|
|
54560
|
-
executor: () =>
|
|
54561
|
-
reviewer: () => new RegExp(
|
|
54562
|
-
"security-reviewer": () => new RegExp(
|
|
54563
|
-
verifier: () =>
|
|
54645
|
+
explorer: () => new RegExp(`(?:${STRICT_ROLE_PATTERNS.explorer.source})|(?:${MARKDOWN_STRUCTURED.source})`, "m"),
|
|
54646
|
+
executor: () => new RegExp(`(?:${STRICT_ROLE_PATTERNS.executor.source})|(?:${MARKDOWN_STRUCTURED.source})`, "m"),
|
|
54647
|
+
reviewer: () => new RegExp(`(?:${STRICT_ROLE_PATTERNS.reviewer.source})|(?:${MARKDOWN_STRUCTURED.source})`, "mu"),
|
|
54648
|
+
"security-reviewer": () => new RegExp(`(?:${STRICT_ROLE_PATTERNS["security-reviewer"].source})|(?:${MARKDOWN_STRUCTURED.source})`, "mu"),
|
|
54649
|
+
verifier: () => new RegExp(`(?:${STRICT_ROLE_PATTERNS.verifier.source})|(?:${MARKDOWN_STRUCTURED.source})`, "m")
|
|
54564
54650
|
};
|
|
54565
54651
|
makeUrlRe = () => /\bhttps?:\/\/[^\s<>)\]"',;]+/gi;
|
|
54566
54652
|
}
|
|
@@ -56787,12 +56873,13 @@ __export(team_runner_exports, {
|
|
|
56787
56873
|
drainPendingUnits: () => drainPendingUnits,
|
|
56788
56874
|
executeTeamRun: () => executeTeamRun,
|
|
56789
56875
|
hasPendingMutatingTaskAtBoundary: () => hasPendingMutatingTaskAtBoundary,
|
|
56790
|
-
mergeTaskUpdatesPreservingTerminal: () => mergeTaskUpdatesPreservingTerminal,
|
|
56791
56876
|
setRunStatusRunning: () => setRunStatusRunning,
|
|
56792
56877
|
shouldUseRetry: () => shouldUseRetry
|
|
56793
56878
|
});
|
|
56879
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
56794
56880
|
import * as fs86 from "node:fs";
|
|
56795
56881
|
import * as path72 from "node:path";
|
|
56882
|
+
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
56796
56883
|
function startTeamRunHeartbeat(stateRoot, runId) {
|
|
56797
56884
|
const heartbeatPath = path72.join(stateRoot, "heartbeat.json");
|
|
56798
56885
|
const writeHeartbeat = () => {
|
|
@@ -56816,6 +56903,87 @@ function startTeamRunHeartbeat(stateRoot, runId) {
|
|
|
56816
56903
|
const interval = setInterval(writeHeartbeat, 6e4);
|
|
56817
56904
|
return () => clearInterval(interval);
|
|
56818
56905
|
}
|
|
56906
|
+
function perfScriptPath(scriptName) {
|
|
56907
|
+
try {
|
|
56908
|
+
const candidates = [
|
|
56909
|
+
fileURLToPath7(new URL(`../../scripts/${scriptName}`, import.meta.url)),
|
|
56910
|
+
fileURLToPath7(new URL(`../scripts/${scriptName}`, import.meta.url))
|
|
56911
|
+
];
|
|
56912
|
+
return candidates.find((p) => fs86.existsSync(p));
|
|
56913
|
+
} catch {
|
|
56914
|
+
return void 0;
|
|
56915
|
+
}
|
|
56916
|
+
}
|
|
56917
|
+
function startPerfSampler(manifest, team) {
|
|
56918
|
+
const marker = (msg) => {
|
|
56919
|
+
try {
|
|
56920
|
+
fs86.appendFileSync(path72.join(manifest.artifactsRoot, "perf-obs.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
|
|
56921
|
+
`);
|
|
56922
|
+
} catch {
|
|
56923
|
+
}
|
|
56924
|
+
};
|
|
56925
|
+
marker(`startPerfSampler entered (team=${team.name} observability=${String(team.observability)} importMetaUrl=${import.meta.url})`);
|
|
56926
|
+
if (team.observability !== true) {
|
|
56927
|
+
marker(`SKIP: observability=${String(team.observability)} !== true`);
|
|
56928
|
+
return;
|
|
56929
|
+
}
|
|
56930
|
+
const samplerPath = perfScriptPath("resource-sampler.mjs");
|
|
56931
|
+
if (!samplerPath) {
|
|
56932
|
+
marker(`SKIP: resource-sampler.mjs not found (importMetaUrl=${import.meta.url})`);
|
|
56933
|
+
return;
|
|
56934
|
+
}
|
|
56935
|
+
marker(`spawning sampler from ${samplerPath}`);
|
|
56936
|
+
const crewRoot = path72.dirname(path72.dirname(path72.dirname(manifest.stateRoot)));
|
|
56937
|
+
const outPath = path72.join(manifest.artifactsRoot, "resources.jsonl");
|
|
56938
|
+
const logPath = path72.join(manifest.artifactsRoot, "perf-obs.log");
|
|
56939
|
+
try {
|
|
56940
|
+
const child = spawn6(
|
|
56941
|
+
process.execPath,
|
|
56942
|
+
[
|
|
56943
|
+
"--experimental-strip-types",
|
|
56944
|
+
samplerPath,
|
|
56945
|
+
"--watch-run",
|
|
56946
|
+
manifest.runId,
|
|
56947
|
+
"--crew-root",
|
|
56948
|
+
crewRoot,
|
|
56949
|
+
"--interval",
|
|
56950
|
+
String(OBSERVABILITY_INTERVAL_MS),
|
|
56951
|
+
"--out",
|
|
56952
|
+
outPath
|
|
56953
|
+
],
|
|
56954
|
+
{ detached: true, stdio: ["ignore", "ignore", "pipe"] }
|
|
56955
|
+
);
|
|
56956
|
+
child.stderr?.on("data", (d) => {
|
|
56957
|
+
try {
|
|
56958
|
+
fs86.appendFileSync(logPath, String(d));
|
|
56959
|
+
} catch {
|
|
56960
|
+
}
|
|
56961
|
+
});
|
|
56962
|
+
child.unref();
|
|
56963
|
+
} catch (err2) {
|
|
56964
|
+
console.warn(`[perf-obs] sampler spawn failed for ${manifest.runId}: ${String(err2)}`);
|
|
56965
|
+
}
|
|
56966
|
+
}
|
|
56967
|
+
function schedulePerfAnalyze(manifest, team) {
|
|
56968
|
+
if (team.observability !== true) return;
|
|
56969
|
+
const analyzePath = perfScriptPath("analyze-run.mjs");
|
|
56970
|
+
const resourcesPath = path72.join(manifest.artifactsRoot, "resources.jsonl");
|
|
56971
|
+
if (!analyzePath || !fs86.existsSync(resourcesPath)) return;
|
|
56972
|
+
const crewRoot = path72.dirname(path72.dirname(path72.dirname(manifest.stateRoot)));
|
|
56973
|
+
const timer = setTimeout(() => {
|
|
56974
|
+
try {
|
|
56975
|
+
const child = spawn6(
|
|
56976
|
+
process.execPath,
|
|
56977
|
+
["--experimental-strip-types", analyzePath, manifest.runId, "--crew-root", crewRoot, "--resources", resourcesPath],
|
|
56978
|
+
{ detached: true, stdio: "ignore" }
|
|
56979
|
+
);
|
|
56980
|
+
child.unref();
|
|
56981
|
+
} catch (err2) {
|
|
56982
|
+
console.warn(`[perf-obs] analyze spawn failed for ${manifest.runId}: ${String(err2)}`);
|
|
56983
|
+
}
|
|
56984
|
+
}, OBSERVABILITY_ANALYZE_DELAY_MS);
|
|
56985
|
+
timer.unref();
|
|
56986
|
+
}
|
|
56819
56987
|
function checkPerTaskBudget(tasks, budgetTotal, budgetWarning, budgetAbort, fairShareFraction = 0.5) {
|
|
56820
56988
|
const usage = aggregateUsage(tasks);
|
|
56821
56989
|
const totalUsed = (usage?.input ?? 0) + (usage?.output ?? 0) + (usage?.cacheWrite ?? 0);
|
|
@@ -56859,9 +57027,6 @@ function markBlocked(tasks, reason) {
|
|
|
56859
57027
|
} : task
|
|
56860
57028
|
);
|
|
56861
57029
|
}
|
|
56862
|
-
function isNonTerminalTaskStatus(status) {
|
|
56863
|
-
return status === "queued" || status === "running" || status === "waiting";
|
|
56864
|
-
}
|
|
56865
57030
|
function cancelNonTerminalTasks(tasks, status, reason, filter, transform) {
|
|
56866
57031
|
const predicate = filter ?? ((task) => isNonTerminalTaskStatus(task.status));
|
|
56867
57032
|
return tasks.map((task) => {
|
|
@@ -56870,63 +57035,6 @@ function cancelNonTerminalTasks(tasks, status, reason, filter, transform) {
|
|
|
56870
57035
|
return transform ? transform(task, terminalised) : terminalised;
|
|
56871
57036
|
});
|
|
56872
57037
|
}
|
|
56873
|
-
function safeFinishedAt(task) {
|
|
56874
|
-
if (!task.finishedAt) return -Infinity;
|
|
56875
|
-
const ms = new Date(task.finishedAt).getTime();
|
|
56876
|
-
return Number.isNaN(ms) ? Infinity : ms;
|
|
56877
|
-
}
|
|
56878
|
-
function isMalformedFinishedAtReplacement(currentTime, updatedTime) {
|
|
56879
|
-
return !Number.isFinite(currentTime) && Number.isFinite(updatedTime);
|
|
56880
|
-
}
|
|
56881
|
-
function statusMergeKey(from, to) {
|
|
56882
|
-
return `${from}->${to}`;
|
|
56883
|
-
}
|
|
56884
|
-
function shouldMergeTaskUpdate(current, updated) {
|
|
56885
|
-
if (REJECTED_STATUS_MERGE_TRANSITIONS.has(statusMergeKey(current.status, updated.status))) return false;
|
|
56886
|
-
if (current.status === updated.status && updated.status === "running" && current.resultArtifact && !updated.resultArtifact)
|
|
56887
|
-
return false;
|
|
56888
|
-
if (current.status === updated.status && current.status === "completed" && current.resultArtifact && !updated.resultArtifact)
|
|
56889
|
-
return false;
|
|
56890
|
-
if (current.finishedAt !== void 0 && updated.finishedAt !== void 0) {
|
|
56891
|
-
const currentTime = safeFinishedAt(current);
|
|
56892
|
-
const updatedTime = safeFinishedAt(updated);
|
|
56893
|
-
if (!Number.isFinite(currentTime)) {
|
|
56894
|
-
console.warn(`[team-runner] Task ${current.id} has malformed finishedAt: ${current.finishedAt}`);
|
|
56895
|
-
}
|
|
56896
|
-
if (isMalformedFinishedAtReplacement(currentTime, updatedTime)) {
|
|
56897
|
-
return true;
|
|
56898
|
-
}
|
|
56899
|
-
if (updatedTime < currentTime) return false;
|
|
56900
|
-
}
|
|
56901
|
-
if (!updated.finishedAt && !isNonTerminalTaskStatus(updated.status)) return false;
|
|
56902
|
-
const hasMeaningfulUpdate = updated.status !== current.status || updated.finishedAt !== current.finishedAt || updated.startedAt !== current.startedAt || Boolean(updated.resultArtifact) !== Boolean(current.resultArtifact) || Boolean(updated.resultArtifact) && updated.resultArtifact !== current.resultArtifact || Boolean(updated.error) || Boolean(updated.modelAttempts?.length) || Boolean(updated.usage) || Boolean(updated.attempts?.length) || updated.heartbeat?.lastSeenAt !== current.heartbeat?.lastSeenAt || updated.jsonEvents !== current.jsonEvents || updated.agentProgress?.lastActivityAt !== current.agentProgress?.lastActivityAt;
|
|
56903
|
-
return hasMeaningfulUpdate;
|
|
56904
|
-
}
|
|
56905
|
-
function mergeTaskUpdatesPreservingTerminal(base, results) {
|
|
56906
|
-
const indexById = /* @__PURE__ */ new Map();
|
|
56907
|
-
for (const task of base) indexById.set(task.id, task);
|
|
56908
|
-
let skipped = 0;
|
|
56909
|
-
for (const result4 of results) {
|
|
56910
|
-
for (const updated of result4.tasks) {
|
|
56911
|
-
const current = indexById.get(updated.id);
|
|
56912
|
-
if (!current) continue;
|
|
56913
|
-
if (!shouldMergeTaskUpdate(current, updated)) {
|
|
56914
|
-
console.debug("[team-runner] Skipping stale merge for task", updated.id, {
|
|
56915
|
-
currentStatus: current.status,
|
|
56916
|
-
updatedStatus: updated.status,
|
|
56917
|
-
currentFinishedAt: current.finishedAt,
|
|
56918
|
-
updatedFinishedAt: updated.finishedAt
|
|
56919
|
-
});
|
|
56920
|
-
skipped += 1;
|
|
56921
|
-
continue;
|
|
56922
|
-
}
|
|
56923
|
-
indexById.set(updated.id, updated);
|
|
56924
|
-
}
|
|
56925
|
-
}
|
|
56926
|
-
const merged = base.map((task) => indexById.get(task.id) ?? task);
|
|
56927
|
-
void skipped;
|
|
56928
|
-
return refreshTaskGraphQueues(merged);
|
|
56929
|
-
}
|
|
56930
57038
|
function formatTaskProgress(task) {
|
|
56931
57039
|
return `- ${task.id}: ${task.status} (${task.role} -> ${task.agent})${task.taskPacket ? ` scope=${task.taskPacket.scope}` : ""}${task.verification ? ` green=${task.verification.observedGreenLevel}/${task.verification.requiredGreenLevel}` : ""}${task.error ? ` - ${task.error}` : ""}`;
|
|
56932
57040
|
}
|
|
@@ -57188,6 +57296,7 @@ async function executeTeamRun(input) {
|
|
|
57188
57296
|
}
|
|
57189
57297
|
void registerRunPromise(manifest.runId);
|
|
57190
57298
|
const stopTeamHeartbeat = startTeamRunHeartbeat(manifest.stateRoot, manifest.runId);
|
|
57299
|
+
startPerfSampler(manifest, input.team);
|
|
57191
57300
|
const cleanupUsage = () => {
|
|
57192
57301
|
for (const task of input.tasks) clearTrackedTaskUsage(task.id);
|
|
57193
57302
|
};
|
|
@@ -57253,6 +57362,7 @@ async function executeTeamRun(input) {
|
|
|
57253
57362
|
);
|
|
57254
57363
|
}
|
|
57255
57364
|
await flushEventLogBuffer();
|
|
57365
|
+
schedulePerfAnalyze(manifest, input.team);
|
|
57256
57366
|
return result4;
|
|
57257
57367
|
} catch (error) {
|
|
57258
57368
|
stopTeamHeartbeat();
|
|
@@ -58340,15 +58450,13 @@ async function executeTeamRunCore(input, manifest, workflow) {
|
|
|
58340
58450
|
await drainPendingUnits(pendingUnits, runController);
|
|
58341
58451
|
}
|
|
58342
58452
|
}
|
|
58343
|
-
var
|
|
58453
|
+
var OBSERVABILITY_INTERVAL_MS, OBSERVABILITY_ANALYZE_DELAY_MS, lastProgressContentHash, __test__lastProgressContentHash, __test__writeProgress, __test__cancelPlanTasks;
|
|
58344
58454
|
var init_team_runner = __esm({
|
|
58345
58455
|
"src/runtime/team-runner.ts"() {
|
|
58346
58456
|
"use strict";
|
|
58347
58457
|
init_errors3();
|
|
58348
58458
|
init_registry2();
|
|
58349
58459
|
init_correlation();
|
|
58350
|
-
init_plugin_registry();
|
|
58351
|
-
init_plugins();
|
|
58352
58460
|
init_atomic_write();
|
|
58353
58461
|
init_contracts();
|
|
58354
58462
|
init_locks();
|
|
@@ -58366,6 +58474,7 @@ var init_team_runner = __esm({
|
|
|
58366
58474
|
init_goal_achievement();
|
|
58367
58475
|
init_group_join();
|
|
58368
58476
|
init_live_agent_manager();
|
|
58477
|
+
init_merge_gate();
|
|
58369
58478
|
init_runtime_policy();
|
|
58370
58479
|
init_path_overlap();
|
|
58371
58480
|
init_policy_engine();
|
|
@@ -58387,32 +58496,10 @@ var init_team_runner = __esm({
|
|
|
58387
58496
|
init_usage_tracker();
|
|
58388
58497
|
init_workflow_state();
|
|
58389
58498
|
init_adaptive_plan();
|
|
58499
|
+
init_merge_gate();
|
|
58390
58500
|
init_adaptive_plan();
|
|
58391
|
-
|
|
58392
|
-
|
|
58393
|
-
builtInRegistry.register(VitestPlugin);
|
|
58394
|
-
builtInRegistry.register(VitePlugin);
|
|
58395
|
-
REJECTED_STATUS_MERGE_TRANSITIONS = (() => {
|
|
58396
|
-
const rejected = /* @__PURE__ */ new Set();
|
|
58397
|
-
for (const from of TEAM_TASK_STATUSES) {
|
|
58398
|
-
if (!TEAM_TERMINAL_TASK_STATUSES.has(from)) continue;
|
|
58399
|
-
for (const to of TEAM_TASK_STATUSES) {
|
|
58400
|
-
if (!TEAM_TERMINAL_TASK_STATUSES.has(to)) rejected.add(statusMergeKey(from, to));
|
|
58401
|
-
}
|
|
58402
|
-
}
|
|
58403
|
-
rejected.add(statusMergeKey("waiting", "running"));
|
|
58404
|
-
const completedIntegrityFlips = [
|
|
58405
|
-
["completed", "failed"],
|
|
58406
|
-
["completed", "needs_attention"],
|
|
58407
|
-
["failed", "completed"],
|
|
58408
|
-
["cancelled", "completed"],
|
|
58409
|
-
["needs_attention", "completed"]
|
|
58410
|
-
];
|
|
58411
|
-
for (const [from, to] of completedIntegrityFlips) rejected.add(statusMergeKey(from, to));
|
|
58412
|
-
return rejected;
|
|
58413
|
-
})();
|
|
58414
|
-
__test__shouldMergeTaskUpdate = shouldMergeTaskUpdate;
|
|
58415
|
-
__test__mergeTaskUpdates = mergeTaskUpdatesPreservingTerminal;
|
|
58501
|
+
OBSERVABILITY_INTERVAL_MS = 2e3;
|
|
58502
|
+
OBSERVABILITY_ANALYZE_DELAY_MS = 3e3;
|
|
58416
58503
|
lastProgressContentHash = /* @__PURE__ */ new Map();
|
|
58417
58504
|
__test__lastProgressContentHash = lastProgressContentHash;
|
|
58418
58505
|
__test__writeProgress = writeProgress;
|
|
@@ -66261,7 +66348,6 @@ var init_mascot = __esm({
|
|
|
66261
66348
|
currentArminGrid;
|
|
66262
66349
|
effectState = {};
|
|
66263
66350
|
effectDone = false;
|
|
66264
|
-
visible = true;
|
|
66265
66351
|
frame = 0;
|
|
66266
66352
|
effectPhase = 0;
|
|
66267
66353
|
gridVersion = 0;
|
|
@@ -66357,7 +66443,7 @@ var init_mascot = __esm({
|
|
|
66357
66443
|
this.gridVersion++;
|
|
66358
66444
|
}
|
|
66359
66445
|
this.invalidate();
|
|
66360
|
-
|
|
66446
|
+
this.requestRender?.();
|
|
66361
66447
|
}
|
|
66362
66448
|
tickArminEffect() {
|
|
66363
66449
|
switch (this.effect) {
|
|
@@ -66564,14 +66650,6 @@ var init_mascot = __esm({
|
|
|
66564
66650
|
this.close();
|
|
66565
66651
|
}
|
|
66566
66652
|
}
|
|
66567
|
-
/**
|
|
66568
|
-
* Set whether the mascot is currently visible (not obscured by another
|
|
66569
|
-
* overlay). When invisible, tick() skips requestRender so the animation
|
|
66570
|
-
* does not trigger needless repaints while hidden.
|
|
66571
|
-
*/
|
|
66572
|
-
setVisible(visible) {
|
|
66573
|
-
this.visible = visible;
|
|
66574
|
-
}
|
|
66575
66653
|
dispose() {
|
|
66576
66654
|
this.doneGuard.called = true;
|
|
66577
66655
|
if (this.interval) clearInterval(this.interval);
|
|
@@ -70620,10 +70698,18 @@ var init_otlp_exporter = __esm({
|
|
|
70620
70698
|
});
|
|
70621
70699
|
|
|
70622
70700
|
// src/observability/metrics-primitives.ts
|
|
70623
|
-
function
|
|
70701
|
+
function getCardinalityEvictions() {
|
|
70702
|
+
return cardinalityEvictions;
|
|
70703
|
+
}
|
|
70704
|
+
function enforceLabelCap(map3, _metricName) {
|
|
70624
70705
|
while (map3.size > MAX_LABEL_COMBINATIONS) {
|
|
70625
70706
|
const firstKey = map3.keys().next().value;
|
|
70626
|
-
if (firstKey !== void 0)
|
|
70707
|
+
if (firstKey !== void 0) {
|
|
70708
|
+
map3.delete(firstKey);
|
|
70709
|
+
cardinalityEvictions++;
|
|
70710
|
+
} else {
|
|
70711
|
+
break;
|
|
70712
|
+
}
|
|
70627
70713
|
}
|
|
70628
70714
|
}
|
|
70629
70715
|
function normalizeLabels(labels = {}) {
|
|
@@ -70637,12 +70723,13 @@ function labelKey(labels = {}) {
|
|
|
70637
70723
|
function cloneLabels(labels) {
|
|
70638
70724
|
return { ...labels };
|
|
70639
70725
|
}
|
|
70640
|
-
var DEFAULT_HISTOGRAM_BUCKETS, MAX_LABEL_COMBINATIONS, Metric, Counter, Gauge, Histogram;
|
|
70726
|
+
var DEFAULT_HISTOGRAM_BUCKETS, MAX_LABEL_COMBINATIONS, cardinalityEvictions, Metric, Counter, Gauge, Histogram;
|
|
70641
70727
|
var init_metrics_primitives = __esm({
|
|
70642
70728
|
"src/observability/metrics-primitives.ts"() {
|
|
70643
70729
|
"use strict";
|
|
70644
70730
|
DEFAULT_HISTOGRAM_BUCKETS = [1, 2, 5, 10, 25, 50, 100, 250, 500, 1e3, 2500, 5e3, 1e4];
|
|
70645
70731
|
MAX_LABEL_COMBINATIONS = 1e4;
|
|
70732
|
+
cardinalityEvictions = 0;
|
|
70646
70733
|
Metric = class {
|
|
70647
70734
|
name;
|
|
70648
70735
|
description;
|
|
@@ -70907,6 +70994,14 @@ function wireEventToMetrics(events, registry2) {
|
|
|
70907
70994
|
const deadletterCount = registry2.counter("crew.task.deadletter_total", "Deadletter triggers by reason");
|
|
70908
70995
|
const overflowCount = registry2.counter("crew.task.overflow_phase_total", "Overflow recovery phase transitions");
|
|
70909
70996
|
const supervisorContactCount = registry2.counter("crew.task.supervisor_contact_total", "Supervisor contact requests by reason");
|
|
70997
|
+
const unboundedConcurrencyCount = registry2.counter(
|
|
70998
|
+
"crew.limits.unbounded_total",
|
|
70999
|
+
"Runs that enabled allowUnboundedConcurrency (advisory; bypasses hard cap)"
|
|
71000
|
+
);
|
|
71001
|
+
const cardinalityEvictedGauge = registry2.gauge(
|
|
71002
|
+
"crew.metrics.cardinality_evicted",
|
|
71003
|
+
"Cumulative label-combination evictions (non-zero = unreliable aggregation)"
|
|
71004
|
+
);
|
|
70910
71005
|
registry2.gauge("crew.heartbeat.staleness_ms", "Heartbeat elapsed since last seen, milliseconds");
|
|
70911
71006
|
const runDuration = registry2.histogram(
|
|
70912
71007
|
"crew.run.duration_ms",
|
|
@@ -71006,11 +71101,21 @@ function wireEventToMetrics(events, registry2) {
|
|
|
71006
71101
|
direction: stringValue(item.direction, "unknown")
|
|
71007
71102
|
});
|
|
71008
71103
|
}
|
|
71104
|
+
],
|
|
71105
|
+
[
|
|
71106
|
+
"crew.limits.unbounded",
|
|
71107
|
+
() => {
|
|
71108
|
+
unboundedConcurrencyCount.inc({});
|
|
71109
|
+
}
|
|
71009
71110
|
]
|
|
71010
71111
|
];
|
|
71011
71112
|
const unsubscribers = [];
|
|
71012
71113
|
for (const [event, handler] of handlers) {
|
|
71013
71114
|
const unsubscribe = events?.on?.(event, (data) => {
|
|
71115
|
+
try {
|
|
71116
|
+
cardinalityEvictedGauge.set({}, getCardinalityEvictions());
|
|
71117
|
+
} catch {
|
|
71118
|
+
}
|
|
71014
71119
|
try {
|
|
71015
71120
|
handler(data);
|
|
71016
71121
|
} catch {
|
|
@@ -71031,6 +71136,7 @@ var CANCELLATION_REASON_LABELS;
|
|
|
71031
71136
|
var init_event_to_metric = __esm({
|
|
71032
71137
|
"src/observability/event-to-metric.ts"() {
|
|
71033
71138
|
"use strict";
|
|
71139
|
+
init_metrics_primitives();
|
|
71034
71140
|
CANCELLATION_REASON_LABELS = /* @__PURE__ */ new Set([
|
|
71035
71141
|
"caller_cancelled",
|
|
71036
71142
|
"leader_interrupted",
|
|
@@ -72583,7 +72689,7 @@ function isDangerStage(index, levels) {
|
|
|
72583
72689
|
init_pi_ui_compat();
|
|
72584
72690
|
init_theme_adapter();
|
|
72585
72691
|
init_visual();
|
|
72586
|
-
import { isAbsolute as
|
|
72692
|
+
import { isAbsolute as isAbsolute11, relative as relative8, resolve as resolve21, sep as sep9 } from "node:path";
|
|
72587
72693
|
|
|
72588
72694
|
// src/extension/crew-vibes/render.ts
|
|
72589
72695
|
function formatCount(value) {
|
|
@@ -72720,7 +72826,7 @@ function formatCwdForFooter(cwd, home) {
|
|
|
72720
72826
|
const resolvedCwd = resolve21(cwd);
|
|
72721
72827
|
const resolvedHome = resolve21(home);
|
|
72722
72828
|
const rel = relative8(resolvedHome, resolvedCwd);
|
|
72723
|
-
const inside = rel === "" || rel !== ".." && !rel.startsWith(`..${sep9}`) && !
|
|
72829
|
+
const inside = rel === "" || rel !== ".." && !rel.startsWith(`..${sep9}`) && !isAbsolute11(rel);
|
|
72724
72830
|
if (!inside) return cwd;
|
|
72725
72831
|
return rel === "" ? "~" : `~${sep9}${rel}`;
|
|
72726
72832
|
}
|
|
@@ -75285,7 +75391,7 @@ function startForegroundRunImpl(pi, ctx, extensionCtx, runner, runId) {
|
|
|
75285
75391
|
init_config();
|
|
75286
75392
|
import * as fs103 from "node:fs";
|
|
75287
75393
|
import * as path82 from "node:path";
|
|
75288
|
-
import { fileURLToPath as
|
|
75394
|
+
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
75289
75395
|
|
|
75290
75396
|
// src/runtime/per-write-validator.ts
|
|
75291
75397
|
import { readFileSync as readFileSync81 } from "node:fs";
|
|
@@ -75388,7 +75494,7 @@ function installResourcesDiscoverHook(pi, ctx) {
|
|
|
75388
75494
|
pi.on("resources_discover", () => {
|
|
75389
75495
|
const sessionCwd = ctx.currentCtx?.cwd ?? process.cwd();
|
|
75390
75496
|
const skillDir = path82.resolve(sessionCwd, "skills");
|
|
75391
|
-
const extSkillDir = path82.resolve(path82.dirname(
|
|
75497
|
+
const extSkillDir = path82.resolve(path82.dirname(fileURLToPath8(import.meta.url)), "..", "..", "skills");
|
|
75392
75498
|
const paths = [];
|
|
75393
75499
|
if (fs103.existsSync(extSkillDir)) paths.push(extSkillDir);
|
|
75394
75500
|
if (skillDir !== extSkillDir && fs103.existsSync(skillDir)) {
|
|
@@ -76011,19 +76117,6 @@ var CrewBroker = class {
|
|
|
76011
76117
|
}
|
|
76012
76118
|
this.resolvedSocketPath = null;
|
|
76013
76119
|
}
|
|
76014
|
-
/**
|
|
76015
|
-
* Non-throwing enqueue entry point for the post-append mailbox observer
|
|
76016
|
-
* (Phase 1) or any other in-process producer. Phase 0 accepts `notifyMessage`
|
|
76017
|
-
* as a no-op shape so the lifecycle controller can install a single
|
|
76018
|
-
* observer regardless of broker state.
|
|
76019
|
-
*
|
|
76020
|
-
* Fanout goes ONLY to authenticated connections matching the recipient.
|
|
76021
|
-
* Phase 0 keeps this as a typed no-op (`not-implemented` would be
|
|
76022
|
-
* inappropriate here — the caller is in-process and shouldn't be
|
|
76023
|
-
* punished for testing the broker skeleton).
|
|
76024
|
-
*/
|
|
76025
|
-
notifyMessage(_message) {
|
|
76026
|
-
}
|
|
76027
76120
|
// ------------------------------------------------------------------------
|
|
76028
76121
|
// Connection lifecycle
|
|
76029
76122
|
// ------------------------------------------------------------------------
|