@mestreyoda/fabrica 0.2.38 → 0.2.40
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/index.js +234 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -113905,8 +113905,8 @@ import fsSync from "node:fs";
|
|
|
113905
113905
|
import path5 from "node:path";
|
|
113906
113906
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
113907
113907
|
function getCurrentVersion() {
|
|
113908
|
-
if ("0.2.
|
|
113909
|
-
return "0.2.
|
|
113908
|
+
if ("0.2.40") {
|
|
113909
|
+
return "0.2.40";
|
|
113910
113910
|
}
|
|
113911
113911
|
try {
|
|
113912
113912
|
const pkgPath = path5.join(THIS_DIR, "..", "..", "package.json");
|
|
@@ -130510,6 +130510,10 @@ async function runIssueDoctor(opts) {
|
|
|
130510
130510
|
const convergenceAction = issueRuntime?.lastConvergenceAction ?? null;
|
|
130511
130511
|
const retryCount = issueRuntime?.lastConvergenceRetryCount ?? 0;
|
|
130512
130512
|
const convergenceReason = issueRuntime?.lastConvergenceReason ?? issueRuntime?.inconclusiveCompletionReason ?? null;
|
|
130513
|
+
const convergenceHeadSha = issueRuntime?.lastConvergenceHeadSha ?? null;
|
|
130514
|
+
const currentHeadSha = issueRuntime?.currentPrHeadSha ?? issueRuntime?.lastHeadSha ?? prStatus?.sourceBranch ?? null;
|
|
130515
|
+
const headShaChangedSinceLastConvergence = convergenceHeadSha && currentHeadSha ? convergenceHeadSha !== currentHeadSha : null;
|
|
130516
|
+
const progressState = issueRuntime?.sessionCompletedAt ? "completed" : issueRuntime?.firstWorkerActivityAt ? "active" : issueRuntime?.agentAcceptedAt ? "accepted_idle" : "no_dispatch";
|
|
130513
130517
|
const summaryParts = [
|
|
130514
130518
|
hasArtifact ? "artifact_present" : "artifact_missing",
|
|
130515
130519
|
convergenceCause ? `cause=${convergenceCause}` : "cause=none",
|
|
@@ -130531,12 +130535,22 @@ async function runIssueDoctor(opts) {
|
|
|
130531
130535
|
issueId: opts.issueId,
|
|
130532
130536
|
issueRuntime,
|
|
130533
130537
|
hasArtifact,
|
|
130538
|
+
lifecycle: {
|
|
130539
|
+
dispatchCycleId: issueRuntime?.lastDispatchCycleId ?? null,
|
|
130540
|
+
dispatchRunId: issueRuntime?.dispatchRunId ?? null,
|
|
130541
|
+
agentAcceptedAt: issueRuntime?.agentAcceptedAt ?? null,
|
|
130542
|
+
firstWorkerActivityAt: issueRuntime?.firstWorkerActivityAt ?? null,
|
|
130543
|
+
sessionCompletedAt: issueRuntime?.sessionCompletedAt ?? null,
|
|
130544
|
+
progressState
|
|
130545
|
+
},
|
|
130534
130546
|
convergence: {
|
|
130535
130547
|
cause: convergenceCause,
|
|
130536
130548
|
action: convergenceAction,
|
|
130537
130549
|
retryCount,
|
|
130538
130550
|
reason: convergenceReason,
|
|
130539
|
-
at: issueRuntime?.lastConvergenceAt ?? null
|
|
130551
|
+
at: issueRuntime?.lastConvergenceAt ?? null,
|
|
130552
|
+
headSha: convergenceHeadSha,
|
|
130553
|
+
headShaChangedSinceLastConvergence
|
|
130540
130554
|
},
|
|
130541
130555
|
pr: prStatus ? {
|
|
130542
130556
|
url: prStatus.url ?? null,
|
|
@@ -130565,9 +130579,17 @@ function formatIssueDoctor(result) {
|
|
|
130565
130579
|
` PR: ${result.pr?.url ?? "n/a"} (${result.pr?.state ?? "unknown"})`,
|
|
130566
130580
|
` Issue: ${result.issue?.url ?? "n/a"} (${result.issue?.state ?? "unknown"})`,
|
|
130567
130581
|
` Labels: ${result.issue?.labels?.join(", ") ?? "n/a"}`,
|
|
130582
|
+
` Dispatch cycle: ${result.lifecycle.dispatchCycleId ?? "n/a"}`,
|
|
130583
|
+
` Dispatch run: ${result.lifecycle.dispatchRunId ?? "n/a"}`,
|
|
130584
|
+
` Progress state: ${result.lifecycle.progressState}`,
|
|
130585
|
+
` Agent accepted: ${result.lifecycle.agentAcceptedAt ?? "n/a"}`,
|
|
130586
|
+
` First worker activity: ${result.lifecycle.firstWorkerActivityAt ?? "n/a"}`,
|
|
130587
|
+
` Session completed: ${result.lifecycle.sessionCompletedAt ?? "n/a"}`,
|
|
130568
130588
|
` Convergence cause: ${result.convergence.cause ?? "none"}`,
|
|
130569
130589
|
` Convergence action: ${result.convergence.action ?? "none"}`,
|
|
130570
130590
|
` Retry count: ${result.convergence.retryCount}`,
|
|
130591
|
+
` Convergence head SHA: ${result.convergence.headSha ?? "n/a"}`,
|
|
130592
|
+
` Head SHA changed since last convergence: ${result.convergence.headShaChangedSinceLastConvergence == null ? "unknown" : result.convergence.headShaChangedSinceLastConvergence ? "yes" : "no"}`,
|
|
130571
130593
|
` Last reason: ${result.convergence.reason ?? "n/a"}`,
|
|
130572
130594
|
` Suggested next action: ${result.recommendation.likelyNextAction}`
|
|
130573
130595
|
];
|
|
@@ -131368,6 +131390,51 @@ init_workflow();
|
|
|
131368
131390
|
init_context3();
|
|
131369
131391
|
init_labels();
|
|
131370
131392
|
|
|
131393
|
+
// lib/services/doctor-snapshot.ts
|
|
131394
|
+
init_audit();
|
|
131395
|
+
async function captureIssueDoctorSnapshot(opts) {
|
|
131396
|
+
try {
|
|
131397
|
+
const result = await runIssueDoctor({
|
|
131398
|
+
workspacePath: opts.workspaceDir,
|
|
131399
|
+
projectSlug: opts.projectSlug,
|
|
131400
|
+
issueId: opts.issueId,
|
|
131401
|
+
runCommand: opts.runCommand,
|
|
131402
|
+
pluginConfig: opts.pluginConfig
|
|
131403
|
+
});
|
|
131404
|
+
await log(opts.workspaceDir, opts.event, {
|
|
131405
|
+
projectSlug: opts.projectSlug,
|
|
131406
|
+
issueId: opts.issueId,
|
|
131407
|
+
trigger: opts.trigger,
|
|
131408
|
+
summary: result.recommendation.summary,
|
|
131409
|
+
likelyNextAction: result.recommendation.likelyNextAction,
|
|
131410
|
+
doctor: {
|
|
131411
|
+
artifact: result.hasArtifact,
|
|
131412
|
+
progressState: result.lifecycle.progressState,
|
|
131413
|
+
dispatchCycleId: result.lifecycle.dispatchCycleId,
|
|
131414
|
+
dispatchRunId: result.lifecycle.dispatchRunId,
|
|
131415
|
+
prUrl: result.pr?.url ?? null,
|
|
131416
|
+
prState: result.pr?.state ?? null,
|
|
131417
|
+
labels: result.issue?.labels ?? [],
|
|
131418
|
+
convergenceCause: result.convergence.cause,
|
|
131419
|
+
convergenceAction: result.convergence.action,
|
|
131420
|
+
convergenceRetryCount: result.convergence.retryCount,
|
|
131421
|
+
convergenceHeadSha: result.convergence.headSha,
|
|
131422
|
+
headShaChangedSinceLastConvergence: result.convergence.headShaChangedSinceLastConvergence
|
|
131423
|
+
},
|
|
131424
|
+
...opts.extra ?? {}
|
|
131425
|
+
});
|
|
131426
|
+
} catch (error48) {
|
|
131427
|
+
await log(opts.workspaceDir, `${opts.event}_failed`, {
|
|
131428
|
+
projectSlug: opts.projectSlug,
|
|
131429
|
+
issueId: opts.issueId,
|
|
131430
|
+
trigger: opts.trigger,
|
|
131431
|
+
error: error48 instanceof Error ? error48.message : String(error48),
|
|
131432
|
+
...opts.extra ?? {}
|
|
131433
|
+
}).catch(() => {
|
|
131434
|
+
});
|
|
131435
|
+
}
|
|
131436
|
+
}
|
|
131437
|
+
|
|
131371
131438
|
// lib/services/post-pr-convergence.ts
|
|
131372
131439
|
init_types3();
|
|
131373
131440
|
function classifyConvergenceCause(reason) {
|
|
@@ -132032,6 +132099,23 @@ ${validationReason}`;
|
|
|
132032
132099
|
lastConvergenceHeadSha: convergence.progressHeadSha
|
|
132033
132100
|
}).catch(() => {
|
|
132034
132101
|
});
|
|
132102
|
+
if (convergenceIssueRuntime?.currentPrUrl || convergence.action === "escalate_human") {
|
|
132103
|
+
await captureIssueDoctorSnapshot({
|
|
132104
|
+
workspaceDir: opts.workspaceDir,
|
|
132105
|
+
projectSlug: context2.projectSlug,
|
|
132106
|
+
issueId: context2.issueId,
|
|
132107
|
+
runCommand: opts.runCommand,
|
|
132108
|
+
pluginConfig: opts.pluginConfig,
|
|
132109
|
+
event: "doctor_snapshot",
|
|
132110
|
+
trigger: convergence.action === "escalate_human" ? "worker_completion_escalated" : "worker_completion_blocked_with_artifact",
|
|
132111
|
+
extra: {
|
|
132112
|
+
convergenceCause: convergence.cause,
|
|
132113
|
+
convergenceAction: convergence.action,
|
|
132114
|
+
convergenceRetryCount: convergence.retryCount
|
|
132115
|
+
}
|
|
132116
|
+
}).catch(() => {
|
|
132117
|
+
});
|
|
132118
|
+
}
|
|
132035
132119
|
await executeCompletion({
|
|
132036
132120
|
workspaceDir: opts.workspaceDir,
|
|
132037
132121
|
projectSlug: context2.projectSlug,
|
|
@@ -132719,6 +132803,22 @@ async function checkWorkerHealth(opts) {
|
|
|
132719
132803
|
toLabel: convergence.targetLabel,
|
|
132720
132804
|
deliveryState
|
|
132721
132805
|
});
|
|
132806
|
+
if (runCommand) {
|
|
132807
|
+
await captureIssueDoctorSnapshot({
|
|
132808
|
+
workspaceDir,
|
|
132809
|
+
projectSlug,
|
|
132810
|
+
issueId: issueIdNum,
|
|
132811
|
+
runCommand,
|
|
132812
|
+
event: "doctor_snapshot",
|
|
132813
|
+
trigger: convergence.action === "escalate_human" ? "completion_recovery_escalated" : "completion_recovery_requeued",
|
|
132814
|
+
extra: {
|
|
132815
|
+
convergenceCause: convergence.cause,
|
|
132816
|
+
convergenceAction: convergence.action,
|
|
132817
|
+
convergenceRetryCount: convergence.retryCount
|
|
132818
|
+
}
|
|
132819
|
+
}).catch(() => {
|
|
132820
|
+
});
|
|
132821
|
+
}
|
|
132722
132822
|
}
|
|
132723
132823
|
}
|
|
132724
132824
|
fixes.push(fix);
|
|
@@ -133087,6 +133187,23 @@ async function checkWorkerHealth(opts) {
|
|
|
133087
133187
|
idleMinutes: Math.round(quietMinutes),
|
|
133088
133188
|
deliveryState
|
|
133089
133189
|
});
|
|
133190
|
+
if (runCommand) {
|
|
133191
|
+
await captureIssueDoctorSnapshot({
|
|
133192
|
+
workspaceDir,
|
|
133193
|
+
projectSlug,
|
|
133194
|
+
issueId: issueIdNum,
|
|
133195
|
+
runCommand,
|
|
133196
|
+
event: "doctor_snapshot",
|
|
133197
|
+
trigger: convergence.action === "escalate_human" ? "stalled_with_artifact_escalated" : "stalled_with_artifact_requeued",
|
|
133198
|
+
extra: {
|
|
133199
|
+
convergenceCause: convergence.cause,
|
|
133200
|
+
convergenceAction: convergence.action,
|
|
133201
|
+
convergenceRetryCount: convergence.retryCount,
|
|
133202
|
+
idleMinutes: Math.round(quietMinutes)
|
|
133203
|
+
}
|
|
133204
|
+
}).catch(() => {
|
|
133205
|
+
});
|
|
133206
|
+
}
|
|
133090
133207
|
}
|
|
133091
133208
|
}
|
|
133092
133209
|
fixes.push(fix);
|
|
@@ -149107,12 +149224,29 @@ async function readAuditLines(filePath) {
|
|
|
149107
149224
|
}
|
|
149108
149225
|
return entries;
|
|
149109
149226
|
}
|
|
149227
|
+
function keyFor(entry) {
|
|
149228
|
+
const projectSlug = entry.projectSlug ?? entry.project ?? null;
|
|
149229
|
+
const issueId = entry.issueId ?? entry.issue ?? null;
|
|
149230
|
+
if (!projectSlug || issueId == null) return null;
|
|
149231
|
+
return `${projectSlug}:${issueId}`;
|
|
149232
|
+
}
|
|
149233
|
+
function normalizeCause(entry) {
|
|
149234
|
+
const cause = entry.convergenceCause ?? entry.reason ?? null;
|
|
149235
|
+
return cause ? String(cause) : null;
|
|
149236
|
+
}
|
|
149110
149237
|
async function computeMetrics(workspaceDir) {
|
|
149111
149238
|
const auditLogPath = join4(workspaceDir, DATA_DIR, "log", "audit.log");
|
|
149239
|
+
const bakEntries3 = await readAuditLines(`${auditLogPath}.3.bak`);
|
|
149112
149240
|
const bakEntries2 = await readAuditLines(`${auditLogPath}.2.bak`);
|
|
149113
149241
|
const bakEntries = await readAuditLines(`${auditLogPath}.bak`);
|
|
149114
149242
|
const currentEntries = await readAuditLines(auditLogPath);
|
|
149115
|
-
|
|
149243
|
+
const entries = [...bakEntries3, ...bakEntries2, ...bakEntries, ...currentEntries];
|
|
149244
|
+
const projectsData = await readProjects(workspaceDir).catch(() => ({ projects: {} }));
|
|
149245
|
+
const stackByProject = /* @__PURE__ */ new Map();
|
|
149246
|
+
for (const [slug, project] of Object.entries(projectsData.projects ?? {})) {
|
|
149247
|
+
const stack = project.stack ?? project.environment?.stack ?? null;
|
|
149248
|
+
if (stack) stackByProject.set(slug, String(stack));
|
|
149249
|
+
}
|
|
149116
149250
|
const entriesScanned = entries.length;
|
|
149117
149251
|
let dispatches = 0;
|
|
149118
149252
|
let completionsTotal = 0;
|
|
@@ -149122,16 +149256,40 @@ async function computeMetrics(workspaceDir) {
|
|
|
149122
149256
|
let completionsOther = 0;
|
|
149123
149257
|
let conflictsDetected = 0;
|
|
149124
149258
|
let sessionBudgetResets = 0;
|
|
149259
|
+
let humanEscalations = 0;
|
|
149260
|
+
const causeCounts = {};
|
|
149125
149261
|
const dispatchTimes = /* @__PURE__ */ new Map();
|
|
149262
|
+
const firstPrTimes = /* @__PURE__ */ new Map();
|
|
149126
149263
|
const completionDeltas = [];
|
|
149264
|
+
const firstPrDeltas = [];
|
|
149265
|
+
const stackMetrics = /* @__PURE__ */ new Map();
|
|
149266
|
+
function stackBucket(entry) {
|
|
149267
|
+
const slug = entry.projectSlug ?? entry.project ?? null;
|
|
149268
|
+
const stack = entry.stack ?? (slug ? stackByProject.get(String(slug)) : null) ?? "unknown";
|
|
149269
|
+
if (!stackMetrics.has(String(stack))) {
|
|
149270
|
+
stackMetrics.set(String(stack), {
|
|
149271
|
+
issues: /* @__PURE__ */ new Set(),
|
|
149272
|
+
dispatches: 0,
|
|
149273
|
+
escalations: 0,
|
|
149274
|
+
causeCounts: {},
|
|
149275
|
+
completionDeltas: [],
|
|
149276
|
+
firstPrDeltas: []
|
|
149277
|
+
});
|
|
149278
|
+
}
|
|
149279
|
+
return String(stack);
|
|
149280
|
+
}
|
|
149127
149281
|
for (const entry of entries) {
|
|
149282
|
+
const issueKey = keyFor(entry);
|
|
149283
|
+
const stack = stackBucket(entry);
|
|
149284
|
+
const stackBucketState = stackMetrics.get(stack);
|
|
149285
|
+
if (issueKey) stackBucketState.issues.add(issueKey);
|
|
149128
149286
|
switch (entry.event) {
|
|
149129
|
-
case "dispatch":
|
|
149287
|
+
case "dispatch": {
|
|
149130
149288
|
dispatches++;
|
|
149131
|
-
|
|
149132
|
-
|
|
149133
|
-
}
|
|
149289
|
+
stackBucketState.dispatches++;
|
|
149290
|
+
if (issueKey) dispatchTimes.set(issueKey, Date.parse(entry.ts));
|
|
149134
149291
|
break;
|
|
149292
|
+
}
|
|
149135
149293
|
case "work_finish": {
|
|
149136
149294
|
completionsTotal++;
|
|
149137
149295
|
const result = String(entry.result ?? "");
|
|
@@ -149139,14 +149297,13 @@ async function computeMetrics(workspaceDir) {
|
|
|
149139
149297
|
else if (result === "pass") completionsPass++;
|
|
149140
149298
|
else if (result === "fail") completionsFail++;
|
|
149141
149299
|
else completionsOther++;
|
|
149142
|
-
if (
|
|
149143
|
-
const
|
|
149144
|
-
const
|
|
149145
|
-
if (dispatchTime !== void 0) {
|
|
149146
|
-
const
|
|
149147
|
-
|
|
149148
|
-
|
|
149149
|
-
}
|
|
149300
|
+
if (issueKey) {
|
|
149301
|
+
const dispatchTime = dispatchTimes.get(issueKey);
|
|
149302
|
+
const completionTime = Date.parse(entry.ts);
|
|
149303
|
+
if (dispatchTime !== void 0 && !Number.isNaN(completionTime) && completionTime > dispatchTime) {
|
|
149304
|
+
const delta = (completionTime - dispatchTime) / 6e4;
|
|
149305
|
+
completionDeltas.push(delta);
|
|
149306
|
+
stackBucketState.completionDeltas.push(delta);
|
|
149150
149307
|
}
|
|
149151
149308
|
}
|
|
149152
149309
|
break;
|
|
@@ -149160,9 +149317,47 @@ async function computeMetrics(workspaceDir) {
|
|
|
149160
149317
|
case "session_budget_reset":
|
|
149161
149318
|
sessionBudgetResets++;
|
|
149162
149319
|
break;
|
|
149320
|
+
case "pr_discovered_via_polling":
|
|
149321
|
+
case "pr_updated_via_polling": {
|
|
149322
|
+
if (issueKey && !firstPrTimes.has(issueKey)) {
|
|
149323
|
+
const prTime = Date.parse(entry.ts);
|
|
149324
|
+
const dispatchTime = dispatchTimes.get(issueKey);
|
|
149325
|
+
firstPrTimes.set(issueKey, prTime);
|
|
149326
|
+
if (dispatchTime !== void 0 && !Number.isNaN(prTime) && prTime > dispatchTime) {
|
|
149327
|
+
const delta = (prTime - dispatchTime) / 6e4;
|
|
149328
|
+
firstPrDeltas.push(delta);
|
|
149329
|
+
stackBucketState.firstPrDeltas.push(delta);
|
|
149330
|
+
}
|
|
149331
|
+
}
|
|
149332
|
+
break;
|
|
149333
|
+
}
|
|
149334
|
+
case "worker_completion_skipped":
|
|
149335
|
+
case "doctor_snapshot":
|
|
149336
|
+
case "health_fix_applied": {
|
|
149337
|
+
const cause = normalizeCause(entry);
|
|
149338
|
+
if (cause) {
|
|
149339
|
+
causeCounts[cause] = (causeCounts[cause] ?? 0) + 1;
|
|
149340
|
+
stackBucketState.causeCounts[cause] = (stackBucketState.causeCounts[cause] ?? 0) + 1;
|
|
149341
|
+
}
|
|
149342
|
+
if (entry.convergenceAction === "escalate_human" || entry.action === "escalate_human") {
|
|
149343
|
+
humanEscalations++;
|
|
149344
|
+
stackBucketState.escalations++;
|
|
149345
|
+
}
|
|
149346
|
+
break;
|
|
149347
|
+
}
|
|
149163
149348
|
}
|
|
149164
149349
|
}
|
|
149165
|
-
const
|
|
149350
|
+
const avg = (values) => values.length ? values.reduce((a, b) => a + b, 0) / values.length : null;
|
|
149351
|
+
const stackMetricsObject = Object.fromEntries(
|
|
149352
|
+
[...stackMetrics.entries()].map(([stack, data]) => [stack, {
|
|
149353
|
+
issues: data.issues.size,
|
|
149354
|
+
dispatches: data.dispatches,
|
|
149355
|
+
escalations: data.escalations,
|
|
149356
|
+
causeCounts: data.causeCounts,
|
|
149357
|
+
avgDispatchToCompletionMinutes: avg(data.completionDeltas),
|
|
149358
|
+
avgDispatchToFirstPrMinutes: avg(data.firstPrDeltas)
|
|
149359
|
+
}])
|
|
149360
|
+
);
|
|
149166
149361
|
return {
|
|
149167
149362
|
entriesScanned,
|
|
149168
149363
|
dispatches,
|
|
@@ -149173,28 +149368,40 @@ async function computeMetrics(workspaceDir) {
|
|
|
149173
149368
|
fail: completionsFail,
|
|
149174
149369
|
other: completionsOther
|
|
149175
149370
|
},
|
|
149176
|
-
avgDispatchToCompletionMinutes,
|
|
149371
|
+
avgDispatchToCompletionMinutes: avg(completionDeltas),
|
|
149372
|
+
avgDispatchToFirstPrMinutes: avg(firstPrDeltas),
|
|
149177
149373
|
conflictsDetected,
|
|
149178
149374
|
sessionBudgetResets,
|
|
149375
|
+
humanEscalations,
|
|
149376
|
+
causeCounts,
|
|
149377
|
+
stackMetrics: stackMetricsObject,
|
|
149179
149378
|
auditLogPath
|
|
149180
149379
|
};
|
|
149181
149380
|
}
|
|
149182
149381
|
function formatMetrics(metrics2) {
|
|
149183
149382
|
const lines = [
|
|
149184
|
-
`Fabrica \u2014
|
|
149383
|
+
`Fabrica \u2014 M\xE9tricas (${metrics2.entriesScanned} entradas do audit.log)`,
|
|
149185
149384
|
` Dispatches: ${metrics2.dispatches}`
|
|
149186
149385
|
];
|
|
149187
149386
|
const c = metrics2.completions;
|
|
149188
|
-
lines.push(
|
|
149189
|
-
|
|
149190
|
-
);
|
|
149191
|
-
if (metrics2.avgDispatchToCompletionMinutes !== null) {
|
|
149192
|
-
lines.push(` Tempo medio dispatch \u2192 completion: ${metrics2.avgDispatchToCompletionMinutes.toFixed(1)} min`);
|
|
149193
|
-
} else {
|
|
149194
|
-
lines.push(` Tempo medio dispatch \u2192 completion: n/a`);
|
|
149195
|
-
}
|
|
149387
|
+
lines.push(` Conclus\xF5es: ${c.total} (done: ${c.done}, pass: ${c.pass}, fail: ${c.fail}${c.other > 0 ? `, other: ${c.other}` : ""})`);
|
|
149388
|
+
lines.push(` Tempo m\xE9dio dispatch \u2192 completion: ${metrics2.avgDispatchToCompletionMinutes?.toFixed(1) ?? "n/a"} min`);
|
|
149389
|
+
lines.push(` Tempo m\xE9dio dispatch \u2192 primeira PR: ${metrics2.avgDispatchToFirstPrMinutes?.toFixed(1) ?? "n/a"} min`);
|
|
149196
149390
|
lines.push(` Conflitos detectados: ${metrics2.conflictsDetected}`);
|
|
149197
149391
|
lines.push(` Session budget resets: ${metrics2.sessionBudgetResets}`);
|
|
149392
|
+
lines.push(` Escalonamentos humanos: ${metrics2.humanEscalations}`);
|
|
149393
|
+
if (Object.keys(metrics2.causeCounts).length > 0) {
|
|
149394
|
+
lines.push(" Causas tipadas:");
|
|
149395
|
+
for (const [cause, count] of Object.entries(metrics2.causeCounts).sort((a, b) => b[1] - a[1])) {
|
|
149396
|
+
lines.push(` - ${cause}: ${count}`);
|
|
149397
|
+
}
|
|
149398
|
+
}
|
|
149399
|
+
if (Object.keys(metrics2.stackMetrics).length > 0) {
|
|
149400
|
+
lines.push(" Por stack:");
|
|
149401
|
+
for (const [stack, data] of Object.entries(metrics2.stackMetrics)) {
|
|
149402
|
+
lines.push(` - ${stack}: issues=${data.issues}, dispatches=${data.dispatches}, escalations=${data.escalations}, avgPR=${data.avgDispatchToFirstPrMinutes?.toFixed(1) ?? "n/a"}m, avgDone=${data.avgDispatchToCompletionMinutes?.toFixed(1) ?? "n/a"}m`);
|
|
149403
|
+
}
|
|
149404
|
+
}
|
|
149198
149405
|
return lines.join("\n");
|
|
149199
149406
|
}
|
|
149200
149407
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mestreyoda/fabrica",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.40",
|
|
4
4
|
"description": "Autonomous software engineering pipeline for OpenClaw. Turns ideas into deployed code via intake, dispatch, review, test, and merge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|