@mestreyoda/fabrica 0.2.6 → 0.2.9
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/defaults/fabrica/prompts/reviewer.md +22 -13
- package/dist/index.js +69 -4
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
|
@@ -73,8 +73,7 @@ Do **not** treat the task envelope (`Repo:`, `Project:`, `Channel:`, branch hint
|
|
|
73
73
|
|
|
74
74
|
- Read the PR diff carefully
|
|
75
75
|
- Check the code against the review checklist
|
|
76
|
-
-
|
|
77
|
-
- Then call `work_finish`
|
|
76
|
+
- Submit your review using **one of the two methods below** (prefer `review_submit` if available)
|
|
78
77
|
|
|
79
78
|
## Conventions
|
|
80
79
|
|
|
@@ -92,21 +91,31 @@ If you discover unrelated bugs or needed improvements, call `task_create`:
|
|
|
92
91
|
|
|
93
92
|
## Completing Your Task
|
|
94
93
|
|
|
95
|
-
|
|
94
|
+
After writing your review, you **MUST** output your final decision on a dedicated line in **exactly** one of these two formats:
|
|
96
95
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
```
|
|
97
|
+
Review result: APPROVE
|
|
98
|
+
```
|
|
99
|
+
```
|
|
100
|
+
Review result: REJECT
|
|
101
|
+
```
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
The Fabrica orchestrator reads your session output and advances the pipeline automatically based on this line. **You do not need to call any tool or run any CLI command.** Just output the line above and your work is done.
|
|
102
104
|
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
- **Blocked:** `work_finish({ role: "reviewer", result: "blocked", channelId: "<project slug from 'Project:' field in task message>", summary: "<what you need>" })`
|
|
105
|
+
- Output `Review result: APPROVE` if all quality gates pass and the code is ready to proceed.
|
|
106
|
+
- Output `Review result: REJECT` if any blocking issue was found that the developer must fix.
|
|
106
107
|
|
|
107
|
-
> **IMPORTANT:** The
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
> **IMPORTANT:** The decision line must appear in your response text, not inside a code block. It is case-insensitive but must follow the `Review result: APPROVE/REJECT` format exactly.
|
|
109
|
+
|
|
110
|
+
### Optional: submit PR comment (best-effort)
|
|
111
|
+
|
|
112
|
+
If `gh` is available and the PR author is not the same GitHub account you are logged in as, you may optionally leave a PR comment for visibility:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
gh pr comment <PR_NUMBER> --repo <OWNER/REPO> --body "<summary of your findings>"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This is informational only — the orchestrator does not require it to advance the pipeline.
|
|
110
119
|
|
|
111
120
|
## Tools You Should NOT Use
|
|
112
121
|
|
package/dist/index.js
CHANGED
|
@@ -111330,8 +111330,8 @@ import fsSync from "node:fs";
|
|
|
111330
111330
|
import path5 from "node:path";
|
|
111331
111331
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
111332
111332
|
function getCurrentVersion() {
|
|
111333
|
-
if ("0.2.
|
|
111334
|
-
return "0.2.
|
|
111333
|
+
if ("0.2.9") {
|
|
111334
|
+
return "0.2.9";
|
|
111335
111335
|
}
|
|
111336
111336
|
try {
|
|
111337
111337
|
const pkgPath = path5.join(THIS_DIR, "..", "..", "package.json");
|
|
@@ -130791,7 +130791,7 @@ async function reviewPass(opts) {
|
|
|
130791
130791
|
const issues = await provider.listIssuesByLabel(state.label);
|
|
130792
130792
|
for (const issue2 of issues) {
|
|
130793
130793
|
const routing = detectStepRouting(issue2.labels, "review");
|
|
130794
|
-
if (routing !== "human") continue;
|
|
130794
|
+
if (routing !== "human" && routing !== "agent") continue;
|
|
130795
130795
|
const isManaged = await provider.issueHasReaction(issue2.iid, "eyes");
|
|
130796
130796
|
if (!isManaged) continue;
|
|
130797
130797
|
const status = await provider.getPrStatus(issue2.iid);
|
|
@@ -139562,6 +139562,36 @@ function registerReactiveDispatchHooks(api, ctx) {
|
|
|
139562
139562
|
|
|
139563
139563
|
// lib/dispatch/subagent-lifecycle-hook.ts
|
|
139564
139564
|
init_workflow();
|
|
139565
|
+
init_labels();
|
|
139566
|
+
async function parseReviewerSessionResult(ctx, sessionKey) {
|
|
139567
|
+
try {
|
|
139568
|
+
const messagesResult = await ctx.runtime.subagent?.getSessionMessages?.({ sessionKey });
|
|
139569
|
+
if (!messagesResult) return null;
|
|
139570
|
+
const messages = Array.isArray(messagesResult) ? messagesResult : Array.isArray(messagesResult?.messages) ? messagesResult.messages : [];
|
|
139571
|
+
const assistantTexts = messages.filter((m2) => m2.role === "assistant").map((m2) => {
|
|
139572
|
+
const raw = m2.content;
|
|
139573
|
+
if (typeof raw === "string") return raw;
|
|
139574
|
+
if (Array.isArray(raw)) {
|
|
139575
|
+
return raw.find((b) => b.type === "text")?.text ?? "";
|
|
139576
|
+
}
|
|
139577
|
+
return "";
|
|
139578
|
+
}).filter(Boolean).reverse();
|
|
139579
|
+
for (const text of assistantTexts) {
|
|
139580
|
+
const lower2 = text.toLowerCase();
|
|
139581
|
+
if (/review\s+result\s*:\s*approve/i.test(text)) return "approve";
|
|
139582
|
+
if (/review\s+result\s*:\s*reject/i.test(text)) return "reject";
|
|
139583
|
+
if (/\*\*approved\*\*/i.test(text)) return "approve";
|
|
139584
|
+
if (/\*\*rejected\*\*/i.test(text)) return "reject";
|
|
139585
|
+
const approveMatch = lower2.match(/\b(approve|approved|lgtm|looks good)\b/);
|
|
139586
|
+
const rejectMatch = lower2.match(/\b(reject|rejected|request[s]?\s+changes?|changes\s+requested)\b/);
|
|
139587
|
+
if (approveMatch && !rejectMatch) return "approve";
|
|
139588
|
+
if (rejectMatch && !approveMatch) return "reject";
|
|
139589
|
+
}
|
|
139590
|
+
return null;
|
|
139591
|
+
} catch {
|
|
139592
|
+
return null;
|
|
139593
|
+
}
|
|
139594
|
+
}
|
|
139565
139595
|
function registerSubagentLifecycleHook(api, ctx) {
|
|
139566
139596
|
const workspaceDir = resolveWorkspaceDir(ctx.config);
|
|
139567
139597
|
if (!workspaceDir) return;
|
|
@@ -139625,7 +139655,42 @@ function registerSubagentLifecycleHook(api, ctx) {
|
|
|
139625
139655
|
runCommand: ctx.runCommand
|
|
139626
139656
|
});
|
|
139627
139657
|
const issue2 = await provider.getIssue(Number(issueId));
|
|
139628
|
-
if (issue2.labels.includes(activeLabel)) {
|
|
139658
|
+
if (!issue2.labels.includes(activeLabel)) {
|
|
139659
|
+
} else if (role === "reviewer") {
|
|
139660
|
+
const reviewResult = await parseReviewerSessionResult(ctx, sessionKey);
|
|
139661
|
+
if (reviewResult === "approve" || reviewResult === "reject") {
|
|
139662
|
+
const reviewingState = findStateByLabel(config2.workflow, activeLabel);
|
|
139663
|
+
const eventKey = reviewResult === "approve" ? WorkflowEvent.APPROVED : WorkflowEvent.CHANGES_REQUESTED;
|
|
139664
|
+
const transition2 = reviewingState?.on?.[eventKey];
|
|
139665
|
+
const targetKey = typeof transition2 === "string" ? transition2 : transition2?.target;
|
|
139666
|
+
const targetState = targetKey ? config2.workflow.states[targetKey] : void 0;
|
|
139667
|
+
if (targetState) {
|
|
139668
|
+
await resilientLabelTransition(provider, Number(issueId), activeLabel, targetState.label);
|
|
139669
|
+
await log(workspaceDir, "reviewer_session_transition", {
|
|
139670
|
+
sessionKey,
|
|
139671
|
+
project: projectName,
|
|
139672
|
+
issueId,
|
|
139673
|
+
result: reviewResult,
|
|
139674
|
+
from: activeLabel,
|
|
139675
|
+
to: targetState.label
|
|
139676
|
+
}).catch(() => {
|
|
139677
|
+
});
|
|
139678
|
+
ctx.logger.info(
|
|
139679
|
+
`reviewer_session_transition: issue #${issueId} \u2192 ${targetState.label} (result=${reviewResult})`
|
|
139680
|
+
);
|
|
139681
|
+
} else {
|
|
139682
|
+
await provider.transitionLabel(Number(issueId), activeLabel, revertLabel);
|
|
139683
|
+
}
|
|
139684
|
+
} else {
|
|
139685
|
+
await provider.transitionLabel(Number(issueId), activeLabel, revertLabel);
|
|
139686
|
+
await log(workspaceDir, "reviewer_session_no_result", {
|
|
139687
|
+
sessionKey,
|
|
139688
|
+
project: projectName,
|
|
139689
|
+
issueId
|
|
139690
|
+
}).catch(() => {
|
|
139691
|
+
});
|
|
139692
|
+
}
|
|
139693
|
+
} else {
|
|
139629
139694
|
await provider.transitionLabel(Number(issueId), activeLabel, revertLabel);
|
|
139630
139695
|
}
|
|
139631
139696
|
} catch {
|