diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml
index abe3acbf2a..ddd7291d33 100644
--- a/.github/workflows/changeset.lock.yml
+++ b/.github/workflows/changeset.lock.yml
@@ -5261,6 +5261,7 @@ jobs:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const fs = require("fs");
+ const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
const isStaged = process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true";
const agentOutputFile = process.env.GH_AW_AGENT_OUTPUT || "";
@@ -5357,23 +5358,28 @@ jobs:
}
core.info("Found push-to-pull-request-branch item");
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Push to PR Branch Preview\n\n";
- summaryContent += "The following changes would be pushed if staged mode was disabled:\n\n";
- summaryContent += `**Target:** ${target}\n\n`;
- if (pushItem.commit_message) {
- summaryContent += `**Commit Message:** ${pushItem.commit_message}\n\n`;
- }
- if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
- const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
- if (patchStats.trim()) {
- summaryContent += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
- summaryContent += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
- } else {
- summaryContent += `**Changes:** No changes (empty patch)\n\n`;
- }
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Push to PR branch preview written to step summary");
+ await generateStagedPreview({
+ title: "Push to PR Branch",
+ description: "The following changes would be pushed if staged mode was disabled:",
+ items: [{ target, commit_message: pushItem.commit_message }],
+ renderItem: item => {
+ let content = "";
+ content += `**Target:** ${item.target}\n\n`;
+ if (item.commit_message) {
+ content += `**Commit Message:** ${item.commit_message}\n\n`;
+ }
+ if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
+ const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
+ if (patchStats.trim()) {
+ content += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
+ content += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
+ } else {
+ content += `**Changes:** No changes (empty patch)\n\n`;
+ }
+ }
+ return content;
+ },
+ });
return;
}
if (target !== "*" && target !== "triggering") {
diff --git a/.github/workflows/ci-doctor.lock.yml b/.github/workflows/ci-doctor.lock.yml
index 39ea272e3b..eccf146555 100644
--- a/.github/workflows/ci-doctor.lock.yml
+++ b/.github/workflows/ci-doctor.lock.yml
@@ -4177,6 +4177,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -4215,23 +4232,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/cli-version-checker.lock.yml b/.github/workflows/cli-version-checker.lock.yml
index ca339e2f09..a0745360fa 100644
--- a/.github/workflows/cli-version-checker.lock.yml
+++ b/.github/workflows/cli-version-checker.lock.yml
@@ -4197,6 +4197,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -4235,23 +4252,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/craft.lock.yml b/.github/workflows/craft.lock.yml
index a24858058b..eb4126e24d 100644
--- a/.github/workflows/craft.lock.yml
+++ b/.github/workflows/craft.lock.yml
@@ -5441,6 +5441,7 @@ jobs:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const fs = require("fs");
+ const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
const isStaged = process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true";
const agentOutputFile = process.env.GH_AW_AGENT_OUTPUT || "";
@@ -5537,23 +5538,28 @@ jobs:
}
core.info("Found push-to-pull-request-branch item");
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Push to PR Branch Preview\n\n";
- summaryContent += "The following changes would be pushed if staged mode was disabled:\n\n";
- summaryContent += `**Target:** ${target}\n\n`;
- if (pushItem.commit_message) {
- summaryContent += `**Commit Message:** ${pushItem.commit_message}\n\n`;
- }
- if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
- const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
- if (patchStats.trim()) {
- summaryContent += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
- summaryContent += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
- } else {
- summaryContent += `**Changes:** No changes (empty patch)\n\n`;
- }
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Push to PR branch preview written to step summary");
+ await generateStagedPreview({
+ title: "Push to PR Branch",
+ description: "The following changes would be pushed if staged mode was disabled:",
+ items: [{ target, commit_message: pushItem.commit_message }],
+ renderItem: item => {
+ let content = "";
+ content += `**Target:** ${item.target}\n\n`;
+ if (item.commit_message) {
+ content += `**Commit Message:** ${item.commit_message}\n\n`;
+ }
+ if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
+ const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
+ if (patchStats.trim()) {
+ content += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
+ content += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
+ } else {
+ content += `**Changes:** No changes (empty patch)\n\n`;
+ }
+ }
+ return content;
+ },
+ });
return;
}
if (target !== "*" && target !== "triggering") {
diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml
index 815891a33a..c06128216e 100644
--- a/.github/workflows/dev.lock.yml
+++ b/.github/workflows/dev.lock.yml
@@ -4344,6 +4344,7 @@ jobs:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const fs = require("fs");
+ const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
const isStaged = process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true";
const agentOutputFile = process.env.GH_AW_AGENT_OUTPUT || "";
@@ -4440,23 +4441,28 @@ jobs:
}
core.info("Found push-to-pull-request-branch item");
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Push to PR Branch Preview\n\n";
- summaryContent += "The following changes would be pushed if staged mode was disabled:\n\n";
- summaryContent += `**Target:** ${target}\n\n`;
- if (pushItem.commit_message) {
- summaryContent += `**Commit Message:** ${pushItem.commit_message}\n\n`;
- }
- if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
- const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
- if (patchStats.trim()) {
- summaryContent += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
- summaryContent += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
- } else {
- summaryContent += `**Changes:** No changes (empty patch)\n\n`;
- }
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Push to PR branch preview written to step summary");
+ await generateStagedPreview({
+ title: "Push to PR Branch",
+ description: "The following changes would be pushed if staged mode was disabled:",
+ items: [{ target, commit_message: pushItem.commit_message }],
+ renderItem: item => {
+ let content = "";
+ content += `**Target:** ${item.target}\n\n`;
+ if (item.commit_message) {
+ content += `**Commit Message:** ${item.commit_message}\n\n`;
+ }
+ if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
+ const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
+ if (patchStats.trim()) {
+ content += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
+ content += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
+ } else {
+ content += `**Changes:** No changes (empty patch)\n\n`;
+ }
+ }
+ return content;
+ },
+ });
return;
}
if (target !== "*" && target !== "triggering") {
diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml
index b2a9caccf3..01aacb158a 100644
--- a/.github/workflows/duplicate-code-detector.lock.yml
+++ b/.github/workflows/duplicate-code-detector.lock.yml
@@ -3170,6 +3170,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -3208,23 +3225,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/go-pattern-detector.lock.yml b/.github/workflows/go-pattern-detector.lock.yml
index 8c5ed06a90..953f8de981 100644
--- a/.github/workflows/go-pattern-detector.lock.yml
+++ b/.github/workflows/go-pattern-detector.lock.yml
@@ -3407,6 +3407,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -3445,23 +3462,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml
index 392dafe6af..6130da071e 100644
--- a/.github/workflows/issue-classifier.lock.yml
+++ b/.github/workflows/issue-classifier.lock.yml
@@ -806,6 +806,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
async function main() {
const result = loadAgentOutput();
if (!result.success) {
@@ -818,18 +835,23 @@ jobs:
}
core.info(`Found add-labels item with ${labelsItem.labels.length} labels`);
if (process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true") {
- let summaryContent = "## 🎭 Staged Mode: Add Labels Preview\n\n";
- summaryContent += "The following labels would be added if staged mode was disabled:\n\n";
- if (labelsItem.item_number) {
- summaryContent += `**Target Issue:** #${labelsItem.item_number}\n\n`;
- } else {
- summaryContent += `**Target:** Current issue/PR\n\n`;
- }
- if (labelsItem.labels && labelsItem.labels.length > 0) {
- summaryContent += `**Labels to add:** ${labelsItem.labels.join(", ")}\n\n`;
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Label addition preview written to step summary");
+ await generateStagedPreview({
+ title: "Add Labels",
+ description: "The following labels would be added if staged mode was disabled:",
+ items: [labelsItem],
+ renderItem: item => {
+ let content = "";
+ if (item.item_number) {
+ content += `**Target Issue:** #${item.item_number}\n\n`;
+ } else {
+ content += `**Target:** Current issue/PR\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels to add:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const allowedLabelsEnv = process.env.GH_AW_LABELS_ALLOWED?.trim();
diff --git a/.github/workflows/mergefest.lock.yml b/.github/workflows/mergefest.lock.yml
index 19e1a99481..bd99c268e7 100644
--- a/.github/workflows/mergefest.lock.yml
+++ b/.github/workflows/mergefest.lock.yml
@@ -4876,6 +4876,7 @@ jobs:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const fs = require("fs");
+ const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
const isStaged = process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true";
const agentOutputFile = process.env.GH_AW_AGENT_OUTPUT || "";
@@ -4972,23 +4973,28 @@ jobs:
}
core.info("Found push-to-pull-request-branch item");
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Push to PR Branch Preview\n\n";
- summaryContent += "The following changes would be pushed if staged mode was disabled:\n\n";
- summaryContent += `**Target:** ${target}\n\n`;
- if (pushItem.commit_message) {
- summaryContent += `**Commit Message:** ${pushItem.commit_message}\n\n`;
- }
- if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
- const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
- if (patchStats.trim()) {
- summaryContent += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
- summaryContent += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
- } else {
- summaryContent += `**Changes:** No changes (empty patch)\n\n`;
- }
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Push to PR branch preview written to step summary");
+ await generateStagedPreview({
+ title: "Push to PR Branch",
+ description: "The following changes would be pushed if staged mode was disabled:",
+ items: [{ target, commit_message: pushItem.commit_message }],
+ renderItem: item => {
+ let content = "";
+ content += `**Target:** ${item.target}\n\n`;
+ if (item.commit_message) {
+ content += `**Commit Message:** ${item.commit_message}\n\n`;
+ }
+ if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
+ const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
+ if (patchStats.trim()) {
+ content += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
+ content += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
+ } else {
+ content += `**Changes:** No changes (empty patch)\n\n`;
+ }
+ }
+ return content;
+ },
+ });
return;
}
if (target !== "*" && target !== "triggering") {
diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml
index cbbb82baf8..10c1471c0e 100644
--- a/.github/workflows/plan.lock.yml
+++ b/.github/workflows/plan.lock.yml
@@ -4268,6 +4268,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -4306,23 +4323,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml
index cf1f8be0f5..1f5cb9f521 100644
--- a/.github/workflows/poem-bot.lock.yml
+++ b/.github/workflows/poem-bot.lock.yml
@@ -1256,6 +1256,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
async function main() {
const result = loadAgentOutput();
if (!result.success) {
@@ -1268,18 +1285,23 @@ jobs:
}
core.info(`Found add-labels item with ${labelsItem.labels.length} labels`);
if (process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true") {
- let summaryContent = "## 🎭 Staged Mode: Add Labels Preview\n\n";
- summaryContent += "The following labels would be added if staged mode was disabled:\n\n";
- if (labelsItem.item_number) {
- summaryContent += `**Target Issue:** #${labelsItem.item_number}\n\n`;
- } else {
- summaryContent += `**Target:** Current issue/PR\n\n`;
- }
- if (labelsItem.labels && labelsItem.labels.length > 0) {
- summaryContent += `**Labels to add:** ${labelsItem.labels.join(", ")}\n\n`;
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Label addition preview written to step summary");
+ await generateStagedPreview({
+ title: "Add Labels",
+ description: "The following labels would be added if staged mode was disabled:",
+ items: [labelsItem],
+ renderItem: item => {
+ let content = "";
+ if (item.item_number) {
+ content += `**Target Issue:** #${item.item_number}\n\n`;
+ } else {
+ content += `**Target:** Current issue/PR\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels to add:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const allowedLabelsEnv = process.env.GH_AW_LABELS_ALLOWED?.trim();
@@ -5162,6 +5184,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -5200,23 +5239,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
@@ -5475,6 +5513,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -5523,29 +5578,29 @@ jobs:
}
core.info(`Found ${reviewCommentItems.length} create-pull-request-review-comment item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create PR Review Comments Preview\n\n";
- summaryContent += "The following review comments would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < reviewCommentItems.length; i++) {
- const item = reviewCommentItems[i];
- summaryContent += `### Review Comment ${i + 1}\n`;
- if (item.pull_request_number) {
- const repoUrl = getRepositoryUrl();
- const pullUrl = `${repoUrl}/pull/${item.pull_request_number}`;
- summaryContent += `**Target PR:** [#${item.pull_request_number}](${pullUrl})\n\n`;
- } else {
- summaryContent += `**Target:** Current PR\n\n`;
- }
- summaryContent += `**File:** ${item.path || "No path provided"}\n\n`;
- summaryContent += `**Line:** ${item.line || "No line provided"}\n\n`;
- if (item.start_line) {
- summaryContent += `**Start Line:** ${item.start_line}\n\n`;
- }
- summaryContent += `**Side:** ${item.side || "RIGHT"}\n\n`;
- summaryContent += `**Body:**\n${item.body || "No content provided"}\n\n`;
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 PR review comment creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create PR Review Comments",
+ description: "The following review comments would be created if staged mode was disabled:",
+ items: reviewCommentItems,
+ renderItem: (item, index) => {
+ let content = `### Review Comment ${index + 1}\n`;
+ if (item.pull_request_number) {
+ const repoUrl = getRepositoryUrl();
+ const pullUrl = `${repoUrl}/pull/${item.pull_request_number}`;
+ content += `**Target PR:** [#${item.pull_request_number}](${pullUrl})\n\n`;
+ } else {
+ content += `**Target:** Current PR\n\n`;
+ }
+ content += `**File:** ${item.path || "No path provided"}\n\n`;
+ content += `**Line:** ${item.line || "No line provided"}\n\n`;
+ if (item.start_line) {
+ content += `**Start Line:** ${item.start_line}\n\n`;
+ }
+ content += `**Side:** ${item.side || "RIGHT"}\n\n`;
+ content += `**Body:**\n${item.body || "No content provided"}\n\n`;
+ return content;
+ },
+ });
return;
}
const defaultSide = process.env.GH_AW_PR_REVIEW_COMMENT_SIDE || "RIGHT";
@@ -6801,6 +6856,7 @@ jobs:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const fs = require("fs");
+ const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
const isStaged = process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true";
const agentOutputFile = process.env.GH_AW_AGENT_OUTPUT || "";
@@ -6897,23 +6953,28 @@ jobs:
}
core.info("Found push-to-pull-request-branch item");
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Push to PR Branch Preview\n\n";
- summaryContent += "The following changes would be pushed if staged mode was disabled:\n\n";
- summaryContent += `**Target:** ${target}\n\n`;
- if (pushItem.commit_message) {
- summaryContent += `**Commit Message:** ${pushItem.commit_message}\n\n`;
- }
- if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
- const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
- if (patchStats.trim()) {
- summaryContent += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
- summaryContent += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
- } else {
- summaryContent += `**Changes:** No changes (empty patch)\n\n`;
- }
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Push to PR branch preview written to step summary");
+ await generateStagedPreview({
+ title: "Push to PR Branch",
+ description: "The following changes would be pushed if staged mode was disabled:",
+ items: [{ target, commit_message: pushItem.commit_message }],
+ renderItem: item => {
+ let content = "";
+ content += `**Target:** ${item.target}\n\n`;
+ if (item.commit_message) {
+ content += `**Commit Message:** ${item.commit_message}\n\n`;
+ }
+ if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
+ const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
+ if (patchStats.trim()) {
+ content += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
+ content += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
+ } else {
+ content += `**Changes:** No changes (empty patch)\n\n`;
+ }
+ }
+ return content;
+ },
+ });
return;
}
if (target !== "*" && target !== "triggering") {
@@ -7178,6 +7239,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
async function main() {
const isStaged = process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true";
const result = loadAgentOutput();
@@ -7191,29 +7269,29 @@ jobs:
}
core.info(`Found ${updateItems.length} update-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Update Issues Preview\n\n";
- summaryContent += "The following issue updates would be applied if staged mode was disabled:\n\n";
- for (let i = 0; i < updateItems.length; i++) {
- const item = updateItems[i];
- summaryContent += `### Issue Update ${i + 1}\n`;
- if (item.issue_number) {
- summaryContent += `**Target Issue:** #${item.issue_number}\n\n`;
- } else {
- summaryContent += `**Target:** Current issue\n\n`;
- }
- if (item.title !== undefined) {
- summaryContent += `**New Title:** ${item.title}\n\n`;
- }
- if (item.body !== undefined) {
- summaryContent += `**New Body:**\n${item.body}\n\n`;
- }
- if (item.status !== undefined) {
- summaryContent += `**New Status:** ${item.status}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Issue update preview written to step summary");
+ await generateStagedPreview({
+ title: "Update Issues",
+ description: "The following issue updates would be applied if staged mode was disabled:",
+ items: updateItems,
+ renderItem: (item, index) => {
+ let content = `### Issue Update ${index + 1}\n`;
+ if (item.issue_number) {
+ content += `**Target Issue:** #${item.issue_number}\n\n`;
+ } else {
+ content += `**Target:** Current issue\n\n`;
+ }
+ if (item.title !== undefined) {
+ content += `**New Title:** ${item.title}\n\n`;
+ }
+ if (item.body !== undefined) {
+ content += `**New Body:**\n${item.body}\n\n`;
+ }
+ if (item.status !== undefined) {
+ content += `**New Status:** ${item.status}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const updateTarget = process.env.GH_AW_UPDATE_TARGET || "triggering";
diff --git a/.github/workflows/semantic-function-refactor.lock.yml b/.github/workflows/semantic-function-refactor.lock.yml
index 4d1ccbf1b8..623f28730d 100644
--- a/.github/workflows/semantic-function-refactor.lock.yml
+++ b/.github/workflows/semantic-function-refactor.lock.yml
@@ -3811,6 +3811,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -3849,23 +3866,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml
index b845fce813..d11feed74d 100644
--- a/.github/workflows/smoke-claude.lock.yml
+++ b/.github/workflows/smoke-claude.lock.yml
@@ -3257,6 +3257,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -3295,23 +3312,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml
index dab018436e..a23985b834 100644
--- a/.github/workflows/smoke-codex.lock.yml
+++ b/.github/workflows/smoke-codex.lock.yml
@@ -2910,6 +2910,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -2948,23 +2965,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml
index 5664b8af4a..e9022f2c5d 100644
--- a/.github/workflows/smoke-copilot.lock.yml
+++ b/.github/workflows/smoke-copilot.lock.yml
@@ -3962,6 +3962,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -4000,23 +4017,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/smoke-detector.lock.yml b/.github/workflows/smoke-detector.lock.yml
index 3c9fd4e62d..3428dd7678 100644
--- a/.github/workflows/smoke-detector.lock.yml
+++ b/.github/workflows/smoke-detector.lock.yml
@@ -4430,6 +4430,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -4468,23 +4485,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/test-ollama-threat-detection.lock.yml b/.github/workflows/test-ollama-threat-detection.lock.yml
index d5dfeef9e4..d7b7aaaae4 100644
--- a/.github/workflows/test-ollama-threat-detection.lock.yml
+++ b/.github/workflows/test-ollama-threat-detection.lock.yml
@@ -3538,6 +3538,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -3576,23 +3593,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml
index e498159852..8c33254ce8 100644
--- a/.github/workflows/tidy.lock.yml
+++ b/.github/workflows/tidy.lock.yml
@@ -5194,6 +5194,7 @@ jobs:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const fs = require("fs");
+ const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
const isStaged = process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true";
const agentOutputFile = process.env.GH_AW_AGENT_OUTPUT || "";
@@ -5290,23 +5291,28 @@ jobs:
}
core.info("Found push-to-pull-request-branch item");
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Push to PR Branch Preview\n\n";
- summaryContent += "The following changes would be pushed if staged mode was disabled:\n\n";
- summaryContent += `**Target:** ${target}\n\n`;
- if (pushItem.commit_message) {
- summaryContent += `**Commit Message:** ${pushItem.commit_message}\n\n`;
- }
- if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
- const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
- if (patchStats.trim()) {
- summaryContent += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
- summaryContent += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
- } else {
- summaryContent += `**Changes:** No changes (empty patch)\n\n`;
- }
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Push to PR branch preview written to step summary");
+ await generateStagedPreview({
+ title: "Push to PR Branch",
+ description: "The following changes would be pushed if staged mode was disabled:",
+ items: [{ target, commit_message: pushItem.commit_message }],
+ renderItem: item => {
+ let content = "";
+ content += `**Target:** ${item.target}\n\n`;
+ if (item.commit_message) {
+ content += `**Commit Message:** ${item.commit_message}\n\n`;
+ }
+ if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
+ const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
+ if (patchStats.trim()) {
+ content += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
+ content += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
+ } else {
+ content += `**Changes:** No changes (empty patch)\n\n`;
+ }
+ }
+ return content;
+ },
+ });
return;
}
if (target !== "*" && target !== "triggering") {
diff --git a/.github/workflows/video-analyzer.lock.yml b/.github/workflows/video-analyzer.lock.yml
index a37d1cecc4..424f38583f 100644
--- a/.github/workflows/video-analyzer.lock.yml
+++ b/.github/workflows/video-analyzer.lock.yml
@@ -3829,6 +3829,23 @@ jobs:
}
return { success: true, items: validatedOutput.items };
}
+ async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
function generateFooter(
workflowName,
runUrl,
@@ -3867,23 +3884,22 @@ jobs:
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/pkg/workflow/js.go b/pkg/workflow/js.go
index a680762dc1..ca436c1d3c 100644
--- a/pkg/workflow/js.go
+++ b/pkg/workflow/js.go
@@ -80,6 +80,9 @@ var sanitizeWorkflowNameScript string
//go:embed js/load_agent_output.cjs
var loadAgentOutputScript string
+//go:embed js/staged_preview.cjs
+var stagedPreviewScript string
+
// Source scripts that may contain local requires
//
//go:embed js/collect_ndjson_output.cjs
@@ -360,6 +363,7 @@ func GetJavaScriptSources() map[string]string {
"sanitize_label_content.cjs": sanitizeLabelContentScript,
"sanitize_workflow_name.cjs": sanitizeWorkflowNameScript,
"load_agent_output.cjs": loadAgentOutputScript,
+ "staged_preview.cjs": stagedPreviewScript,
}
}
diff --git a/pkg/workflow/js/add_labels.cjs b/pkg/workflow/js/add_labels.cjs
index 0eb5f91b52..96b6e53317 100644
--- a/pkg/workflow/js/add_labels.cjs
+++ b/pkg/workflow/js/add_labels.cjs
@@ -3,6 +3,7 @@
const { sanitizeLabelContent } = require("./sanitize_label_content.cjs");
const { loadAgentOutput } = require("./load_agent_output.cjs");
+const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
const result = loadAgentOutput();
@@ -17,18 +18,23 @@ async function main() {
}
core.info(`Found add-labels item with ${labelsItem.labels.length} labels`);
if (process.env.GH_AW_SAFE_OUTPUTS_STAGED === "true") {
- let summaryContent = "## 🎭 Staged Mode: Add Labels Preview\n\n";
- summaryContent += "The following labels would be added if staged mode was disabled:\n\n";
- if (labelsItem.item_number) {
- summaryContent += `**Target Issue:** #${labelsItem.item_number}\n\n`;
- } else {
- summaryContent += `**Target:** Current issue/PR\n\n`;
- }
- if (labelsItem.labels && labelsItem.labels.length > 0) {
- summaryContent += `**Labels to add:** ${labelsItem.labels.join(", ")}\n\n`;
- }
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Label addition preview written to step summary");
+ await generateStagedPreview({
+ title: "Add Labels",
+ description: "The following labels would be added if staged mode was disabled:",
+ items: [labelsItem],
+ renderItem: item => {
+ let content = "";
+ if (item.item_number) {
+ content += `**Target Issue:** #${item.item_number}\n\n`;
+ } else {
+ content += `**Target:** Current issue/PR\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels to add:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const allowedLabelsEnv = process.env.GH_AW_LABELS_ALLOWED?.trim();
diff --git a/pkg/workflow/js/create_issue.cjs b/pkg/workflow/js/create_issue.cjs
index c5c8b060f2..b087d0d2a2 100644
--- a/pkg/workflow/js/create_issue.cjs
+++ b/pkg/workflow/js/create_issue.cjs
@@ -3,6 +3,7 @@
const { sanitizeLabelContent } = require("./sanitize_label_content.cjs");
const { loadAgentOutput } = require("./load_agent_output.cjs");
+const { generateStagedPreview } = require("./staged_preview.cjs");
/**
* Generate footer with AI attribution and workflow installation instructions
@@ -62,23 +63,22 @@ async function main() {
}
core.info(`Found ${createIssueItems.length} create-issue item(s)`);
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create Issues Preview\n\n";
- summaryContent += "The following issues would be created if staged mode was disabled:\n\n";
- for (let i = 0; i < createIssueItems.length; i++) {
- const item = createIssueItems[i];
- summaryContent += `### Issue ${i + 1}\n`;
- summaryContent += `**Title:** ${item.title || "No title provided"}\n\n`;
- if (item.body) {
- summaryContent += `**Body:**\n${item.body}\n\n`;
- }
- if (item.labels && item.labels.length > 0) {
- summaryContent += `**Labels:** ${item.labels.join(", ")}\n\n`;
- }
- summaryContent += "---\n\n";
- }
- await core.summary.addRaw(summaryContent).write();
- core.info(summaryContent);
- core.info("📝 Issue creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: createIssueItems,
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}
const parentIssueNumber = context.payload?.issue?.number;
diff --git a/pkg/workflow/js/create_issue.test.cjs b/pkg/workflow/js/create_issue.test.cjs
index 581c049110..761f751262 100644
--- a/pkg/workflow/js/create_issue.test.cjs
+++ b/pkg/workflow/js/create_issue.test.cjs
@@ -765,7 +765,7 @@ describe("create_issue.cjs", () => {
expect(infoCall[0]).toContain("**Labels:** bug, enhancement");
// Should also log the completion message
- expect(mockCore.info).toHaveBeenCalledWith("📝 Issue creation preview written to step summary");
+ expect(mockCore.info).toHaveBeenCalledWith("📝 Create Issues preview written to step summary");
// Clean up
delete process.env.GH_AW_SAFE_OUTPUTS_STAGED;
diff --git a/pkg/workflow/js/create_pr_review_comment.cjs b/pkg/workflow/js/create_pr_review_comment.cjs
index d3719650de..54854677ba 100644
--- a/pkg/workflow/js/create_pr_review_comment.cjs
+++ b/pkg/workflow/js/create_pr_review_comment.cjs
@@ -2,6 +2,7 @@
///
const { loadAgentOutput } = require("./load_agent_output.cjs");
+const { generateStagedPreview } = require("./staged_preview.cjs");
/**
* Generate footer with AI attribution and workflow installation instructions
@@ -81,32 +82,29 @@ async function main() {
// If in staged mode, emit step summary instead of creating review comments
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Create PR Review Comments Preview\n\n";
- summaryContent += "The following review comments would be created if staged mode was disabled:\n\n";
-
- for (let i = 0; i < reviewCommentItems.length; i++) {
- const item = reviewCommentItems[i];
- summaryContent += `### Review Comment ${i + 1}\n`;
- if (item.pull_request_number) {
- const repoUrl = getRepositoryUrl();
- const pullUrl = `${repoUrl}/pull/${item.pull_request_number}`;
- summaryContent += `**Target PR:** [#${item.pull_request_number}](${pullUrl})\n\n`;
- } else {
- summaryContent += `**Target:** Current PR\n\n`;
- }
- summaryContent += `**File:** ${item.path || "No path provided"}\n\n`;
- summaryContent += `**Line:** ${item.line || "No line provided"}\n\n`;
- if (item.start_line) {
- summaryContent += `**Start Line:** ${item.start_line}\n\n`;
- }
- summaryContent += `**Side:** ${item.side || "RIGHT"}\n\n`;
- summaryContent += `**Body:**\n${item.body || "No content provided"}\n\n`;
- summaryContent += "---\n\n";
- }
-
- // Write to step summary
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 PR review comment creation preview written to step summary");
+ await generateStagedPreview({
+ title: "Create PR Review Comments",
+ description: "The following review comments would be created if staged mode was disabled:",
+ items: reviewCommentItems,
+ renderItem: (item, index) => {
+ let content = `### Review Comment ${index + 1}\n`;
+ if (item.pull_request_number) {
+ const repoUrl = getRepositoryUrl();
+ const pullUrl = `${repoUrl}/pull/${item.pull_request_number}`;
+ content += `**Target PR:** [#${item.pull_request_number}](${pullUrl})\n\n`;
+ } else {
+ content += `**Target:** Current PR\n\n`;
+ }
+ content += `**File:** ${item.path || "No path provided"}\n\n`;
+ content += `**Line:** ${item.line || "No line provided"}\n\n`;
+ if (item.start_line) {
+ content += `**Start Line:** ${item.start_line}\n\n`;
+ }
+ content += `**Side:** ${item.side || "RIGHT"}\n\n`;
+ content += `**Body:**\n${item.body || "No content provided"}\n\n`;
+ return content;
+ },
+ });
return;
}
diff --git a/pkg/workflow/js/push_to_pull_request_branch.cjs b/pkg/workflow/js/push_to_pull_request_branch.cjs
index ce29382daa..660377e614 100644
--- a/pkg/workflow/js/push_to_pull_request_branch.cjs
+++ b/pkg/workflow/js/push_to_pull_request_branch.cjs
@@ -3,6 +3,7 @@
/** @type {typeof import("fs")} */
const fs = require("fs");
+const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
// Check if we're in staged mode
@@ -138,28 +139,30 @@ async function main() {
// If in staged mode, emit step summary instead of pushing changes
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Push to PR Branch Preview\n\n";
- summaryContent += "The following changes would be pushed if staged mode was disabled:\n\n";
-
- summaryContent += `**Target:** ${target}\n\n`;
-
- if (pushItem.commit_message) {
- summaryContent += `**Commit Message:** ${pushItem.commit_message}\n\n`;
- }
-
- if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
- const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
- if (patchStats.trim()) {
- summaryContent += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
- summaryContent += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
- } else {
- summaryContent += `**Changes:** No changes (empty patch)\n\n`;
- }
- }
-
- // Write to step summary
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Push to PR branch preview written to step summary");
+ await generateStagedPreview({
+ title: "Push to PR Branch",
+ description: "The following changes would be pushed if staged mode was disabled:",
+ items: [{ target, commit_message: pushItem.commit_message }],
+ renderItem: item => {
+ let content = "";
+ content += `**Target:** ${item.target}\n\n`;
+
+ if (item.commit_message) {
+ content += `**Commit Message:** ${item.commit_message}\n\n`;
+ }
+
+ if (fs.existsSync("/tmp/gh-aw/aw.patch")) {
+ const patchStats = fs.readFileSync("/tmp/gh-aw/aw.patch", "utf8");
+ if (patchStats.trim()) {
+ content += `**Changes:** Patch file exists with ${patchStats.split("\n").length} lines\n\n`;
+ content += `Show patch preview
\n\n\`\`\`diff\n${patchStats.slice(0, 2000)}${patchStats.length > 2000 ? "\n... (truncated)" : ""}\n\`\`\`\n\n \n\n`;
+ } else {
+ content += `**Changes:** No changes (empty patch)\n\n`;
+ }
+ }
+ return content;
+ },
+ });
return;
}
diff --git a/pkg/workflow/js/staged_preview.cjs b/pkg/workflow/js/staged_preview.cjs
new file mode 100644
index 0000000000..8097800ac3
--- /dev/null
+++ b/pkg/workflow/js/staged_preview.cjs
@@ -0,0 +1,35 @@
+// @ts-check
+///
+
+/**
+ * Generate a staged mode preview summary and write it to the step summary.
+ *
+ * @param {Object} options - Configuration options for the preview
+ * @param {string} options.title - The main title for the preview (e.g., "Create Issues")
+ * @param {string} options.description - Description of what would happen if staged mode was disabled
+ * @param {Array} options.items - Array of items to preview
+ * @param {(item: any, index: number) => string} options.renderItem - Function to render each item as markdown
+ * @returns {Promise}
+ */
+async function generateStagedPreview(options) {
+ const { title, description, items, renderItem } = options;
+
+ let summaryContent = `## 🎭 Staged Mode: ${title} Preview\n\n`;
+ summaryContent += `${description}\n\n`;
+
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i];
+ summaryContent += renderItem(item, i);
+ summaryContent += "---\n\n";
+ }
+
+ try {
+ await core.summary.addRaw(summaryContent).write();
+ core.info(summaryContent);
+ core.info(`📝 ${title} preview written to step summary`);
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+}
+
+module.exports = { generateStagedPreview };
diff --git a/pkg/workflow/js/staged_preview.test.cjs b/pkg/workflow/js/staged_preview.test.cjs
new file mode 100644
index 0000000000..3e8ce4d836
--- /dev/null
+++ b/pkg/workflow/js/staged_preview.test.cjs
@@ -0,0 +1,306 @@
+import { describe, it, expect, beforeEach, vi } from "vitest";
+
+// Mock the global objects that GitHub Actions provides
+const mockCore = {
+ info: vi.fn(),
+ summary: {
+ addRaw: vi.fn().mockReturnThis(),
+ write: vi.fn().mockResolvedValue(),
+ },
+};
+
+// Set up global mocks before importing the module
+globalThis.core = mockCore;
+
+const { generateStagedPreview } = await import("./staged_preview.cjs");
+
+describe("staged_preview.cjs", () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ });
+
+ describe("generateStagedPreview", () => {
+ it("should generate preview with single item", async () => {
+ const options = {
+ title: "Create Issues",
+ description: "The following issues would be created if staged mode was disabled:",
+ items: [
+ {
+ title: "Test Issue",
+ body: "Test body",
+ labels: ["bug", "enhancement"],
+ },
+ ],
+ renderItem: (item, index) => {
+ let content = `### Issue ${index + 1}\n`;
+ content += `**Title:** ${item.title || "No title provided"}\n\n`;
+ if (item.body) {
+ content += `**Body:**\n${item.body}\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ };
+
+ await generateStagedPreview(options);
+
+ expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
+ expect(mockCore.summary.write).toHaveBeenCalledTimes(1);
+
+ const summaryContent = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(summaryContent).toContain("## 🎭 Staged Mode: Create Issues Preview");
+ expect(summaryContent).toContain("The following issues would be created if staged mode was disabled:");
+ expect(summaryContent).toContain("### Issue 1");
+ expect(summaryContent).toContain("**Title:** Test Issue");
+ expect(summaryContent).toContain("**Body:**\nTest body");
+ expect(summaryContent).toContain("**Labels:** bug, enhancement");
+ expect(summaryContent).toContain("---");
+
+ // Verify that summary content is logged to core.info
+ expect(mockCore.info).toHaveBeenCalledWith(summaryContent);
+ expect(mockCore.info).toHaveBeenCalledWith("📝 Create Issues preview written to step summary");
+ });
+
+ it("should generate preview with multiple items", async () => {
+ const options = {
+ title: "Update Issues",
+ description: "The following issue updates would be applied if staged mode was disabled:",
+ items: [
+ { issue_number: 1, title: "New Title 1", status: "open" },
+ { issue_number: 2, title: "New Title 2", status: "closed" },
+ { issue_number: 3, body: "New Body 3" },
+ ],
+ renderItem: (item, index) => {
+ let content = `### Issue Update ${index + 1}\n`;
+ if (item.issue_number) {
+ content += `**Target Issue:** #${item.issue_number}\n\n`;
+ }
+ if (item.title !== undefined) {
+ content += `**New Title:** ${item.title}\n\n`;
+ }
+ if (item.body !== undefined) {
+ content += `**New Body:**\n${item.body}\n\n`;
+ }
+ if (item.status !== undefined) {
+ content += `**New Status:** ${item.status}\n\n`;
+ }
+ return content;
+ },
+ };
+
+ await generateStagedPreview(options);
+
+ const summaryContent = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(summaryContent).toContain("## 🎭 Staged Mode: Update Issues Preview");
+ expect(summaryContent).toContain("### Issue Update 1");
+ expect(summaryContent).toContain("**Target Issue:** #1");
+ expect(summaryContent).toContain("**New Title:** New Title 1");
+ expect(summaryContent).toContain("**New Status:** open");
+ expect(summaryContent).toContain("### Issue Update 2");
+ expect(summaryContent).toContain("**Target Issue:** #2");
+ expect(summaryContent).toContain("**New Status:** closed");
+ expect(summaryContent).toContain("### Issue Update 3");
+ expect(summaryContent).toContain("**New Body:**\nNew Body 3");
+
+ // Check that all items are separated by dividers
+ const dividerCount = (summaryContent.match(/---/g) || []).length;
+ expect(dividerCount).toBe(3);
+ });
+
+ it("should handle add labels preview", async () => {
+ const options = {
+ title: "Add Labels",
+ description: "The following labels would be added if staged mode was disabled:",
+ items: [
+ {
+ item_number: 42,
+ labels: ["bug", "enhancement", "good first issue"],
+ },
+ ],
+ renderItem: item => {
+ let content = "";
+ if (item.item_number) {
+ content += `**Target Issue:** #${item.item_number}\n\n`;
+ } else {
+ content += `**Target:** Current issue/PR\n\n`;
+ }
+ if (item.labels && item.labels.length > 0) {
+ content += `**Labels to add:** ${item.labels.join(", ")}\n\n`;
+ }
+ return content;
+ },
+ };
+
+ await generateStagedPreview(options);
+
+ const summaryContent = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(summaryContent).toContain("## 🎭 Staged Mode: Add Labels Preview");
+ expect(summaryContent).toContain("**Target Issue:** #42");
+ expect(summaryContent).toContain("**Labels to add:** bug, enhancement, good first issue");
+ });
+
+ it("should handle PR review comments preview", async () => {
+ const options = {
+ title: "Create PR Review Comments",
+ description: "The following review comments would be created if staged mode was disabled:",
+ items: [
+ {
+ pull_request_number: 123,
+ path: "src/main.js",
+ line: 42,
+ start_line: 40,
+ side: "RIGHT",
+ body: "This needs improvement",
+ },
+ {
+ path: "src/utils.js",
+ line: 10,
+ side: "LEFT",
+ body: "Consider refactoring",
+ },
+ ],
+ renderItem: (item, index) => {
+ const getRepositoryUrl = () => "https://github.com/test/repo";
+ let content = `### Review Comment ${index + 1}\n`;
+ if (item.pull_request_number) {
+ const repoUrl = getRepositoryUrl();
+ const pullUrl = `${repoUrl}/pull/${item.pull_request_number}`;
+ content += `**Target PR:** [#${item.pull_request_number}](${pullUrl})\n\n`;
+ } else {
+ content += `**Target:** Current PR\n\n`;
+ }
+ content += `**File:** ${item.path || "No path provided"}\n\n`;
+ content += `**Line:** ${item.line || "No line provided"}\n\n`;
+ if (item.start_line) {
+ content += `**Start Line:** ${item.start_line}\n\n`;
+ }
+ content += `**Side:** ${item.side || "RIGHT"}\n\n`;
+ content += `**Body:**\n${item.body || "No content provided"}\n\n`;
+ return content;
+ },
+ };
+
+ await generateStagedPreview(options);
+
+ const summaryContent = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(summaryContent).toContain("## 🎭 Staged Mode: Create PR Review Comments Preview");
+ expect(summaryContent).toContain("### Review Comment 1");
+ expect(summaryContent).toContain("**Target PR:** [#123](https://github.com/test/repo/pull/123)");
+ expect(summaryContent).toContain("**File:** src/main.js");
+ expect(summaryContent).toContain("**Line:** 42");
+ expect(summaryContent).toContain("**Start Line:** 40");
+ expect(summaryContent).toContain("**Side:** RIGHT");
+ expect(summaryContent).toContain("**Body:**\nThis needs improvement");
+ expect(summaryContent).toContain("### Review Comment 2");
+ expect(summaryContent).toContain("**Target:** Current PR");
+ expect(summaryContent).toContain("**File:** src/utils.js");
+ expect(summaryContent).toContain("**Side:** LEFT");
+ });
+
+ it("should handle push to PR branch preview with complex data", async () => {
+ const options = {
+ title: "Push to PR Branch",
+ description: "The following changes would be pushed if staged mode was disabled:",
+ items: [
+ {
+ target: "feature-branch",
+ commit_message: "Update implementation",
+ has_patch: true,
+ patch_size: 150,
+ },
+ ],
+ renderItem: item => {
+ let content = "";
+ content += `**Target:** ${item.target}\n\n`;
+ if (item.commit_message) {
+ content += `**Commit Message:** ${item.commit_message}\n\n`;
+ }
+ if (item.has_patch) {
+ content += `**Changes:** Patch file exists with ${item.patch_size} lines\n\n`;
+ }
+ return content;
+ },
+ };
+
+ await generateStagedPreview(options);
+
+ const summaryContent = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(summaryContent).toContain("## 🎭 Staged Mode: Push to PR Branch Preview");
+ expect(summaryContent).toContain("**Target:** feature-branch");
+ expect(summaryContent).toContain("**Commit Message:** Update implementation");
+ expect(summaryContent).toContain("**Changes:** Patch file exists with 150 lines");
+ });
+
+ it("should handle empty items array", async () => {
+ const options = {
+ title: "Test Preview",
+ description: "Nothing to preview:",
+ items: [],
+ renderItem: () => "",
+ };
+
+ await generateStagedPreview(options);
+
+ const summaryContent = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(summaryContent).toContain("## 🎭 Staged Mode: Test Preview Preview");
+ expect(summaryContent).toContain("Nothing to preview:");
+ // Should not have any dividers since there are no items
+ expect(summaryContent).not.toContain("---");
+ });
+
+ it("should handle custom renderItem function with no divider", async () => {
+ const options = {
+ title: "Custom Preview",
+ description: "Custom items:",
+ items: [{ name: "item1" }, { name: "item2" }],
+ renderItem: item => {
+ return `- ${item.name}\n`;
+ },
+ };
+
+ await generateStagedPreview(options);
+
+ const summaryContent = mockCore.summary.addRaw.mock.calls[0][0];
+ expect(summaryContent).toContain("- item1");
+ expect(summaryContent).toContain("- item2");
+ // Dividers should still be added after each item by the function
+ const dividerCount = (summaryContent.match(/---/g) || []).length;
+ expect(dividerCount).toBe(2);
+ });
+
+ it("should properly chain summary methods", async () => {
+ const options = {
+ title: "Test",
+ description: "Test description",
+ items: [{ test: "data" }],
+ renderItem: () => "Test content\n",
+ };
+
+ await generateStagedPreview(options);
+
+ expect(mockCore.summary.addRaw).toHaveBeenCalledTimes(1);
+ expect(mockCore.summary.addRaw).toHaveReturnedWith(mockCore.summary);
+ expect(mockCore.summary.write).toHaveBeenCalledTimes(1);
+ });
+
+ it("should include index in renderItem callback", async () => {
+ const renderItemSpy = vi.fn((item, index) => `Item ${index + 1}\n`);
+
+ const options = {
+ title: "Index Test",
+ description: "Testing index parameter",
+ items: [{ id: 1 }, { id: 2 }, { id: 3 }],
+ renderItem: renderItemSpy,
+ };
+
+ await generateStagedPreview(options);
+
+ expect(renderItemSpy).toHaveBeenCalledTimes(3);
+ expect(renderItemSpy).toHaveBeenNthCalledWith(1, { id: 1 }, 0);
+ expect(renderItemSpy).toHaveBeenNthCalledWith(2, { id: 2 }, 1);
+ expect(renderItemSpy).toHaveBeenNthCalledWith(3, { id: 3 }, 2);
+ });
+ });
+});
diff --git a/pkg/workflow/js/update_issue.cjs b/pkg/workflow/js/update_issue.cjs
index 439627e266..eeb5083640 100644
--- a/pkg/workflow/js/update_issue.cjs
+++ b/pkg/workflow/js/update_issue.cjs
@@ -2,6 +2,7 @@
///
const { loadAgentOutput } = require("./load_agent_output.cjs");
+const { generateStagedPreview } = require("./staged_preview.cjs");
async function main() {
// Check if we're in staged mode
@@ -23,33 +24,30 @@ async function main() {
// If in staged mode, emit step summary instead of updating issues
if (isStaged) {
- let summaryContent = "## 🎭 Staged Mode: Update Issues Preview\n\n";
- summaryContent += "The following issue updates would be applied if staged mode was disabled:\n\n";
-
- for (let i = 0; i < updateItems.length; i++) {
- const item = updateItems[i];
- summaryContent += `### Issue Update ${i + 1}\n`;
- if (item.issue_number) {
- summaryContent += `**Target Issue:** #${item.issue_number}\n\n`;
- } else {
- summaryContent += `**Target:** Current issue\n\n`;
- }
-
- if (item.title !== undefined) {
- summaryContent += `**New Title:** ${item.title}\n\n`;
- }
- if (item.body !== undefined) {
- summaryContent += `**New Body:**\n${item.body}\n\n`;
- }
- if (item.status !== undefined) {
- summaryContent += `**New Status:** ${item.status}\n\n`;
- }
- summaryContent += "---\n\n";
- }
+ await generateStagedPreview({
+ title: "Update Issues",
+ description: "The following issue updates would be applied if staged mode was disabled:",
+ items: updateItems,
+ renderItem: (item, index) => {
+ let content = `### Issue Update ${index + 1}\n`;
+ if (item.issue_number) {
+ content += `**Target Issue:** #${item.issue_number}\n\n`;
+ } else {
+ content += `**Target:** Current issue\n\n`;
+ }
- // Write to step summary
- await core.summary.addRaw(summaryContent).write();
- core.info("📝 Issue update preview written to step summary");
+ if (item.title !== undefined) {
+ content += `**New Title:** ${item.title}\n\n`;
+ }
+ if (item.body !== undefined) {
+ content += `**New Body:**\n${item.body}\n\n`;
+ }
+ if (item.status !== undefined) {
+ content += `**New Status:** ${item.status}\n\n`;
+ }
+ return content;
+ },
+ });
return;
}