@mestreyoda/fabrica 0.2.31 → 0.2.34
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 +142 -47
- 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.34") {
|
|
113909
|
+
return "0.2.34";
|
|
113910
113910
|
}
|
|
113911
113911
|
try {
|
|
113912
113912
|
const pkgPath = path5.join(THIS_DIR, "..", "..", "package.json");
|
|
@@ -131466,6 +131466,13 @@ function detectExecutionContractViolation(messages) {
|
|
|
131466
131466
|
evidence: nestedCommand
|
|
131467
131467
|
};
|
|
131468
131468
|
}
|
|
131469
|
+
const worktreeDrift = evidenceEntries.map((entry) => matchWorktreeDriftEvidence(entry.text)).find((match) => Boolean(match));
|
|
131470
|
+
if (worktreeDrift) {
|
|
131471
|
+
return {
|
|
131472
|
+
reason: "worktree_drift",
|
|
131473
|
+
evidence: worktreeDrift
|
|
131474
|
+
};
|
|
131475
|
+
}
|
|
131469
131476
|
for (const entry of assistantEntries) {
|
|
131470
131477
|
const metaSkillUsage = matchStrongMetaSkillUsage(entry.text);
|
|
131471
131478
|
if (metaSkillUsage) {
|
|
@@ -131491,6 +131498,19 @@ function detectExecutionContractViolation(messages) {
|
|
|
131491
131498
|
}
|
|
131492
131499
|
return null;
|
|
131493
131500
|
}
|
|
131501
|
+
function matchWorktreeDriftEvidence(text) {
|
|
131502
|
+
if (!text) return null;
|
|
131503
|
+
const patterns = [
|
|
131504
|
+
/ENOENT: .*\/home\/ubuntu\/\.openclaw\/workspace(?:\/[^\s'"`]+)?/,
|
|
131505
|
+
/^\/home\/ubuntu\/\.openclaw\/workspace$/m,
|
|
131506
|
+
/\/home\/ubuntu\/\.openclaw\/workspace(?:\/[^\s'"`]+)?/
|
|
131507
|
+
];
|
|
131508
|
+
for (const pattern of patterns) {
|
|
131509
|
+
const match = text.match(pattern);
|
|
131510
|
+
if (match?.[0]) return match[0];
|
|
131511
|
+
}
|
|
131512
|
+
return null;
|
|
131513
|
+
}
|
|
131494
131514
|
function collectWorkerTranscriptEvidence(messages) {
|
|
131495
131515
|
const evidence = [];
|
|
131496
131516
|
for (const message of messages) {
|
|
@@ -131914,48 +131934,49 @@ async function handleWorkerAgentEnd(opts) {
|
|
|
131914
131934
|
}).catch(() => {
|
|
131915
131935
|
});
|
|
131916
131936
|
}
|
|
131917
|
-
if (!observation.result) {
|
|
131918
|
-
if (
|
|
131919
|
-
|
|
131920
|
-
|
|
131921
|
-
|
|
131922
|
-
|
|
131923
|
-
|
|
131924
|
-
|
|
131925
|
-
|
|
131926
|
-
|
|
131927
|
-
|
|
131928
|
-
|
|
131929
|
-
|
|
131930
|
-
|
|
131931
|
-
|
|
131932
|
-
|
|
131933
|
-
|
|
131934
|
-
|
|
131935
|
-
|
|
131936
|
-
|
|
131937
|
-
|
|
131938
|
-
|
|
131939
|
-
|
|
131940
|
-
|
|
131941
|
-
|
|
131942
|
-
|
|
131943
|
-
|
|
131944
|
-
|
|
131945
|
-
|
|
131946
|
-
|
|
131947
|
-
|
|
131948
|
-
|
|
131949
|
-
|
|
131950
|
-
|
|
131951
|
-
|
|
131952
|
-
|
|
131953
|
-
|
|
131954
|
-
|
|
131955
|
-
|
|
131956
|
-
}
|
|
131957
|
-
return { applied: false, reason: "invalid_execution_path" };
|
|
131937
|
+
if (observation.executionContractViolation && (!observation.result || observation.executionContractViolation.reason === "worktree_drift")) {
|
|
131938
|
+
if (context2) {
|
|
131939
|
+
const violationPayload = {
|
|
131940
|
+
sessionKey: opts.sessionKey,
|
|
131941
|
+
projectSlug: context2.projectSlug,
|
|
131942
|
+
issueId: context2.issueId,
|
|
131943
|
+
role,
|
|
131944
|
+
reason: "invalid_execution_path",
|
|
131945
|
+
violationReason: observation.executionContractViolation.reason,
|
|
131946
|
+
evidence: observation.executionContractViolation.evidence
|
|
131947
|
+
};
|
|
131948
|
+
await updateIssueRuntime(opts.workspaceDir, context2.projectSlug, context2.issueId, {
|
|
131949
|
+
inconclusiveCompletionAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
131950
|
+
inconclusiveCompletionReason: "invalid_execution_path"
|
|
131951
|
+
}).catch(() => {
|
|
131952
|
+
});
|
|
131953
|
+
await log(opts.workspaceDir, "worker_execution_contract_violation", violationPayload).catch(() => {
|
|
131954
|
+
});
|
|
131955
|
+
await log(opts.workspaceDir, "worker_execution_recovery_started", violationPayload).catch(() => {
|
|
131956
|
+
});
|
|
131957
|
+
await log(opts.workspaceDir, "worker_completion_inconclusive", {
|
|
131958
|
+
...violationPayload,
|
|
131959
|
+
hadResultLine: Boolean(observation.result)
|
|
131960
|
+
}).catch(() => {
|
|
131961
|
+
});
|
|
131962
|
+
} else {
|
|
131963
|
+
const violationPayload = {
|
|
131964
|
+
sessionKey: opts.sessionKey,
|
|
131965
|
+
role,
|
|
131966
|
+
reason: "invalid_execution_path",
|
|
131967
|
+
violationReason: observation.executionContractViolation.reason,
|
|
131968
|
+
evidence: observation.executionContractViolation.evidence
|
|
131969
|
+
};
|
|
131970
|
+
await log(opts.workspaceDir, "worker_execution_contract_violation", violationPayload).catch(() => {
|
|
131971
|
+
});
|
|
131972
|
+
await log(opts.workspaceDir, "worker_result_skipped", {
|
|
131973
|
+
...violationPayload
|
|
131974
|
+
}).catch(() => {
|
|
131975
|
+
});
|
|
131958
131976
|
}
|
|
131977
|
+
return { applied: false, reason: "invalid_execution_path" };
|
|
131978
|
+
}
|
|
131979
|
+
if (!observation.result) {
|
|
131959
131980
|
if (context2 && observation.activityObserved) {
|
|
131960
131981
|
await updateIssueRuntime(opts.workspaceDir, context2.projectSlug, context2.issueId, {
|
|
131961
131982
|
inconclusiveCompletionAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -132597,15 +132618,17 @@ async function checkWorkerHealth(opts) {
|
|
|
132597
132618
|
const startedAtMs = new Date(slot.startTime).getTime();
|
|
132598
132619
|
const minutesActive = (Date.now() - startedAtMs) / 6e4;
|
|
132599
132620
|
const hours = minutesActive / 60;
|
|
132621
|
+
let reviewablePrStatus = null;
|
|
132600
132622
|
let hasReviewableArtifact = Boolean(
|
|
132601
132623
|
issueRuntime?.currentPrNumber || issueRuntime?.currentPrUrl || issueRuntime?.artifactOfRecord?.prNumber
|
|
132602
132624
|
);
|
|
132603
|
-
if (
|
|
132625
|
+
if (issueIdNum) {
|
|
132604
132626
|
try {
|
|
132605
132627
|
const prStatus = await provider.getPrStatus(issueIdNum);
|
|
132606
|
-
|
|
132607
|
-
|
|
132608
|
-
|
|
132628
|
+
if (prStatus.url && prStatus.state !== PrState.MERGED && prStatus.state !== PrState.CLOSED && prStatus.currentIssueMatch !== false) {
|
|
132629
|
+
reviewablePrStatus = prStatus;
|
|
132630
|
+
hasReviewableArtifact = true;
|
|
132631
|
+
}
|
|
132609
132632
|
} catch {
|
|
132610
132633
|
}
|
|
132611
132634
|
}
|
|
@@ -132708,6 +132731,78 @@ async function checkWorkerHealth(opts) {
|
|
|
132708
132731
|
fixes.push(fix);
|
|
132709
132732
|
continue;
|
|
132710
132733
|
}
|
|
132734
|
+
const quietMinutes = (() => {
|
|
132735
|
+
const lastObservableAt = sessionKey ? getLastObservableSessionActivityAt(sessionKey, sessions) : null;
|
|
132736
|
+
const referenceAt = lastObservableAt ?? agentAcceptedAt ?? dispatchRequestedAt ?? startedAtMs;
|
|
132737
|
+
if (!referenceAt || Number.isNaN(referenceAt)) return minutesActive;
|
|
132738
|
+
return (Date.now() - referenceAt) / 6e4;
|
|
132739
|
+
})();
|
|
132740
|
+
if (role === "developer" && issue2 && issueIdNum && hasReviewableArtifact && reviewablePrStatus?.url && minutesActive >= stallTimeoutMinutes && quietMinutes >= Math.max(8, Math.floor(stallTimeoutMinutes / 2))) {
|
|
132741
|
+
const fix = {
|
|
132742
|
+
issue: {
|
|
132743
|
+
type: "stalled_with_artifact",
|
|
132744
|
+
severity: "critical",
|
|
132745
|
+
project: project.name,
|
|
132746
|
+
projectSlug,
|
|
132747
|
+
role,
|
|
132748
|
+
level,
|
|
132749
|
+
sessionKey,
|
|
132750
|
+
issueId: slot.issueId,
|
|
132751
|
+
slotIndex,
|
|
132752
|
+
message: `${role.toUpperCase()} ${level}[${slotIndex}] has an open PR but stayed idle for ${Math.round(quietMinutes)}m without converging`
|
|
132753
|
+
},
|
|
132754
|
+
fixed: false
|
|
132755
|
+
};
|
|
132756
|
+
if (autoFix) {
|
|
132757
|
+
const channel = project.channels?.[0];
|
|
132758
|
+
await notify(
|
|
132759
|
+
{
|
|
132760
|
+
type: "workerRecoveryExhausted",
|
|
132761
|
+
project: project.name,
|
|
132762
|
+
issueId: issueIdNum,
|
|
132763
|
+
issueUrl: issue2.web_url,
|
|
132764
|
+
issueTitle: issue2.title,
|
|
132765
|
+
role,
|
|
132766
|
+
detail: `Open PR ${reviewablePrStatus.url} has stalled for ${Math.round(quietMinutes)} minutes without a trustworthy completion. Re-queueing to ${slotQueueLabel}.`,
|
|
132767
|
+
nextState: slotQueueLabel,
|
|
132768
|
+
dispatchCycleId: slot.dispatchCycleId ?? issueRuntime?.lastDispatchCycleId ?? null,
|
|
132769
|
+
dispatchRunId: slot.dispatchRunId ?? issueRuntime?.dispatchRunId ?? null
|
|
132770
|
+
},
|
|
132771
|
+
{
|
|
132772
|
+
workspaceDir,
|
|
132773
|
+
config: notificationConfig,
|
|
132774
|
+
target: channel ? {
|
|
132775
|
+
channelId: channel.channelId,
|
|
132776
|
+
channel: channel.channel,
|
|
132777
|
+
accountId: channel.accountId,
|
|
132778
|
+
messageThreadId: channel.messageThreadId
|
|
132779
|
+
} : void 0,
|
|
132780
|
+
runCommand
|
|
132781
|
+
}
|
|
132782
|
+
).catch(() => {
|
|
132783
|
+
});
|
|
132784
|
+
await revertLabel(fix, expectedLabel, slotQueueLabel);
|
|
132785
|
+
if (!fix.labelRevertFailed) {
|
|
132786
|
+
await deactivateSlot();
|
|
132787
|
+
await updateIssueRuntime(workspaceDir, projectSlug, issueIdNum, {
|
|
132788
|
+
inconclusiveCompletionAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
132789
|
+
inconclusiveCompletionReason: "stalled_with_artifact",
|
|
132790
|
+
progressNotifiedAt: null
|
|
132791
|
+
}).catch(() => {
|
|
132792
|
+
});
|
|
132793
|
+
fix.fixed = true;
|
|
132794
|
+
await auditHealthFixApplied(workspaceDir, fix, {
|
|
132795
|
+
action: "requeue_issue",
|
|
132796
|
+
fromLabel: expectedLabel,
|
|
132797
|
+
toLabel: slotQueueLabel,
|
|
132798
|
+
idleMinutes: Math.round(quietMinutes),
|
|
132799
|
+
deliveryState
|
|
132800
|
+
});
|
|
132801
|
+
}
|
|
132802
|
+
}
|
|
132803
|
+
fixes.push(fix);
|
|
132804
|
+
continue;
|
|
132805
|
+
}
|
|
132711
132806
|
if (hours > staleWorkerHours) {
|
|
132712
132807
|
const fix = {
|
|
132713
132808
|
issue: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mestreyoda/fabrica",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.34",
|
|
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",
|