diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml
index 24c2359584..d9f5f1e19e 100644
--- a/.github/workflows/audit-workflows.lock.yml
+++ b/.github/workflows/audit-workflows.lock.yml
@@ -322,7 +322,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -352,7 +352,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1894,7 +1894,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1933,7 +1933,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Agentic Workflow Audit Agent",
experimental: true,
supports_tools_allowlist: true,
@@ -1950,7 +1950,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1997,7 +1997,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'';
@@ -5975,9 +5975,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6943,7 +6943,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/blog-auditor.lock.yml b/.github/workflows/blog-auditor.lock.yml
index 6f1834ae51..85e3ecac1d 100644
--- a/.github/workflows/blog-auditor.lock.yml
+++ b/.github/workflows/blog-auditor.lock.yml
@@ -255,7 +255,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -285,7 +285,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
docker_pull_with_retry mcr.microsoft.com/playwright/mcp
- name: Write Safe Outputs Config
run: |
@@ -1795,7 +1795,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1850,7 +1850,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Blog Auditor",
experimental: true,
supports_tools_allowlist: true,
@@ -1867,7 +1867,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","githubnext.com","www.githubnext.com"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1914,7 +1914,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5472,9 +5472,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6426,7 +6426,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/blog-auditor.md b/.github/workflows/blog-auditor.md
index 0ab9c5d4d4..332ce5ca3c 100644
--- a/.github/workflows/blog-auditor.md
+++ b/.github/workflows/blog-auditor.md
@@ -9,7 +9,7 @@ permissions:
pull-requests: read
tracker-id: blog-auditor-weekly
engine: claude
-strict: false
+strict: true
network:
allowed:
- defaults
diff --git a/.github/workflows/campaign-generator.lock.yml b/.github/workflows/campaign-generator.lock.yml
index d8a8899dd6..d72be49b26 100644
--- a/.github/workflows/campaign-generator.lock.yml
+++ b/.github/workflows/campaign-generator.lock.yml
@@ -287,7 +287,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -331,7 +331,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1887,7 +1887,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"tools": ["*"],
"env": {
@@ -1936,7 +1936,7 @@ jobs:
engine_name: "GitHub Copilot CLI",
model: process.env.GH_AW_MODEL_AGENT_COPILOT || "",
version: "",
- agent_version: "0.0.369",
+ agent_version: "0.0.371",
workflow_name: "Campaign Generator",
experimental: false,
supports_tools_allowlist: true,
@@ -1953,7 +1953,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2000,7 +2000,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5574,9 +5574,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6561,7 +6561,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -7522,7 +7522,7 @@ jobs:
};
EOF_4d21ccbd
- cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_006d32d7'
+ cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_60283df2'
// @ts-check
///
@@ -7607,11 +7607,12 @@ jobs:
* @param {boolean} params.canUpdateStatus - Whether status updates are allowed
* @param {boolean} params.canUpdateTitle - Whether title updates are allowed
* @param {boolean} params.canUpdateBody - Whether body updates are allowed
+ * @param {boolean} [params.canUpdateLabels] - Whether label updates are allowed
* @param {boolean} params.supportsStatus - Whether this type supports status
* @returns {{hasUpdates: boolean, updateData: any, logMessages: string[]}}
*/
function buildUpdateData(params) {
- const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, supportsStatus } = params;
+ const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, canUpdateLabels, supportsStatus } = params;
/** @type {any} */
const updateData = {};
@@ -7661,6 +7662,17 @@ jobs:
}
}
+ // Handle labels update
+ if (canUpdateLabels && item.labels !== undefined) {
+ if (Array.isArray(item.labels)) {
+ updateData.labels = item.labels;
+ hasUpdates = true;
+ logMessages.push(`Will update labels to: ${item.labels.join(", ")}`);
+ } else {
+ logMessages.push("Invalid labels value: must be an array");
+ }
+ }
+
return { hasUpdates, updateData, logMessages };
}
@@ -7705,12 +7717,13 @@ jobs:
const canUpdateStatus = process.env.GH_AW_UPDATE_STATUS === "true";
const canUpdateTitle = process.env.GH_AW_UPDATE_TITLE === "true";
const canUpdateBody = process.env.GH_AW_UPDATE_BODY === "true";
+ const canUpdateLabels = process.env.GH_AW_UPDATE_LABELS === "true";
core.info(`Update target configuration: ${updateTarget}`);
if (supportsStatus) {
- core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
} else {
- core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
}
// Check context validity
@@ -7754,6 +7767,7 @@ jobs:
canUpdateStatus,
canUpdateTitle,
canUpdateBody,
+ canUpdateLabels,
supportsStatus,
});
@@ -7875,7 +7889,7 @@ jobs:
createGetSummaryLine,
};
- EOF_006d32d7
+ EOF_60283df2
- name: Assign To Agent
id: assign_to_agent
if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'assign_to_agent'))
diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml
index 9028f71a96..0993dbd152 100644
--- a/.github/workflows/changeset.lock.yml
+++ b/.github/workflows/changeset.lock.yml
@@ -988,7 +988,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -1026,7 +1026,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -2600,7 +2600,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -2623,7 +2623,7 @@ jobs:
engine_name: "Codex",
model: "gpt-5-mini",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "Changeset Generator",
experimental: true,
supports_tools_allowlist: true,
@@ -2640,7 +2640,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","node"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2687,7 +2687,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6244,9 +6244,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-changeset-generator
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -8269,7 +8428,7 @@ jobs:
};
EOF_d0693c3b
- cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_006d32d7'
+ cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_60283df2'
// @ts-check
///
@@ -8354,11 +8513,12 @@ jobs:
* @param {boolean} params.canUpdateStatus - Whether status updates are allowed
* @param {boolean} params.canUpdateTitle - Whether title updates are allowed
* @param {boolean} params.canUpdateBody - Whether body updates are allowed
+ * @param {boolean} [params.canUpdateLabels] - Whether label updates are allowed
* @param {boolean} params.supportsStatus - Whether this type supports status
* @returns {{hasUpdates: boolean, updateData: any, logMessages: string[]}}
*/
function buildUpdateData(params) {
- const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, supportsStatus } = params;
+ const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, canUpdateLabels, supportsStatus } = params;
/** @type {any} */
const updateData = {};
@@ -8408,6 +8568,17 @@ jobs:
}
}
+ // Handle labels update
+ if (canUpdateLabels && item.labels !== undefined) {
+ if (Array.isArray(item.labels)) {
+ updateData.labels = item.labels;
+ hasUpdates = true;
+ logMessages.push(`Will update labels to: ${item.labels.join(", ")}`);
+ } else {
+ logMessages.push("Invalid labels value: must be an array");
+ }
+ }
+
return { hasUpdates, updateData, logMessages };
}
@@ -8452,12 +8623,13 @@ jobs:
const canUpdateStatus = process.env.GH_AW_UPDATE_STATUS === "true";
const canUpdateTitle = process.env.GH_AW_UPDATE_TITLE === "true";
const canUpdateBody = process.env.GH_AW_UPDATE_BODY === "true";
+ const canUpdateLabels = process.env.GH_AW_UPDATE_LABELS === "true";
core.info(`Update target configuration: ${updateTarget}`);
if (supportsStatus) {
- core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
} else {
- core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
}
// Check context validity
@@ -8501,6 +8673,7 @@ jobs:
canUpdateStatus,
canUpdateTitle,
canUpdateBody,
+ canUpdateLabels,
supportsStatus,
});
@@ -8622,7 +8795,7 @@ jobs:
createGetSummaryLine,
};
- EOF_006d32d7
+ EOF_60283df2
- name: Update Pull Request
id: update_pull_request
if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'update_pull_request'))
diff --git a/.github/workflows/changeset.md b/.github/workflows/changeset.md
index 5eb6afd6dd..45cd2ee578 100644
--- a/.github/workflows/changeset.md
+++ b/.github/workflows/changeset.md
@@ -15,7 +15,7 @@ permissions:
engine:
id: codex
model: gpt-5-mini
-strict: false # Required: codex engine doesn't support network firewall
+strict: true
safe-outputs:
push-to-pull-request-branch:
commit-title-suffix: " [skip-ci]"
diff --git a/.github/workflows/cli-version-checker.lock.yml b/.github/workflows/cli-version-checker.lock.yml
index edf443f7e6..97567db202 100644
--- a/.github/workflows/cli-version-checker.lock.yml
+++ b/.github/workflows/cli-version-checker.lock.yml
@@ -273,7 +273,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -303,7 +303,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1833,7 +1833,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1872,7 +1872,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "CLI Version Checker",
experimental: true,
supports_tools_allowlist: true,
@@ -1889,7 +1889,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","node","api.github.com","ghcr.io"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1936,7 +1936,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5474,9 +5474,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6432,7 +6432,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/cli-version-checker.md b/.github/workflows/cli-version-checker.md
index 12902e3ded..425b6c2058 100644
--- a/.github/workflows/cli-version-checker.md
+++ b/.github/workflows/cli-version-checker.md
@@ -7,7 +7,7 @@ permissions:
contents: read
pull-requests: read
issues: read
-strict: false
+strict: true
engine: claude
network:
allowed: [defaults, node, "api.github.com", "ghcr.io"]
diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml
index 01ffb8598a..3c1e892a22 100644
--- a/.github/workflows/cloclo.lock.yml
+++ b/.github/workflows/cloclo.lock.yml
@@ -1064,7 +1064,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -1094,7 +1094,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
docker_pull_with_retry mcr.microsoft.com/playwright/mcp
- name: Write Safe Outputs Config
run: |
@@ -2654,7 +2654,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -2722,7 +2722,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "/cloclo",
experimental: true,
supports_tools_allowlist: true,
@@ -2739,7 +2739,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2786,7 +2786,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6342,9 +6342,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7306,7 +7306,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/close-old-discussions.lock.yml b/.github/workflows/close-old-discussions.lock.yml
index 36428eb38f..aab970964a 100644
--- a/.github/workflows/close-old-discussions.lock.yml
+++ b/.github/workflows/close-old-discussions.lock.yml
@@ -279,7 +279,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -317,7 +317,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1839,7 +1839,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests,discussions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -1862,7 +1862,7 @@ jobs:
engine_name: "Codex",
model: process.env.GH_AW_MODEL_AGENT_CODEX || "",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "Close Outdated Discussions",
experimental: true,
supports_tools_allowlist: true,
@@ -1879,7 +1879,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1926,7 +1926,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5426,9 +5426,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-close-outdated-discussions
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6384,7 +6543,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Run Codex
run: |
set -o pipefail
diff --git a/.github/workflows/commit-changes-analyzer.lock.yml b/.github/workflows/commit-changes-analyzer.lock.yml
index f1da96f780..3370366425 100644
--- a/.github/workflows/commit-changes-analyzer.lock.yml
+++ b/.github/workflows/commit-changes-analyzer.lock.yml
@@ -257,7 +257,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -287,7 +287,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1796,7 +1796,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1835,7 +1835,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Commit Changes Analyzer",
experimental: true,
supports_tools_allowlist: true,
@@ -1852,7 +1852,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1899,7 +1899,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5393,9 +5393,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6344,7 +6344,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml
index 21ed5f0de9..6f25ece959 100644
--- a/.github/workflows/copilot-agent-analysis.lock.yml
+++ b/.github/workflows/copilot-agent-analysis.lock.yml
@@ -282,7 +282,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -312,7 +312,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1821,7 +1821,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1860,7 +1860,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Copilot Agent PR Analysis",
experimental: true,
supports_tools_allowlist: true,
@@ -1877,7 +1877,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1924,7 +1924,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5784,9 +5784,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6742,7 +6742,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/copilot-agent-analysis.md b/.github/workflows/copilot-agent-analysis.md
index 043469677c..f92793dad6 100644
--- a/.github/workflows/copilot-agent-analysis.md
+++ b/.github/workflows/copilot-agent-analysis.md
@@ -14,7 +14,7 @@ permissions:
actions: read
engine: claude
-strict: false
+strict: true
network:
allowed:
diff --git a/.github/workflows/copilot-pr-merged-report.md b/.github/workflows/copilot-pr-merged-report.md
index 47e91c309a..60c7b3b4f8 100644
--- a/.github/workflows/copilot-pr-merged-report.md
+++ b/.github/workflows/copilot-pr-merged-report.md
@@ -14,7 +14,7 @@ permissions:
actions: read
engine: copilot
-strict: false
+strict: true
tools:
github: false
diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml
index 6dd6ea140f..395b9236e7 100644
--- a/.github/workflows/copilot-session-insights.lock.yml
+++ b/.github/workflows/copilot-session-insights.lock.yml
@@ -308,7 +308,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -338,7 +338,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1876,7 +1876,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1915,7 +1915,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Copilot Session Insights",
experimental: true,
supports_tools_allowlist: true,
@@ -1932,7 +1932,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github","python"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1979,7 +1979,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6516,9 +6516,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7481,7 +7481,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/copilot-session-insights.md b/.github/workflows/copilot-session-insights.md
index 899e639e76..098a900667 100644
--- a/.github/workflows/copilot-session-insights.md
+++ b/.github/workflows/copilot-session-insights.md
@@ -14,7 +14,7 @@ permissions:
pull-requests: read
engine: claude
-strict: false
+strict: true
network:
allowed:
diff --git a/.github/workflows/daily-code-metrics.lock.yml b/.github/workflows/daily-code-metrics.lock.yml
index 3d2cbd817a..ef1f8f397c 100644
--- a/.github/workflows/daily-code-metrics.lock.yml
+++ b/.github/workflows/daily-code-metrics.lock.yml
@@ -295,7 +295,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -325,7 +325,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1834,7 +1834,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1873,7 +1873,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Daily Code Metrics and Trend Tracking Agent",
experimental: true,
supports_tools_allowlist: true,
@@ -1890,7 +1890,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1937,7 +1937,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6018,9 +6018,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6979,7 +6979,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/daily-doc-updater.lock.yml b/.github/workflows/daily-doc-updater.lock.yml
index c65b8cb9ac..dc022e7a49 100644
--- a/.github/workflows/daily-doc-updater.lock.yml
+++ b/.github/workflows/daily-doc-updater.lock.yml
@@ -266,7 +266,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -296,7 +296,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1815,7 +1815,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1854,7 +1854,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Daily Documentation Updater",
experimental: true,
supports_tools_allowlist: true,
@@ -1871,7 +1871,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1918,7 +1918,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5311,9 +5311,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6279,7 +6279,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/daily-doc-updater.md b/.github/workflows/daily-doc-updater.md
index a5893530e5..fb7b281fee 100644
--- a/.github/workflows/daily-doc-updater.md
+++ b/.github/workflows/daily-doc-updater.md
@@ -14,7 +14,7 @@ permissions:
tracker-id: daily-doc-updater
engine: claude
-strict: false
+strict: true
network:
allowed:
diff --git a/.github/workflows/daily-fact.lock.yml b/.github/workflows/daily-fact.lock.yml
index 227bca5d40..0621a54545 100644
--- a/.github/workflows/daily-fact.lock.yml
+++ b/.github/workflows/daily-fact.lock.yml
@@ -244,7 +244,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -282,7 +282,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1783,7 +1783,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests,discussions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -1806,7 +1806,7 @@ jobs:
engine_name: "Codex",
model: "gpt-5-mini",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "Daily Fact About gh-aw",
experimental: true,
supports_tools_allowlist: true,
@@ -1823,7 +1823,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1870,7 +1870,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5248,9 +5248,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-daily-fact-about-gh-aw
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6203,7 +6362,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Run Codex
run: |
set -o pipefail
diff --git a/.github/workflows/daily-fact.md b/.github/workflows/daily-fact.md
index b99956d354..20539becc4 100644
--- a/.github/workflows/daily-fact.md
+++ b/.github/workflows/daily-fact.md
@@ -14,7 +14,7 @@ tracker-id: daily-fact-thread
engine:
id: codex
model: gpt-5-mini
-strict: false # Required: codex engine doesn't support network firewall
+strict: true
timeout-minutes: 15
network:
diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml
index a76841daf5..8b36305819 100644
--- a/.github/workflows/daily-issues-report.lock.yml
+++ b/.github/workflows/daily-issues-report.lock.yml
@@ -301,7 +301,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -339,7 +339,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1942,7 +1942,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests,discussions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -1965,7 +1965,7 @@ jobs:
engine_name: "Codex",
model: process.env.GH_AW_MODEL_AGENT_CODEX || "",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "Daily Issues Report Generator",
experimental: true,
supports_tools_allowlist: true,
@@ -1982,7 +1982,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","python"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2029,7 +2029,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6413,9 +6413,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-daily-issues-report-generator
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7381,7 +7540,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Run Codex
run: |
set -o pipefail
diff --git a/.github/workflows/daily-issues-report.md b/.github/workflows/daily-issues-report.md
index 2ae5fb4388..204fd04b77 100644
--- a/.github/workflows/daily-issues-report.md
+++ b/.github/workflows/daily-issues-report.md
@@ -10,7 +10,7 @@ permissions:
pull-requests: read
discussions: write
engine: codex
-strict: false
+strict: true
tracker-id: daily-issues-report
tools:
github:
diff --git a/.github/workflows/daily-multi-device-docs-tester.lock.yml b/.github/workflows/daily-multi-device-docs-tester.lock.yml
index 1b019ef786..83fb769d91 100644
--- a/.github/workflows/daily-multi-device-docs-tester.lock.yml
+++ b/.github/workflows/daily-multi-device-docs-tester.lock.yml
@@ -140,7 +140,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
- issues: write
+ issues: read
pull-requests: read
concurrency:
group: "gh-aw-claude-${{ github.workflow }}"
@@ -259,7 +259,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -289,7 +289,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
docker_pull_with_retry mcr.microsoft.com/playwright/mcp
- name: Write Safe Outputs Config
run: |
@@ -1849,7 +1849,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1904,7 +1904,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Multi-Device Docs Tester",
experimental: true,
supports_tools_allowlist: true,
@@ -1921,7 +1921,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["node"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1968,7 +1968,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5293,9 +5293,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6254,7 +6254,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/daily-multi-device-docs-tester.md b/.github/workflows/daily-multi-device-docs-tester.md
index 79cb1cddd9..2c9623f7ff 100644
--- a/.github/workflows/daily-multi-device-docs-tester.md
+++ b/.github/workflows/daily-multi-device-docs-tester.md
@@ -11,13 +11,13 @@ on:
default: 'mobile,tablet,desktop'
permissions:
contents: read
- issues: write
+ issues: read
pull-requests: read
tracker-id: daily-multi-device-docs-tester
engine:
id: claude
max-turns: 30 # Prevent runaway token usage
-strict: false
+strict: true
timeout-minutes: 30
tools:
playwright:
diff --git a/.github/workflows/daily-performance-summary.lock.yml b/.github/workflows/daily-performance-summary.lock.yml
index eeb10be1ed..5d09c3ea7b 100644
--- a/.github/workflows/daily-performance-summary.lock.yml
+++ b/.github/workflows/daily-performance-summary.lock.yml
@@ -293,7 +293,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -331,7 +331,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -3617,7 +3617,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests,discussions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -3646,7 +3646,7 @@ jobs:
engine_name: "Codex",
model: process.env.GH_AW_MODEL_AGENT_CODEX || "",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "Daily Project Performance Summary Generator (Using Safe Inputs)",
experimental: true,
supports_tools_allowlist: true,
@@ -3663,7 +3663,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -3710,7 +3710,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -7876,9 +7876,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-daily-project-performance-summary-generator-using-safe-inputs-
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -8844,7 +9003,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Run Codex
run: |
set -o pipefail
diff --git a/.github/workflows/daily-performance-summary.md b/.github/workflows/daily-performance-summary.md
index 376aa5f5d8..36728bfa6d 100644
--- a/.github/workflows/daily-performance-summary.md
+++ b/.github/workflows/daily-performance-summary.md
@@ -10,7 +10,7 @@ permissions:
pull-requests: read
discussions: write
engine: codex
-strict: false
+strict: true
tracker-id: daily-performance-summary
tools:
github:
diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml
index 9facc42777..cf1867aae9 100644
--- a/.github/workflows/deep-report.lock.yml
+++ b/.github/workflows/deep-report.lock.yml
@@ -324,7 +324,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -362,7 +362,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1911,7 +1911,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=all",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -1934,7 +1934,7 @@ jobs:
engine_name: "Codex",
model: process.env.GH_AW_MODEL_AGENT_CODEX || "",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "DeepReport - Intelligence Gathering Agent",
experimental: true,
supports_tools_allowlist: true,
@@ -1951,7 +1951,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","python","node"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1998,7 +1998,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5894,9 +5894,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-deepreport-intelligence-gathering-agent
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6872,7 +7031,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Run Codex
run: |
set -o pipefail
diff --git a/.github/workflows/deep-report.md b/.github/workflows/deep-report.md
index 577963f4de..4284281c03 100644
--- a/.github/workflows/deep-report.md
+++ b/.github/workflows/deep-report.md
@@ -18,7 +18,7 @@ permissions:
tracker-id: deep-report-intel-agent
timeout-minutes: 45
engine: codex
-strict: false
+strict: true
network:
allowed:
diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml
index fb168fe885..00a614e66a 100644
--- a/.github/workflows/dev.lock.yml
+++ b/.github/workflows/dev.lock.yml
@@ -240,7 +240,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -284,7 +284,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -3157,7 +3157,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=discussions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"tools": ["*"],
"env": {
@@ -3220,7 +3220,7 @@ jobs:
engine_name: "GitHub Copilot CLI",
model: process.env.GH_AW_MODEL_AGENT_COPILOT || "",
version: "",
- agent_version: "0.0.369",
+ agent_version: "0.0.371",
workflow_name: "Dev",
experimental: false,
supports_tools_allowlist: true,
@@ -3237,7 +3237,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["api.github.com"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -3284,7 +3284,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6797,9 +6797,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7746,7 +7746,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -8404,7 +8404,7 @@ jobs:
};
EOF_4d21ccbd
- cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_006d32d7'
+ cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_60283df2'
// @ts-check
///
@@ -8489,11 +8489,12 @@ jobs:
* @param {boolean} params.canUpdateStatus - Whether status updates are allowed
* @param {boolean} params.canUpdateTitle - Whether title updates are allowed
* @param {boolean} params.canUpdateBody - Whether body updates are allowed
+ * @param {boolean} [params.canUpdateLabels] - Whether label updates are allowed
* @param {boolean} params.supportsStatus - Whether this type supports status
* @returns {{hasUpdates: boolean, updateData: any, logMessages: string[]}}
*/
function buildUpdateData(params) {
- const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, supportsStatus } = params;
+ const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, canUpdateLabels, supportsStatus } = params;
/** @type {any} */
const updateData = {};
@@ -8543,6 +8544,17 @@ jobs:
}
}
+ // Handle labels update
+ if (canUpdateLabels && item.labels !== undefined) {
+ if (Array.isArray(item.labels)) {
+ updateData.labels = item.labels;
+ hasUpdates = true;
+ logMessages.push(`Will update labels to: ${item.labels.join(", ")}`);
+ } else {
+ logMessages.push("Invalid labels value: must be an array");
+ }
+ }
+
return { hasUpdates, updateData, logMessages };
}
@@ -8587,12 +8599,13 @@ jobs:
const canUpdateStatus = process.env.GH_AW_UPDATE_STATUS === "true";
const canUpdateTitle = process.env.GH_AW_UPDATE_TITLE === "true";
const canUpdateBody = process.env.GH_AW_UPDATE_BODY === "true";
+ const canUpdateLabels = process.env.GH_AW_UPDATE_LABELS === "true";
core.info(`Update target configuration: ${updateTarget}`);
if (supportsStatus) {
- core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
} else {
- core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
}
// Check context validity
@@ -8636,6 +8649,7 @@ jobs:
canUpdateStatus,
canUpdateTitle,
canUpdateBody,
+ canUpdateLabels,
supportsStatus,
});
@@ -8757,7 +8771,7 @@ jobs:
createGetSummaryLine,
};
- EOF_006d32d7
+ EOF_60283df2
- name: Update Discussion
id: update_discussion
if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'update_discussion'))
@@ -8788,8 +8802,28 @@ jobs:
includeOperation: false,
});
async function executeDiscussionUpdate(github, context, discussionNumber, updateData) {
- const { _operation, _rawBody, ...fieldsToUpdate } = updateData;
- const getDiscussionQuery = `
+ const { _operation, _rawBody, labels, ...fieldsToUpdate } = updateData;
+ const shouldUpdateLabels = process.env.GH_AW_UPDATE_LABELS === "true" && labels !== undefined;
+ const getDiscussionQuery = shouldUpdateLabels
+ ? `
+ query($owner: String!, $repo: String!, $number: Int!) {
+ repository(owner: $owner, name: $repo) {
+ discussion(number: $number) {
+ id
+ title
+ body
+ url
+ labels(first: 100) {
+ nodes {
+ id
+ name
+ }
+ }
+ }
+ }
+ }
+ `
+ : `
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
discussion(number: $number) {
@@ -8809,9 +8843,11 @@ jobs:
if (!queryResult?.repository?.discussion) {
throw new Error(`Discussion #${discussionNumber} not found`);
}
- const discussionId = queryResult.repository.discussion.id;
- if (fieldsToUpdate.title === undefined && fieldsToUpdate.body === undefined) {
- throw new Error("At least one field (title or body) must be provided for update");
+ const discussion = queryResult.repository.discussion;
+ const discussionId = discussion.id;
+ const currentLabels = shouldUpdateLabels ? discussion.labels?.nodes || [] : [];
+ if (fieldsToUpdate.title === undefined && fieldsToUpdate.body === undefined && !shouldUpdateLabels) {
+ throw new Error("At least one field (title, body, or labels) must be provided for update");
}
if (fieldsToUpdate.body !== undefined) {
const workflowName = process.env.GH_AW_WORKFLOW_NAME || "Workflow";
@@ -8826,22 +8862,130 @@ jobs:
const footer = generateFooterWithMessages(workflowName, runUrl, workflowSource, workflowSourceURL, triggeringIssueNumber, triggeringPRNumber, triggeringDiscussionNumber);
fieldsToUpdate.body = fieldsToUpdate.body + footer;
}
- const mutationFields = [];
- if (fieldsToUpdate.title !== undefined) {
- mutationFields.push("title: $title");
+ if (fieldsToUpdate.title !== undefined || fieldsToUpdate.body !== undefined) {
+ const mutationFields = [];
+ if (fieldsToUpdate.title !== undefined) {
+ mutationFields.push("title: $title");
+ }
+ if (fieldsToUpdate.body !== undefined) {
+ mutationFields.push("body: $body");
+ }
+ const updateDiscussionMutation = `
+ mutation($discussionId: ID!${fieldsToUpdate.title !== undefined ? ", $title: String!" : ""}${fieldsToUpdate.body !== undefined ? ", $body: String!" : ""}) {
+ updateDiscussion(input: {
+ discussionId: $discussionId
+ ${mutationFields.join("\n ")}
+ }) {
+ discussion {
+ id
+ number
+ title
+ body
+ url
+ }
+ }
+ }
+ `;
+ const variables = {
+ discussionId: discussionId,
+ };
+ if (fieldsToUpdate.title !== undefined) {
+ variables.title = fieldsToUpdate.title;
+ }
+ if (fieldsToUpdate.body !== undefined) {
+ variables.body = fieldsToUpdate.body;
+ }
+ const mutationResult = await github.graphql(updateDiscussionMutation, variables);
+ if (!mutationResult?.updateDiscussion?.discussion) {
+ throw new Error("Failed to update discussion");
+ }
}
- if (fieldsToUpdate.body !== undefined) {
- mutationFields.push("body: $body");
- }
- const updateDiscussionMutation = `
- mutation($discussionId: ID!${fieldsToUpdate.title !== undefined ? ", $title: String!" : ""}${fieldsToUpdate.body !== undefined ? ", $body: String!" : ""}) {
- updateDiscussion(input: {
- discussionId: $discussionId
- ${mutationFields.join("\n ")}
- }) {
- discussion {
+ if (shouldUpdateLabels && Array.isArray(labels)) {
+ const repoQuery = `
+ query($owner: String!, $repo: String!) {
+ repository(owner: $owner, name: $repo) {
+ id
+ labels(first: 100) {
+ nodes {
+ id
+ name
+ }
+ }
+ }
+ }
+ `;
+ const repoResult = await github.graphql(repoQuery, {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ });
+ if (!repoResult?.repository) {
+ throw new Error(`Repository ${context.repo.owner}/${context.repo.repo} not found`);
+ }
+ const repoLabels = repoResult.repository.labels?.nodes || [];
+ const labelIds = labels.map(labelName => {
+ const label = repoLabels.find(l => l.name === labelName);
+ if (!label) {
+ throw new Error(`Label "${labelName}" not found in repository`);
+ }
+ return label.id;
+ });
+ if (currentLabels.length > 0) {
+ const removeLabelsMutation = `
+ mutation($labelableId: ID!, $labelIds: [ID!]!) {
+ removeLabelsFromLabelable(input: {
+ labelableId: $labelableId
+ labelIds: $labelIds
+ }) {
+ clientMutationId
+ }
+ }
+ `;
+ await github.graphql(removeLabelsMutation, {
+ labelableId: discussionId,
+ labelIds: currentLabels.map(l => l.id),
+ });
+ }
+ if (labelIds.length > 0) {
+ const addLabelsMutation = `
+ mutation($labelableId: ID!, $labelIds: [ID!]!) {
+ addLabelsToLabelable(input: {
+ labelableId: $labelableId
+ labelIds: $labelIds
+ }) {
+ clientMutationId
+ }
+ }
+ `;
+ await github.graphql(addLabelsMutation, {
+ labelableId: discussionId,
+ labelIds: labelIds,
+ });
+ }
+ }
+ const finalQuery = shouldUpdateLabels
+ ? `
+ query($owner: String!, $repo: String!, $number: Int!) {
+ repository(owner: $owner, name: $repo) {
+ discussion(number: $number) {
+ id
+ title
+ body
+ url
+ labels(first: 100) {
+ nodes {
+ id
+ name
+ }
+ }
+ }
+ }
+ }
+ `
+ : `
+ query($owner: String!, $repo: String!, $number: Int!) {
+ repository(owner: $owner, name: $repo) {
+ discussion(number: $number) {
id
- number
title
body
url
@@ -8849,23 +8993,15 @@ jobs:
}
}
`;
- const variables = {
- discussionId: discussionId,
- };
- if (fieldsToUpdate.title !== undefined) {
- variables.title = fieldsToUpdate.title;
- }
- if (fieldsToUpdate.body !== undefined) {
- variables.body = fieldsToUpdate.body;
- }
- const mutationResult = await github.graphql(updateDiscussionMutation, variables);
- if (!mutationResult?.updateDiscussion?.discussion) {
- throw new Error("Failed to update discussion");
- }
- const discussion = mutationResult.updateDiscussion.discussion;
+ const finalQueryResult = await github.graphql(finalQuery, {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ number: discussionNumber,
+ });
+ const updatedDiscussion = finalQueryResult.repository.discussion;
return {
- ...discussion,
- html_url: discussion.url,
+ ...updatedDiscussion,
+ html_url: updatedDiscussion.url,
};
}
const getSummaryLine = createGetSummaryLine({
diff --git a/.github/workflows/dev.md b/.github/workflows/dev.md
index 3301b90108..4df0e5c1da 100644
--- a/.github/workflows/dev.md
+++ b/.github/workflows/dev.md
@@ -4,7 +4,7 @@ on:
name: Dev
description: Add a poem to the latest discussion
timeout-minutes: 5
-strict: false
+strict: true
engine: copilot
permissions:
diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml
index 63628e9c8d..96741703c5 100644
--- a/.github/workflows/developer-docs-consolidator.lock.yml
+++ b/.github/workflows/developer-docs-consolidator.lock.yml
@@ -284,7 +284,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -314,7 +314,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1885,7 +1885,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1937,7 +1937,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Developer Documentation Consolidator",
experimental: true,
supports_tools_allowlist: true,
@@ -1954,7 +1954,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2001,7 +2001,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5930,9 +5930,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6895,7 +6895,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/developer-docs-consolidator.md b/.github/workflows/developer-docs-consolidator.md
index 4c288cef12..06f224d111 100644
--- a/.github/workflows/developer-docs-consolidator.md
+++ b/.github/workflows/developer-docs-consolidator.md
@@ -14,7 +14,7 @@ permissions:
pull-requests: read
engine: claude
-strict: false
+strict: true
network:
allowed:
diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml
index 0d17c82494..46aece0fda 100644
--- a/.github/workflows/duplicate-code-detector.lock.yml
+++ b/.github/workflows/duplicate-code-detector.lock.yml
@@ -255,7 +255,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -293,7 +293,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1831,7 +1831,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -1867,7 +1867,7 @@ jobs:
engine_name: "Codex",
model: process.env.GH_AW_MODEL_AGENT_CODEX || "",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "Duplicate Code Detector",
experimental: true,
supports_tools_allowlist: true,
@@ -1884,7 +1884,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1931,7 +1931,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5481,9 +5481,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-duplicate-code-detector
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6432,7 +6591,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Run Codex
run: |
set -o pipefail
diff --git a/.github/workflows/example-workflow-analyzer.lock.yml b/.github/workflows/example-workflow-analyzer.lock.yml
index 5840890694..2b2d3d8735 100644
--- a/.github/workflows/example-workflow-analyzer.lock.yml
+++ b/.github/workflows/example-workflow-analyzer.lock.yml
@@ -256,7 +256,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -286,7 +286,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Install gh-aw extension
env:
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
@@ -1816,7 +1816,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests,actions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1855,7 +1855,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Weekly Workflow Analysis",
experimental: true,
supports_tools_allowlist: true,
@@ -1872,7 +1872,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1919,7 +1919,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5142,9 +5142,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6093,7 +6093,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/firewall-escape.md b/.github/workflows/firewall-escape.md
index 371aaa527e..f8a9a4b528 100644
--- a/.github/workflows/firewall-escape.md
+++ b/.github/workflows/firewall-escape.md
@@ -15,7 +15,7 @@ permissions:
issues: read
pull-requests: read
-strict: false
+strict: true
engine: copilot
diff --git a/.github/workflows/github-mcp-structural-analysis.lock.yml b/.github/workflows/github-mcp-structural-analysis.lock.yml
index 3b51245ff6..8f9edd03f2 100644
--- a/.github/workflows/github-mcp-structural-analysis.lock.yml
+++ b/.github/workflows/github-mcp-structural-analysis.lock.yml
@@ -300,7 +300,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -330,7 +330,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1868,7 +1868,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=all",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1907,7 +1907,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "GitHub MCP Structural Analysis",
experimental: true,
supports_tools_allowlist: true,
@@ -1924,7 +1924,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","python"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1971,7 +1971,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5870,9 +5870,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6835,7 +6835,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/github-mcp-structural-analysis.md b/.github/workflows/github-mcp-structural-analysis.md
index e2b49448be..a857b1ad25 100644
--- a/.github/workflows/github-mcp-structural-analysis.md
+++ b/.github/workflows/github-mcp-structural-analysis.md
@@ -14,7 +14,7 @@ permissions:
repository-projects: read
security-events: read
engine: claude
-strict: false # Required: imports python-dataviz.md which needs network access, and claude doesn't support firewall
+strict: true
tools:
github:
mode: local
diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml
index 26ca19b57c..7825fda3a3 100644
--- a/.github/workflows/github-mcp-tools-report.lock.yml
+++ b/.github/workflows/github-mcp-tools-report.lock.yml
@@ -274,7 +274,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1875,7 +1875,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "GitHub MCP Remote Server Tools Report Generator",
experimental: true,
supports_tools_allowlist: true,
@@ -1892,7 +1892,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1939,7 +1939,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5742,9 +5742,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6707,7 +6707,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/go-fan.lock.yml b/.github/workflows/go-fan.lock.yml
index 276db272b2..b8580010ac 100644
--- a/.github/workflows/go-fan.lock.yml
+++ b/.github/workflows/go-fan.lock.yml
@@ -282,7 +282,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -312,7 +312,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1821,7 +1821,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1873,7 +1873,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Go Fan",
experimental: true,
supports_tools_allowlist: true,
@@ -1890,7 +1890,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github","go"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1937,7 +1937,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5528,9 +5528,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6489,7 +6489,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/go-fan.md b/.github/workflows/go-fan.md
index 601fa32786..c18be92af0 100644
--- a/.github/workflows/go-fan.md
+++ b/.github/workflows/go-fan.md
@@ -48,7 +48,7 @@ tools:
- "cat specs/mods/*"
timeout-minutes: 30
-strict: false
+strict: true
---
# Go Fan 🐹 - Daily Go Module Reviewer
diff --git a/.github/workflows/go-file-size-reduction-project64.campaign.g.lock.yml b/.github/workflows/go-file-size-reduction-project64.campaign.g.lock.yml
index 80819b97ab..1b57eae222 100644
--- a/.github/workflows/go-file-size-reduction-project64.campaign.g.lock.yml
+++ b/.github/workflows/go-file-size-reduction-project64.campaign.g.lock.yml
@@ -239,7 +239,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -283,7 +283,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1859,7 +1859,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"tools": ["*"],
"env": {
@@ -1908,7 +1908,7 @@ jobs:
engine_name: "GitHub Copilot CLI",
model: process.env.GH_AW_MODEL_AGENT_COPILOT || "",
version: "",
- agent_version: "0.0.369",
+ agent_version: "0.0.371",
workflow_name: "Go File Size Reduction Campaign (Project 64)",
experimental: false,
supports_tools_allowlist: true,
@@ -1925,7 +1925,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1972,7 +1972,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5631,9 +5631,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6579,7 +6579,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -7721,29 +7721,29 @@ jobs:
globalThis.io = io;
const { loadAgentOutput } = require('/tmp/gh-aw/scripts/load_agent_output.cjs');
function logGraphQLError(error, operation) {
- (core.error(`GraphQL Error during: ${operation}`), core.error(`Message: ${error.message}`));
+ (core.info(`GraphQL Error during: ${operation}`), core.info(`Message: ${error.message}`));
const errorList = Array.isArray(error.errors) ? error.errors : [],
hasInsufficientScopes = errorList.some(e => e && "INSUFFICIENT_SCOPES" === e.type),
hasNotFound = errorList.some(e => e && "NOT_FOUND" === e.type);
(hasInsufficientScopes
- ? core.error(
+ ? core.info(
"This looks like a token permission problem for Projects v2. The GraphQL fields used by update_project require a token with Projects access (classic PAT: scope 'project'; fine-grained PAT: Organization permission 'Projects' and access to the org). Fix: set safe-outputs.update-project.github-token to a secret PAT that can access the target org project."
)
: hasNotFound &&
/projectV2\b/.test(error.message) &&
- core.error(
+ core.info(
"GitHub returned NOT_FOUND for ProjectV2. This can mean either: (1) the project number is wrong for Projects v2, (2) the project is a classic Projects board (not Projects v2), or (3) the token does not have access to that org/user project."
),
error.errors &&
- (core.error(`Errors array (${error.errors.length} error(s)):`),
+ (core.info(`Errors array (${error.errors.length} error(s)):`),
error.errors.forEach((err, idx) => {
- (core.error(` [${idx + 1}] ${err.message}`),
- err.type && core.error(` Type: ${err.type}`),
- err.path && core.error(` Path: ${JSON.stringify(err.path)}`),
- err.locations && core.error(` Locations: ${JSON.stringify(err.locations)}`));
+ (core.info(` [${idx + 1}] ${err.message}`),
+ err.type && core.info(` Type: ${err.type}`),
+ err.path && core.info(` Path: ${JSON.stringify(err.path)}`),
+ err.locations && core.info(` Locations: ${JSON.stringify(err.locations)}`));
})),
- error.request && core.error(`Request: ${JSON.stringify(error.request, null, 2)}`),
- error.data && core.error(`Response data: ${JSON.stringify(error.data, null, 2)}`));
+ error.request && core.info(`Request: ${JSON.stringify(error.request, null, 2)}`),
+ error.data && core.info(`Response data: ${JSON.stringify(error.data, null, 2)}`));
}
function parseProjectInput(projectUrl) {
if (!projectUrl || "string" != typeof projectUrl) throw new Error(`Invalid project input: expected string, got ${typeof projectUrl}. The "project" field is required and must be a full GitHub project URL.`);
@@ -7917,10 +7917,13 @@ jobs:
const contentType = "pull_request" === output.content_type ? "PullRequest" : "issue" === output.content_type || output.issue ? "Issue" : "PullRequest",
contentQuery =
"Issue" === contentType
- ? "query($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n issue(number: $number) {\n id\n }\n }\n }"
- : "query($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n pullRequest(number: $number) {\n id\n }\n }\n }",
+ ? "query($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n issue(number: $number) {\n id\n createdAt\n closedAt\n }\n }\n }"
+ : "query($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n pullRequest(number: $number) {\n id\n createdAt\n closedAt\n }\n }\n }",
contentResult = await github.graphql(contentQuery, { owner, repo, number: contentNumber }),
- contentId = "Issue" === contentType ? contentResult.repository.issue.id : contentResult.repository.pullRequest.id,
+ contentData = "Issue" === contentType ? contentResult.repository.issue : contentResult.repository.pullRequest,
+ contentId = contentData.id,
+ createdAt = contentData.createdAt,
+ closedAt = contentData.closedAt,
existingItem = await (async function (projectId, contentId) {
let hasNextPage = !0,
endCursor = null;
@@ -7950,14 +7953,29 @@ jobs:
core.warning(`Failed to add campaign label: ${labelError.message}`);
}
}
- if (output.fields && Object.keys(output.fields).length > 0) {
+ const fieldsToUpdate = output.fields ? { ...output.fields } : {};
+ if (createdAt) {
+ const startDate = new Date(createdAt).toISOString().split("T")[0];
+ if (!fieldsToUpdate.start_date && !fieldsToUpdate["Start Date"] && !fieldsToUpdate.StartDate) {
+ fieldsToUpdate.start_date = startDate;
+ core.info(`Auto-populating Start Date from createdAt: ${startDate}`);
+ }
+ }
+ if (closedAt) {
+ const endDate = new Date(closedAt).toISOString().split("T")[0];
+ if (!fieldsToUpdate.end_date && !fieldsToUpdate["End Date"] && !fieldsToUpdate.EndDate) {
+ fieldsToUpdate.end_date = endDate;
+ core.info(`Auto-populating End Date from closedAt: ${endDate}`);
+ }
+ }
+ if (Object.keys(fieldsToUpdate).length > 0) {
const projectFields = (
await github.graphql(
- "query($projectId: ID!) {\n node(id: $projectId) {\n ... on ProjectV2 {\n fields(first: 20) {\n nodes {\n ... on ProjectV2Field {\n id\n name\n }\n ... on ProjectV2SingleSelectField {\n id\n name\n options {\n id\n name\n color\n }\n }\n }\n }\n }\n }\n }",
+ "query($projectId: ID!) {\n node(id: $projectId) {\n ... on ProjectV2 {\n fields(first: 20) {\n nodes {\n ... on ProjectV2Field {\n id\n name\n dataType\n }\n ... on ProjectV2SingleSelectField {\n id\n name\n dataType\n options {\n id\n name\n color\n }\n }\n }\n }\n }\n }\n }",
{ projectId }
)
).node.fields.nodes;
- for (const [fieldName, fieldValue] of Object.entries(output.fields)) {
+ for (const [fieldName, fieldValue] of Object.entries(fieldsToUpdate)) {
const normalizedFieldName = fieldName
.split(/[\s_-]+/)
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
@@ -7989,7 +8007,9 @@ jobs:
core.warning(`Failed to create field "${fieldName}": ${createError.message}`);
continue;
}
- if (field.options) {
+ if (field.dataType === "DATE") {
+ valueToSet = { date: String(fieldValue) };
+ } else if (field.options) {
let option = field.options.find(o => o.name === fieldValue);
if (!option)
try {
diff --git a/.github/workflows/go-file-size-reduction.campaign.g.lock.yml b/.github/workflows/go-file-size-reduction.campaign.g.lock.yml
index 85b2277c0a..fa3379507f 100644
--- a/.github/workflows/go-file-size-reduction.campaign.g.lock.yml
+++ b/.github/workflows/go-file-size-reduction.campaign.g.lock.yml
@@ -239,7 +239,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -283,7 +283,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1859,7 +1859,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"tools": ["*"],
"env": {
@@ -1908,7 +1908,7 @@ jobs:
engine_name: "GitHub Copilot CLI",
model: process.env.GH_AW_MODEL_AGENT_COPILOT || "",
version: "",
- agent_version: "0.0.369",
+ agent_version: "0.0.371",
workflow_name: "Go File Size Reduction Campaign",
experimental: false,
supports_tools_allowlist: true,
@@ -1925,7 +1925,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1972,7 +1972,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5631,9 +5631,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6579,7 +6579,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -7721,29 +7721,29 @@ jobs:
globalThis.io = io;
const { loadAgentOutput } = require('/tmp/gh-aw/scripts/load_agent_output.cjs');
function logGraphQLError(error, operation) {
- (core.error(`GraphQL Error during: ${operation}`), core.error(`Message: ${error.message}`));
+ (core.info(`GraphQL Error during: ${operation}`), core.info(`Message: ${error.message}`));
const errorList = Array.isArray(error.errors) ? error.errors : [],
hasInsufficientScopes = errorList.some(e => e && "INSUFFICIENT_SCOPES" === e.type),
hasNotFound = errorList.some(e => e && "NOT_FOUND" === e.type);
(hasInsufficientScopes
- ? core.error(
+ ? core.info(
"This looks like a token permission problem for Projects v2. The GraphQL fields used by update_project require a token with Projects access (classic PAT: scope 'project'; fine-grained PAT: Organization permission 'Projects' and access to the org). Fix: set safe-outputs.update-project.github-token to a secret PAT that can access the target org project."
)
: hasNotFound &&
/projectV2\b/.test(error.message) &&
- core.error(
+ core.info(
"GitHub returned NOT_FOUND for ProjectV2. This can mean either: (1) the project number is wrong for Projects v2, (2) the project is a classic Projects board (not Projects v2), or (3) the token does not have access to that org/user project."
),
error.errors &&
- (core.error(`Errors array (${error.errors.length} error(s)):`),
+ (core.info(`Errors array (${error.errors.length} error(s)):`),
error.errors.forEach((err, idx) => {
- (core.error(` [${idx + 1}] ${err.message}`),
- err.type && core.error(` Type: ${err.type}`),
- err.path && core.error(` Path: ${JSON.stringify(err.path)}`),
- err.locations && core.error(` Locations: ${JSON.stringify(err.locations)}`));
+ (core.info(` [${idx + 1}] ${err.message}`),
+ err.type && core.info(` Type: ${err.type}`),
+ err.path && core.info(` Path: ${JSON.stringify(err.path)}`),
+ err.locations && core.info(` Locations: ${JSON.stringify(err.locations)}`));
})),
- error.request && core.error(`Request: ${JSON.stringify(error.request, null, 2)}`),
- error.data && core.error(`Response data: ${JSON.stringify(error.data, null, 2)}`));
+ error.request && core.info(`Request: ${JSON.stringify(error.request, null, 2)}`),
+ error.data && core.info(`Response data: ${JSON.stringify(error.data, null, 2)}`));
}
function parseProjectInput(projectUrl) {
if (!projectUrl || "string" != typeof projectUrl) throw new Error(`Invalid project input: expected string, got ${typeof projectUrl}. The "project" field is required and must be a full GitHub project URL.`);
@@ -7917,10 +7917,13 @@ jobs:
const contentType = "pull_request" === output.content_type ? "PullRequest" : "issue" === output.content_type || output.issue ? "Issue" : "PullRequest",
contentQuery =
"Issue" === contentType
- ? "query($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n issue(number: $number) {\n id\n }\n }\n }"
- : "query($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n pullRequest(number: $number) {\n id\n }\n }\n }",
+ ? "query($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n issue(number: $number) {\n id\n createdAt\n closedAt\n }\n }\n }"
+ : "query($owner: String!, $repo: String!, $number: Int!) {\n repository(owner: $owner, name: $repo) {\n pullRequest(number: $number) {\n id\n createdAt\n closedAt\n }\n }\n }",
contentResult = await github.graphql(contentQuery, { owner, repo, number: contentNumber }),
- contentId = "Issue" === contentType ? contentResult.repository.issue.id : contentResult.repository.pullRequest.id,
+ contentData = "Issue" === contentType ? contentResult.repository.issue : contentResult.repository.pullRequest,
+ contentId = contentData.id,
+ createdAt = contentData.createdAt,
+ closedAt = contentData.closedAt,
existingItem = await (async function (projectId, contentId) {
let hasNextPage = !0,
endCursor = null;
@@ -7950,14 +7953,29 @@ jobs:
core.warning(`Failed to add campaign label: ${labelError.message}`);
}
}
- if (output.fields && Object.keys(output.fields).length > 0) {
+ const fieldsToUpdate = output.fields ? { ...output.fields } : {};
+ if (createdAt) {
+ const startDate = new Date(createdAt).toISOString().split("T")[0];
+ if (!fieldsToUpdate.start_date && !fieldsToUpdate["Start Date"] && !fieldsToUpdate.StartDate) {
+ fieldsToUpdate.start_date = startDate;
+ core.info(`Auto-populating Start Date from createdAt: ${startDate}`);
+ }
+ }
+ if (closedAt) {
+ const endDate = new Date(closedAt).toISOString().split("T")[0];
+ if (!fieldsToUpdate.end_date && !fieldsToUpdate["End Date"] && !fieldsToUpdate.EndDate) {
+ fieldsToUpdate.end_date = endDate;
+ core.info(`Auto-populating End Date from closedAt: ${endDate}`);
+ }
+ }
+ if (Object.keys(fieldsToUpdate).length > 0) {
const projectFields = (
await github.graphql(
- "query($projectId: ID!) {\n node(id: $projectId) {\n ... on ProjectV2 {\n fields(first: 20) {\n nodes {\n ... on ProjectV2Field {\n id\n name\n }\n ... on ProjectV2SingleSelectField {\n id\n name\n options {\n id\n name\n color\n }\n }\n }\n }\n }\n }\n }",
+ "query($projectId: ID!) {\n node(id: $projectId) {\n ... on ProjectV2 {\n fields(first: 20) {\n nodes {\n ... on ProjectV2Field {\n id\n name\n dataType\n }\n ... on ProjectV2SingleSelectField {\n id\n name\n dataType\n options {\n id\n name\n color\n }\n }\n }\n }\n }\n }\n }",
{ projectId }
)
).node.fields.nodes;
- for (const [fieldName, fieldValue] of Object.entries(output.fields)) {
+ for (const [fieldName, fieldValue] of Object.entries(fieldsToUpdate)) {
const normalizedFieldName = fieldName
.split(/[\s_-]+/)
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
@@ -7989,7 +8007,9 @@ jobs:
core.warning(`Failed to create field "${fieldName}": ${createError.message}`);
continue;
}
- if (field.options) {
+ if (field.dataType === "DATE") {
+ valueToSet = { date: String(fieldValue) };
+ } else if (field.options) {
let option = field.options.find(o => o.name === fieldValue);
if (!option)
try {
diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml
index f6b6b3329d..b5b7f21f4a 100644
--- a/.github/workflows/go-logger.lock.yml
+++ b/.github/workflows/go-logger.lock.yml
@@ -282,7 +282,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -312,7 +312,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1831,7 +1831,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1870,7 +1870,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Go Logger Enhancement",
experimental: true,
supports_tools_allowlist: true,
@@ -1887,7 +1887,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1934,7 +1934,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5389,9 +5389,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6354,7 +6354,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/go-pattern-detector.lock.yml b/.github/workflows/go-pattern-detector.lock.yml
index 3eaf35c0d1..d1298f0c25 100644
--- a/.github/workflows/go-pattern-detector.lock.yml
+++ b/.github/workflows/go-pattern-detector.lock.yml
@@ -257,7 +257,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -287,7 +287,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
docker_pull_with_retry mcp/ast-grep:latest
- name: Write Safe Outputs Config
run: |
@@ -1828,7 +1828,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1867,7 +1867,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Go Pattern Detector",
experimental: true,
supports_tools_allowlist: true,
@@ -1884,7 +1884,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1931,7 +1931,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5235,9 +5235,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6220,7 +6220,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/instructions-janitor.lock.yml b/.github/workflows/instructions-janitor.lock.yml
index 075bdb6418..c593b90958 100644
--- a/.github/workflows/instructions-janitor.lock.yml
+++ b/.github/workflows/instructions-janitor.lock.yml
@@ -266,7 +266,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -296,7 +296,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1815,7 +1815,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1854,7 +1854,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Instructions Janitor",
experimental: true,
supports_tools_allowlist: true,
@@ -1871,7 +1871,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1918,7 +1918,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5269,9 +5269,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6234,7 +6234,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/instructions-janitor.md b/.github/workflows/instructions-janitor.md
index 68b7fc4590..bee95127b5 100644
--- a/.github/workflows/instructions-janitor.md
+++ b/.github/workflows/instructions-janitor.md
@@ -11,7 +11,7 @@ permissions:
pull-requests: read
engine: claude
-strict: false
+strict: true
network:
allowed:
diff --git a/.github/workflows/issue-arborist.lock.yml b/.github/workflows/issue-arborist.lock.yml
index 1f2e15240d..fe76909399 100644
--- a/.github/workflows/issue-arborist.lock.yml
+++ b/.github/workflows/issue-arborist.lock.yml
@@ -254,7 +254,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -292,7 +292,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1924,7 +1924,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=issues",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -1947,7 +1947,7 @@ jobs:
engine_name: "Codex",
model: process.env.GH_AW_MODEL_AGENT_CODEX || "",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "Issue Arborist",
experimental: true,
supports_tools_allowlist: true,
@@ -1964,7 +1964,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2011,7 +2011,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5551,9 +5551,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-issue-arborist
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6502,7 +6661,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Run Codex
run: |
set -o pipefail
diff --git a/.github/workflows/issue-arborist.md b/.github/workflows/issue-arborist.md
index 432be784c8..b4be948a09 100644
--- a/.github/workflows/issue-arborist.md
+++ b/.github/workflows/issue-arborist.md
@@ -8,7 +8,7 @@ permissions:
contents: read
issues: read
engine: codex
-strict: false
+strict: true
network:
allowed:
- defaults
diff --git a/.github/workflows/lockfile-stats.lock.yml b/.github/workflows/lockfile-stats.lock.yml
index 4106eeeecb..58804996dd 100644
--- a/.github/workflows/lockfile-stats.lock.yml
+++ b/.github/workflows/lockfile-stats.lock.yml
@@ -270,7 +270,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -300,7 +300,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1809,7 +1809,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1848,7 +1848,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Lockfile Statistics Analysis Agent",
experimental: true,
supports_tools_allowlist: true,
@@ -1865,7 +1865,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1912,7 +1912,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5522,9 +5522,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6480,7 +6480,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml
index f2aa070bbb..dc89da5530 100644
--- a/.github/workflows/poem-bot.lock.yml
+++ b/.github/workflows/poem-bot.lock.yml
@@ -998,7 +998,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -1042,7 +1042,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -3068,7 +3068,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"tools": ["*"],
"env": {
@@ -3117,7 +3117,7 @@ jobs:
engine_name: "GitHub Copilot CLI",
model: "gpt-5",
version: "",
- agent_version: "0.0.369",
+ agent_version: "0.0.371",
workflow_name: "Poem Bot - A Creative Agentic Workflow",
experimental: false,
supports_tools_allowlist: true,
@@ -3134,7 +3134,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -3181,7 +3181,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6834,9 +6834,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7803,7 +7803,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -10633,7 +10633,7 @@ jobs:
};
EOF_4d21ccbd
- cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_006d32d7'
+ cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_60283df2'
// @ts-check
///
@@ -10718,11 +10718,12 @@ jobs:
* @param {boolean} params.canUpdateStatus - Whether status updates are allowed
* @param {boolean} params.canUpdateTitle - Whether title updates are allowed
* @param {boolean} params.canUpdateBody - Whether body updates are allowed
+ * @param {boolean} [params.canUpdateLabels] - Whether label updates are allowed
* @param {boolean} params.supportsStatus - Whether this type supports status
* @returns {{hasUpdates: boolean, updateData: any, logMessages: string[]}}
*/
function buildUpdateData(params) {
- const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, supportsStatus } = params;
+ const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, canUpdateLabels, supportsStatus } = params;
/** @type {any} */
const updateData = {};
@@ -10772,6 +10773,17 @@ jobs:
}
}
+ // Handle labels update
+ if (canUpdateLabels && item.labels !== undefined) {
+ if (Array.isArray(item.labels)) {
+ updateData.labels = item.labels;
+ hasUpdates = true;
+ logMessages.push(`Will update labels to: ${item.labels.join(", ")}`);
+ } else {
+ logMessages.push("Invalid labels value: must be an array");
+ }
+ }
+
return { hasUpdates, updateData, logMessages };
}
@@ -10816,12 +10828,13 @@ jobs:
const canUpdateStatus = process.env.GH_AW_UPDATE_STATUS === "true";
const canUpdateTitle = process.env.GH_AW_UPDATE_TITLE === "true";
const canUpdateBody = process.env.GH_AW_UPDATE_BODY === "true";
+ const canUpdateLabels = process.env.GH_AW_UPDATE_LABELS === "true";
core.info(`Update target configuration: ${updateTarget}`);
if (supportsStatus) {
- core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
} else {
- core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
}
// Check context validity
@@ -10865,6 +10878,7 @@ jobs:
canUpdateStatus,
canUpdateTitle,
canUpdateBody,
+ canUpdateLabels,
supportsStatus,
});
@@ -10986,7 +11000,7 @@ jobs:
createGetSummaryLine,
};
- EOF_006d32d7
+ EOF_60283df2
- name: Create Issue
id: create_issue
if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_issue'))
diff --git a/.github/workflows/prompt-clustering-analysis.lock.yml b/.github/workflows/prompt-clustering-analysis.lock.yml
index 6961e6e7b8..f3b1398ee6 100644
--- a/.github/workflows/prompt-clustering-analysis.lock.yml
+++ b/.github/workflows/prompt-clustering-analysis.lock.yml
@@ -343,7 +343,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -373,7 +373,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1886,7 +1886,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=repos,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1925,7 +1925,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Copilot Agent Prompt Clustering Analysis",
experimental: true,
supports_tools_allowlist: true,
@@ -1942,7 +1942,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github","python"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1989,7 +1989,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6157,9 +6157,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7115,7 +7115,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/prompt-clustering-analysis.md b/.github/workflows/prompt-clustering-analysis.md
index 1f7f503774..ab6d62164c 100644
--- a/.github/workflows/prompt-clustering-analysis.md
+++ b/.github/workflows/prompt-clustering-analysis.md
@@ -11,7 +11,7 @@ permissions:
issues: read
actions: read
engine: claude
-strict: false
+strict: true
network:
allowed:
diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml
index 03e69ac517..0274cd8d19 100644
--- a/.github/workflows/q.lock.yml
+++ b/.github/workflows/q.lock.yml
@@ -1045,7 +1045,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -1089,7 +1089,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -2653,7 +2653,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests,actions,discussions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"tools": ["*"],
"env": {
@@ -2721,7 +2721,7 @@ jobs:
engine_name: "GitHub Copilot CLI",
model: process.env.GH_AW_MODEL_AGENT_COPILOT || "",
version: "",
- agent_version: "0.0.369",
+ agent_version: "0.0.371",
workflow_name: "Q",
experimental: false,
supports_tools_allowlist: true,
@@ -2738,7 +2738,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2785,7 +2785,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6757,9 +6757,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7718,7 +7718,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
diff --git a/.github/workflows/safe-output-health.lock.yml b/.github/workflows/safe-output-health.lock.yml
index fb5b54e285..3f39e4b75d 100644
--- a/.github/workflows/safe-output-health.lock.yml
+++ b/.github/workflows/safe-output-health.lock.yml
@@ -295,7 +295,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -325,7 +325,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1838,7 +1838,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1877,7 +1877,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Safe Output Health Monitor",
experimental: true,
supports_tools_allowlist: true,
@@ -1894,7 +1894,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1941,7 +1941,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5691,9 +5691,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6649,7 +6649,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/schema-consistency-checker.lock.yml b/.github/workflows/schema-consistency-checker.lock.yml
index 29bc0a385c..111f714b2e 100644
--- a/.github/workflows/schema-consistency-checker.lock.yml
+++ b/.github/workflows/schema-consistency-checker.lock.yml
@@ -273,7 +273,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1812,7 +1812,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Schema Consistency Checker",
experimental: true,
supports_tools_allowlist: true,
@@ -1829,7 +1829,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1876,7 +1876,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5458,9 +5458,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6416,7 +6416,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml
index 94f08449de..6d9cbef6b3 100644
--- a/.github/workflows/scout.lock.yml
+++ b/.github/workflows/scout.lock.yml
@@ -1055,7 +1055,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -1085,7 +1085,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
docker_pull_with_retry mcp/arxiv-mcp-server
docker_pull_with_retry mcp/context7
- name: Write Safe Outputs Config
@@ -2609,7 +2609,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -2663,7 +2663,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Scout",
experimental: true,
supports_tools_allowlist: true,
@@ -2680,7 +2680,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2727,7 +2727,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6317,9 +6317,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7274,7 +7274,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/security-fix-pr.lock.yml b/.github/workflows/security-fix-pr.lock.yml
index 502ead04f2..2dde2170f9 100644
--- a/.github/workflows/security-fix-pr.lock.yml
+++ b/.github/workflows/security-fix-pr.lock.yml
@@ -274,7 +274,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -304,7 +304,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1823,7 +1823,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,code_security,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1862,7 +1862,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Security Fix PR",
experimental: true,
supports_tools_allowlist: true,
@@ -1879,7 +1879,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1926,7 +1926,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5279,9 +5279,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6244,7 +6244,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/semantic-function-refactor.lock.yml b/.github/workflows/semantic-function-refactor.lock.yml
index d2bad32fcb..eae41e8b38 100644
--- a/.github/workflows/semantic-function-refactor.lock.yml
+++ b/.github/workflows/semantic-function-refactor.lock.yml
@@ -255,7 +255,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -285,7 +285,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1853,7 +1853,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1892,7 +1892,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Semantic Function Refactoring",
experimental: true,
supports_tools_allowlist: true,
@@ -1909,7 +1909,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1956,7 +1956,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5712,9 +5712,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6663,7 +6663,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml
index 56fb86feda..b752acbc73 100644
--- a/.github/workflows/smoke-claude.lock.yml
+++ b/.github/workflows/smoke-claude.lock.yml
@@ -694,7 +694,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -724,7 +724,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
docker_pull_with_retry mcr.microsoft.com/playwright/mcp
- name: Write Safe Outputs Config
run: |
@@ -2330,7 +2330,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=repos,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -2398,7 +2398,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Smoke Claude",
experimental: true,
supports_tools_allowlist: true,
@@ -2415,7 +2415,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github","playwright"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2462,7 +2462,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5839,9 +5839,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6796,7 +6796,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/smoke-codex-firewall.md b/.github/workflows/smoke-codex-firewall.md
index cca5656da5..048b420444 100644
--- a/.github/workflows/smoke-codex-firewall.md
+++ b/.github/workflows/smoke-codex-firewall.md
@@ -14,7 +14,7 @@ permissions:
pull-requests: read
name: Smoke Codex Firewall
engine: codex
-strict: false
+strict: true
network:
allowed:
- defaults
diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml
index 7dc3b12082..1b4b483a6a 100644
--- a/.github/workflows/smoke-codex.lock.yml
+++ b/.github/workflows/smoke-codex.lock.yml
@@ -682,7 +682,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Install awf binary
run: |
echo "Installing awf from release: v0.7.0"
@@ -720,7 +720,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
docker_pull_with_retry mcr.microsoft.com/playwright/mcp
- name: Write Safe Outputs Config
run: |
@@ -2362,7 +2362,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"]
@@ -2414,7 +2414,7 @@ jobs:
engine_name: "Codex",
model: process.env.GH_AW_MODEL_AGENT_CODEX || "",
version: "",
- agent_version: "0.73.0",
+ agent_version: "0.75.0",
workflow_name: "Smoke Codex",
experimental: true,
supports_tools_allowlist: true,
@@ -2431,7 +2431,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github","playwright"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2478,7 +2478,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5872,9 +5872,168 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
+ summary += "\n";
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `${validAllowedRequests} allowed | `;
+ summary += `${validDeniedRequests} blocked | `;
+ summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
+ if (uniqueDomainCount > 0) {
+ summary += "| Domain | Allowed | Denied |\n";
+ summary += "|--------|---------|--------|\n";
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ summary += `| ${domain} | ${stats.allowed} | ${stats.denied} |\n`;
+ }
+ } else {
+ summary += "No firewall activity detected.\n";
+ }
+ summary += "\n \n\n";
+ return summary;
+ }
+ const isDirectExecution = typeof module === "undefined" || (typeof require !== "undefined" && typeof require.main !== "undefined" && require.main === module);
+ if (isDirectExecution) {
+ main();
+ }
+ - name: Upload Firewall Logs
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
+ with:
+ name: firewall-logs-smoke-codex
+ path: /tmp/gh-aw/sandbox/firewall/logs/
+ if-no-files-found: ignore
+ - name: Parse firewall logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ function sanitizeWorkflowName(name) {
+ return name
+ .toLowerCase()
+ .replace(/[:\\/\s]/g, "-")
+ .replace(/[^a-z0-9._-]/g, "-");
+ }
+ function main() {
+ const fs = require("fs");
+ const path = require("path");
+ try {
+ const squidLogsDir = `/tmp/gh-aw/sandbox/firewall/logs/`;
+ if (!fs.existsSync(squidLogsDir)) {
+ core.info(`No firewall logs directory found at: ${squidLogsDir}`);
+ return;
+ }
+ const files = fs.readdirSync(squidLogsDir).filter(file => file.endsWith(".log"));
+ if (files.length === 0) {
+ core.info(`No firewall log files found in: ${squidLogsDir}`);
+ return;
+ }
+ core.info(`Found ${files.length} firewall log file(s)`);
+ let totalRequests = 0;
+ let allowedRequests = 0;
+ let deniedRequests = 0;
+ const allowedDomains = new Set();
+ const deniedDomains = new Set();
+ const requestsByDomain = new Map();
+ for (const file of files) {
+ const filePath = path.join(squidLogsDir, file);
+ core.info(`Parsing firewall log: ${file}`);
+ const content = fs.readFileSync(filePath, "utf8");
+ const lines = content.split("\n").filter(line => line.trim());
+ for (const line of lines) {
+ const entry = parseFirewallLogLine(line);
+ if (!entry) {
+ continue;
+ }
+ totalRequests++;
+ const isAllowed = isRequestAllowed(entry.decision, entry.status);
+ if (isAllowed) {
+ allowedRequests++;
+ allowedDomains.add(entry.domain);
+ } else {
+ deniedRequests++;
+ deniedDomains.add(entry.domain);
+ }
+ if (!requestsByDomain.has(entry.domain)) {
+ requestsByDomain.set(entry.domain, { allowed: 0, denied: 0 });
+ }
+ const domainStats = requestsByDomain.get(entry.domain);
+ if (isAllowed) {
+ domainStats.allowed++;
+ } else {
+ domainStats.denied++;
+ }
+ }
+ }
+ const summary = generateFirewallSummary({
+ totalRequests,
+ allowedRequests,
+ deniedRequests,
+ allowedDomains: Array.from(allowedDomains).sort(),
+ deniedDomains: Array.from(deniedDomains).sort(),
+ requestsByDomain,
+ });
+ core.summary.addRaw(summary).write();
+ core.info("Firewall log summary generated successfully");
+ } catch (error) {
+ core.setFailed(error instanceof Error ? error : String(error));
+ }
+ }
+ function parseFirewallLogLine(line) {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed.startsWith("#")) {
+ return null;
+ }
+ const fields = trimmed.match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (!fields || fields.length < 10) {
+ return null;
+ }
+ const timestamp = fields[0];
+ if (!/^\d+(\.\d+)?$/.test(timestamp)) {
+ return null;
+ }
+ return {
+ timestamp,
+ clientIpPort: fields[1],
+ domain: fields[2],
+ destIpPort: fields[3],
+ proto: fields[4],
+ method: fields[5],
+ status: fields[6],
+ decision: fields[7],
+ url: fields[8],
+ userAgent: fields[9]?.replace(/^"|"$/g, "") || "-",
+ };
+ }
+ function isRequestAllowed(decision, status) {
+ const statusCode = parseInt(status, 10);
+ if (statusCode === 200 || statusCode === 206 || statusCode === 304) {
+ return true;
+ }
+ if (decision.includes("TCP_TUNNEL") || decision.includes("TCP_HIT") || decision.includes("TCP_MISS")) {
+ return true;
+ }
+ if (decision.includes("NONE_NONE") || decision.includes("TCP_DENIED") || statusCode === 403 || statusCode === 407) {
+ return false;
+ }
+ return false;
+ }
+ function generateFirewallSummary(analysis) {
+ const { totalRequests, requestsByDomain } = analysis;
+ const validDomains = Array.from(requestsByDomain.keys())
+ .filter(domain => domain !== "-")
+ .sort();
+ const uniqueDomainCount = validDomains.length;
+ let validAllowedRequests = 0;
+ let validDeniedRequests = 0;
+ for (const domain of validDomains) {
+ const stats = requestsByDomain.get(domain);
+ validAllowedRequests += stats.allowed;
+ validDeniedRequests += stats.denied;
+ }
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6829,7 +6988,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Codex
- run: npm install -g @openai/codex@0.73.0
+ run: npm install -g @openai/codex@0.75.0
- name: Run Codex
run: |
set -o pipefail
diff --git a/.github/workflows/smoke-codex.md b/.github/workflows/smoke-codex.md
index 50c0ced02e..d90060fee8 100644
--- a/.github/workflows/smoke-codex.md
+++ b/.github/workflows/smoke-codex.md
@@ -14,7 +14,7 @@ permissions:
pull-requests: read
name: Smoke Codex
engine: codex
-strict: false
+strict: true
network:
allowed:
- defaults
diff --git a/.github/workflows/smoke-copilot-playwright.md b/.github/workflows/smoke-copilot-playwright.md
index 7b0a1855e5..5fe80c96e3 100644
--- a/.github/workflows/smoke-copilot-playwright.md
+++ b/.github/workflows/smoke-copilot-playwright.md
@@ -56,7 +56,7 @@ safe-outputs:
run-success: "📰 VERDICT: [{workflow_name}]({run_url}) has concluded. All systems operational. This is a developing story. 🎤"
run-failure: "📰 DEVELOPING STORY: [{workflow_name}]({run_url}) reports {status}. Our correspondents are investigating the incident..."
timeout-minutes: 5
-strict: false
+strict: true
steps:
# Pre-flight Docker container test for Playwright MCP
- name: Pre-flight Playwright MCP Test
diff --git a/.github/workflows/smoke-copilot.md b/.github/workflows/smoke-copilot.md
index a4bca74b7b..e04e4d56b1 100644
--- a/.github/workflows/smoke-copilot.md
+++ b/.github/workflows/smoke-copilot.md
@@ -40,7 +40,7 @@ safe-outputs:
run-success: "📰 VERDICT: [{workflow_name}]({run_url}) has concluded. All systems operational. This is a developing story. 🎤"
run-failure: "📰 DEVELOPING STORY: [{workflow_name}]({run_url}) reports {status}. Our correspondents are investigating the incident..."
timeout-minutes: 5
-strict: false
+strict: true
---
# Smoke Test: Copilot Engine Validation
diff --git a/.github/workflows/smoke-detector.lock.yml b/.github/workflows/smoke-detector.lock.yml
index 3b730a0607..2884b16e34 100644
--- a/.github/workflows/smoke-detector.lock.yml
+++ b/.github/workflows/smoke-detector.lock.yml
@@ -717,7 +717,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -747,7 +747,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -2317,7 +2317,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests,actions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -2356,7 +2356,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Smoke Detector - Smoke Test Failure Investigator",
experimental: true,
supports_tools_allowlist: true,
@@ -2373,7 +2373,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2420,7 +2420,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5954,9 +5954,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6913,7 +6913,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/smoke-detector.md b/.github/workflows/smoke-detector.md
index e2fa7a658f..205c55bd5a 100644
--- a/.github/workflows/smoke-detector.md
+++ b/.github/workflows/smoke-detector.md
@@ -56,7 +56,7 @@ tools:
cache-memory: true
github:
toolsets: [default, actions]
-strict: false
+strict: true
---
# Smoke Detector - Smoke Test Failure Investigator
diff --git a/.github/workflows/spec-kit-execute.md b/.github/workflows/spec-kit-execute.md
index b03a7200b8..be3433f6f5 100644
--- a/.github/workflows/spec-kit-execute.md
+++ b/.github/workflows/spec-kit-execute.md
@@ -13,7 +13,7 @@ permissions:
tracker-id: spec-kit-execute
engine: copilot
-strict: false
+strict: true
safe-outputs:
create-pull-request:
diff --git a/.github/workflows/spec-kit-executor.md b/.github/workflows/spec-kit-executor.md
index 2197726f1c..fdf82758b2 100644
--- a/.github/workflows/spec-kit-executor.md
+++ b/.github/workflows/spec-kit-executor.md
@@ -14,7 +14,7 @@ permissions:
tracker-id: spec-kit-executor
engine: copilot
-strict: false
+strict: true
network:
allowed:
diff --git a/.github/workflows/speckit-dispatcher.md b/.github/workflows/speckit-dispatcher.md
index d0f74880f4..adb251c301 100644
--- a/.github/workflows/speckit-dispatcher.md
+++ b/.github/workflows/speckit-dispatcher.md
@@ -13,7 +13,7 @@ permissions:
pull-requests: read
engine: copilot
-strict: false
+strict: true
imports:
- ../agents/speckit-dispatcher.agent.md
diff --git a/.github/workflows/stale-repo-identifier.md b/.github/workflows/stale-repo-identifier.md
index 790c908ab4..aa73bb9546 100644
--- a/.github/workflows/stale-repo-identifier.md
+++ b/.github/workflows/stale-repo-identifier.md
@@ -18,7 +18,7 @@ permissions:
actions: read
engine: copilot
-strict: false
+strict: true
timeout-minutes: 45
imports:
diff --git a/.github/workflows/static-analysis-report.lock.yml b/.github/workflows/static-analysis-report.lock.yml
index d52f9fa2a6..3df98376ed 100644
--- a/.github/workflows/static-analysis-report.lock.yml
+++ b/.github/workflows/static-analysis-report.lock.yml
@@ -288,7 +288,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -318,7 +318,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1831,7 +1831,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests,actions",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1870,7 +1870,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Static Analysis Report",
experimental: true,
supports_tools_allowlist: true,
@@ -1887,7 +1887,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1934,7 +1934,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5542,9 +5542,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6500,7 +6500,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/sub-issue-closer.lock.yml b/.github/workflows/sub-issue-closer.lock.yml
index 4246aed312..62aa303e5f 100644
--- a/.github/workflows/sub-issue-closer.lock.yml
+++ b/.github/workflows/sub-issue-closer.lock.yml
@@ -239,7 +239,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -283,7 +283,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1837,7 +1837,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=issues",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"tools": ["*"],
"env": {
@@ -1886,7 +1886,7 @@ jobs:
engine_name: "GitHub Copilot CLI",
model: process.env.GH_AW_MODEL_AGENT_COPILOT || "",
version: "",
- agent_version: "0.0.369",
+ agent_version: "0.0.371",
workflow_name: "Sub-Issue Closer",
experimental: false,
supports_tools_allowlist: true,
@@ -1903,7 +1903,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1950,7 +1950,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5581,9 +5581,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6529,7 +6529,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -7428,7 +7428,7 @@ jobs:
};
EOF_4d21ccbd
- cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_006d32d7'
+ cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_60283df2'
// @ts-check
///
@@ -7513,11 +7513,12 @@ jobs:
* @param {boolean} params.canUpdateStatus - Whether status updates are allowed
* @param {boolean} params.canUpdateTitle - Whether title updates are allowed
* @param {boolean} params.canUpdateBody - Whether body updates are allowed
+ * @param {boolean} [params.canUpdateLabels] - Whether label updates are allowed
* @param {boolean} params.supportsStatus - Whether this type supports status
* @returns {{hasUpdates: boolean, updateData: any, logMessages: string[]}}
*/
function buildUpdateData(params) {
- const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, supportsStatus } = params;
+ const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, canUpdateLabels, supportsStatus } = params;
/** @type {any} */
const updateData = {};
@@ -7567,6 +7568,17 @@ jobs:
}
}
+ // Handle labels update
+ if (canUpdateLabels && item.labels !== undefined) {
+ if (Array.isArray(item.labels)) {
+ updateData.labels = item.labels;
+ hasUpdates = true;
+ logMessages.push(`Will update labels to: ${item.labels.join(", ")}`);
+ } else {
+ logMessages.push("Invalid labels value: must be an array");
+ }
+ }
+
return { hasUpdates, updateData, logMessages };
}
@@ -7611,12 +7623,13 @@ jobs:
const canUpdateStatus = process.env.GH_AW_UPDATE_STATUS === "true";
const canUpdateTitle = process.env.GH_AW_UPDATE_TITLE === "true";
const canUpdateBody = process.env.GH_AW_UPDATE_BODY === "true";
+ const canUpdateLabels = process.env.GH_AW_UPDATE_LABELS === "true";
core.info(`Update target configuration: ${updateTarget}`);
if (supportsStatus) {
- core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
} else {
- core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
}
// Check context validity
@@ -7660,6 +7673,7 @@ jobs:
canUpdateStatus,
canUpdateTitle,
canUpdateBody,
+ canUpdateLabels,
supportsStatus,
});
@@ -7781,7 +7795,7 @@ jobs:
createGetSummaryLine,
};
- EOF_006d32d7
+ EOF_60283df2
- name: Add Comment
id: add_comment
if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'add_comment'))
diff --git a/.github/workflows/typist.lock.yml b/.github/workflows/typist.lock.yml
index 4b39555f3d..94af3201ba 100644
--- a/.github/workflows/typist.lock.yml
+++ b/.github/workflows/typist.lock.yml
@@ -266,7 +266,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -296,7 +296,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1805,7 +1805,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -1857,7 +1857,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Typist - Go Type Analysis",
experimental: true,
supports_tools_allowlist: true,
@@ -1874,7 +1874,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -1921,7 +1921,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -5710,9 +5710,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6661,7 +6661,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml
index def8af6062..aea8b04294 100644
--- a/.github/workflows/unbloat-docs.lock.yml
+++ b/.github/workflows/unbloat-docs.lock.yml
@@ -701,7 +701,7 @@ jobs:
which awf
awf --version
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Downloading container images
run: |
set -e
@@ -731,7 +731,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
docker_pull_with_retry mcr.microsoft.com/playwright/mcp
- name: Write Safe Outputs Config
run: |
@@ -2316,7 +2316,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "$GITHUB_MCP_SERVER_TOKEN"
@@ -2373,7 +2373,7 @@ jobs:
engine_name: "Claude Code",
model: process.env.GH_AW_MODEL_AGENT_CLAUDE || "",
version: "",
- agent_version: "2.0.71",
+ agent_version: "2.0.73",
workflow_name: "Documentation Unbloat",
experimental: true,
supports_tools_allowlist: true,
@@ -2390,7 +2390,7 @@ jobs:
network_mode: "defaults",
allowed_domains: ["defaults","github"],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2437,7 +2437,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -6036,9 +6036,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -7007,7 +7007,7 @@ jobs:
node-version: '24'
package-manager-cache: false
- name: Install Claude Code CLI
- run: npm install -g @anthropic-ai/claude-code@2.0.71
+ run: npm install -g @anthropic-ai/claude-code@2.0.73
- name: Execute Claude Code CLI
id: agentic_execution
# Allowed tools (sorted):
diff --git a/.github/workflows/unbloat-docs.md b/.github/workflows/unbloat-docs.md
index 58b87721a5..c7060604b8 100644
--- a/.github/workflows/unbloat-docs.md
+++ b/.github/workflows/unbloat-docs.md
@@ -19,7 +19,7 @@ permissions:
pull-requests: read
issues: read
-strict: false
+strict: true
# AI engine configuration
engine:
diff --git a/.github/workflows/workflow-generator.lock.yml b/.github/workflows/workflow-generator.lock.yml
index 46400e300e..730f37980c 100644
--- a/.github/workflows/workflow-generator.lock.yml
+++ b/.github/workflows/workflow-generator.lock.yml
@@ -287,7 +287,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -331,7 +331,7 @@ jobs:
done
}
- docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.25.0
+ docker_pull_with_retry ghcr.io/github/github-mcp-server:v0.26.3
- name: Write Safe Outputs Config
run: |
mkdir -p /tmp/gh-aw/safeoutputs
@@ -1887,7 +1887,7 @@ jobs:
"GITHUB_READ_ONLY=1",
"-e",
"GITHUB_TOOLSETS=context,repos,issues,pull_requests",
- "ghcr.io/github/github-mcp-server:v0.25.0"
+ "ghcr.io/github/github-mcp-server:v0.26.3"
],
"tools": ["*"],
"env": {
@@ -1936,7 +1936,7 @@ jobs:
engine_name: "GitHub Copilot CLI",
model: process.env.GH_AW_MODEL_AGENT_COPILOT || "",
version: "",
- agent_version: "0.0.369",
+ agent_version: "0.0.371",
workflow_name: "Workflow Generator",
experimental: false,
supports_tools_allowlist: true,
@@ -1953,7 +1953,7 @@ jobs:
network_mode: "defaults",
allowed_domains: [],
firewall_enabled: true,
- firewall_version: "",
+ awf_version: "v0.7.0",
steps: {
firewall: "squid"
},
@@ -2000,7 +2000,7 @@ jobs:
'|----------|-------|\n' +
`| Mode | ${awInfo.network_mode || 'defaults'} |\n` +
`| Firewall | ${awInfo.firewall_enabled ? '✅ Enabled' : '❌ Disabled'} |\n` +
- `| Firewall Version | ${awInfo.firewall_version || '(latest)'} |\n` +
+ `| Firewall Version | ${awInfo.awf_version || '(latest)'} |\n` +
'\n' +
(networkDetails ? `##### Allowed Domains\n${networkDetails}\n` : '') +
'
';
@@ -2047,26 +2047,39 @@ jobs:
This issue has been assigned to an AI agent for workflow design. The agent will:
- 1. **Parse the workflow requirements** from the information provided above
- 2. **Generate a NEW workflow specification file** (`.md`) with appropriate triggers, tools, and safe outputs
- 3. **Create a pull request** with the new workflow file at `.github/workflows/.md`
+ 1. **Parse the workflow requirements** from the issue form fields above:
+ - Workflow Name
+ - Workflow Description
+ - Additional Context (if provided)
- **IMPORTANT**: The agent will create a NEW workflow file following best practices for:
- - Security (minimal permissions, safe outputs for write operations)
- - Appropriate triggers (issues, pull requests, schedule, workflow_dispatch, etc.)
- - Necessary tools and MCP servers
- - Network restrictions when needed
- - Proper safe output configuration for GitHub operations
+ 2. **Generate a NEW workflow specification file** (`.md`) with:
+ - Kebab-case workflow ID derived from the name
+ - Complete YAML frontmatter (triggers, permissions, engine, tools, safe-outputs)
+ - Clear prompt body with instructions for the AI agent
+ - Security best practices applied
- The workflow specification will include:
- - Frontmatter with triggers, permissions, engine, and tools
- - Clear prompt instructions for the AI agent
- - Safe output configuration for any write operations
- - Security best practices (network restrictions, minimal permissions)
+ 3. **Compile the workflow** using `gh aw compile ` to generate the `.lock.yml` file
+
+ 4. **Create a pull request** with BOTH files:
+ - `.github/workflows/.md` (source)
+ - `.github/workflows/.lock.yml` (compiled)
+
+ **IMPORTANT - Issue Form Mode**: The agent operates in non-interactive mode and will:
+ - Parse the issue form data directly
+ - Make intelligent decisions about triggers, tools, and permissions based on the description
+ - Create a complete, working workflow without back-and-forth conversation
+ - Follow the same pattern as the campaign generator
+
+ **Best Practices Applied:**
+ - Security: minimal permissions, safe outputs for write operations
+ - Triggers: inferred from description (issues, pull_requests, schedule, workflow_dispatch)
+ - Tools: only include what's needed (github, web-fetch, playwright, etc.)
+ - Network: restricted to required domains/ecosystems
+ - Safe Outputs: for all GitHub write operations
**Next Steps:**
- - The AI agent will analyze your requirements and create a comprehensive workflow
- - The workflow will be compiled automatically to ensure validity
+ - The AI agent will parse your requirements and generate a complete workflow
+ - Both `.md` and `.lock.yml` files will be included in the PR
- Review the generated PR when it's ready
- Merge the PR to activate your workflow
```
@@ -5579,9 +5592,9 @@ jobs:
validAllowedRequests += stats.allowed;
validDeniedRequests += stats.denied;
}
- let summary = "### 🔥 Firewall Activity\n\n";
+ let summary = "";
summary += "\n";
- summary += `📊 ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
+ summary += `sandbox agent: ${totalRequests} request${totalRequests !== 1 ? "s" : ""} | `;
summary += `${validAllowedRequests} allowed | `;
summary += `${validDeniedRequests} blocked | `;
summary += `${uniqueDomainCount} unique domain${uniqueDomainCount !== 1 ? "s" : ""}
\n\n`;
@@ -6566,7 +6579,7 @@ jobs:
curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh
# Execute the installer with the specified version
- export VERSION=0.0.369 && sudo bash /tmp/copilot-install.sh
+ export VERSION=0.0.371 && sudo bash /tmp/copilot-install.sh
# Cleanup
rm -f /tmp/copilot-install.sh
@@ -7434,7 +7447,7 @@ jobs:
module.exports = { generateStagedPreview };
EOF_8386ee20
- cat > /tmp/gh-aw/scripts/update_context_helpers.cjs << 'EOF_95d23c7d'
+ cat > /tmp/gh-aw/scripts/update_context_helpers.cjs << 'EOF_4d21ccbd'
// @ts-check
///
@@ -7498,15 +7511,36 @@ jobs:
return undefined;
}
+ /**
+ * Check if the current context is a valid discussion context
+ * @param {string} eventName - GitHub event name
+ * @param {any} _payload - GitHub event payload (unused but kept for interface consistency)
+ * @returns {boolean} Whether context is valid for discussion updates
+ */
+ function isDiscussionContext(eventName, _payload) {
+ return eventName === "discussion" || eventName === "discussion_comment";
+ }
+
+ /**
+ * Get discussion number from the context payload
+ * @param {any} payload - GitHub event payload
+ * @returns {number|undefined} Discussion number or undefined
+ */
+ function getDiscussionNumber(payload) {
+ return payload?.discussion?.number;
+ }
+
module.exports = {
isIssueContext,
getIssueNumber,
isPRContext,
getPRNumber,
+ isDiscussionContext,
+ getDiscussionNumber,
};
- EOF_95d23c7d
- cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_006d32d7'
+ EOF_4d21ccbd
+ cat > /tmp/gh-aw/scripts/update_runner.cjs << 'EOF_60283df2'
// @ts-check
///
@@ -7591,11 +7625,12 @@ jobs:
* @param {boolean} params.canUpdateStatus - Whether status updates are allowed
* @param {boolean} params.canUpdateTitle - Whether title updates are allowed
* @param {boolean} params.canUpdateBody - Whether body updates are allowed
+ * @param {boolean} [params.canUpdateLabels] - Whether label updates are allowed
* @param {boolean} params.supportsStatus - Whether this type supports status
* @returns {{hasUpdates: boolean, updateData: any, logMessages: string[]}}
*/
function buildUpdateData(params) {
- const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, supportsStatus } = params;
+ const { item, canUpdateStatus, canUpdateTitle, canUpdateBody, canUpdateLabels, supportsStatus } = params;
/** @type {any} */
const updateData = {};
@@ -7645,6 +7680,17 @@ jobs:
}
}
+ // Handle labels update
+ if (canUpdateLabels && item.labels !== undefined) {
+ if (Array.isArray(item.labels)) {
+ updateData.labels = item.labels;
+ hasUpdates = true;
+ logMessages.push(`Will update labels to: ${item.labels.join(", ")}`);
+ } else {
+ logMessages.push("Invalid labels value: must be an array");
+ }
+ }
+
return { hasUpdates, updateData, logMessages };
}
@@ -7689,12 +7735,13 @@ jobs:
const canUpdateStatus = process.env.GH_AW_UPDATE_STATUS === "true";
const canUpdateTitle = process.env.GH_AW_UPDATE_TITLE === "true";
const canUpdateBody = process.env.GH_AW_UPDATE_BODY === "true";
+ const canUpdateLabels = process.env.GH_AW_UPDATE_LABELS === "true";
core.info(`Update target configuration: ${updateTarget}`);
if (supportsStatus) {
- core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update status: ${canUpdateStatus}, title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
} else {
- core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}`);
+ core.info(`Can update title: ${canUpdateTitle}, body: ${canUpdateBody}, labels: ${canUpdateLabels}`);
}
// Check context validity
@@ -7738,6 +7785,7 @@ jobs:
canUpdateStatus,
canUpdateTitle,
canUpdateBody,
+ canUpdateLabels,
supportsStatus,
});
@@ -7859,7 +7907,7 @@ jobs:
createGetSummaryLine,
};
- EOF_006d32d7
+ EOF_60283df2
- name: Assign To Agent
id: assign_to_agent
if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'assign_to_agent'))
diff --git a/pkg/workflow/aw_info_steps_test.go b/pkg/workflow/aw_info_steps_test.go
index dddf1c516b..056070f085 100644
--- a/pkg/workflow/aw_info_steps_test.go
+++ b/pkg/workflow/aw_info_steps_test.go
@@ -72,8 +72,8 @@ engine: claude
This workflow tests that Claude has firewall enabled by default when network is not configured.
`,
- expectFirewall: "",
- description: "Should have empty firewall type when no network is configured (firewall only applies with network restrictions)",
+ expectFirewall: "squid",
+ description: "Should have firewall type squid when no network is configured (firewall enabled by default)",
},
}
diff --git a/pkg/workflow/compiler_permissions_test.go b/pkg/workflow/compiler_permissions_test.go
index 25505be587..484f8763cf 100644
--- a/pkg/workflow/compiler_permissions_test.go
+++ b/pkg/workflow/compiler_permissions_test.go
@@ -136,14 +136,14 @@ This is a test workflow without network permissions.
t.Fatalf("Failed to read lock file: %v", err)
}
- // When no network is specified, firewall is NOT enabled (defaults to full access)
- // AWF is only enabled when network restrictions are configured
- if strings.Contains(string(lockContent), "sudo -E awf") {
- t.Error("Should NOT contain AWF wrapper when no network field specified (defaults to full access)")
+ // AWF is enabled by default for all engines (copilot, claude, codex) even without explicit network config
+ // This ensures sandbox.agent: awf is the default behavior
+ if !strings.Contains(string(lockContent), "sudo -E awf") {
+ t.Error("Should contain AWF wrapper by default for Claude engine")
}
})
- t.Run("network: defaults should not enable AWF for Claude without firewall config", func(t *testing.T) {
+ t.Run("network: defaults enables AWF by default for Claude", func(t *testing.T) {
testContent := `---
on: push
engine: claude
@@ -173,14 +173,13 @@ This is a test workflow with explicit defaults network permissions.
t.Fatalf("Failed to read lock file: %v", err)
}
- // network: defaults without explicit firewall config does NOT enable AWF
- // (firewall must be explicitly enabled or network.allowed must be specified)
- if strings.Contains(string(lockContent), "sudo -E awf") {
- t.Error("Should NOT contain AWF wrapper for network: defaults without firewall config")
+ // AWF is enabled by default for Claude engine with network: defaults
+ if !strings.Contains(string(lockContent), "sudo -E awf") {
+ t.Error("Should contain AWF wrapper for Claude engine with network: defaults")
}
})
- t.Run("network: {} should not enable AWF without firewall config", func(t *testing.T) {
+ t.Run("network: {} enables AWF by default for Claude", func(t *testing.T) {
testContent := `---
on: push
engine: claude
@@ -210,9 +209,9 @@ This is a test workflow with empty network permissions (deny all).
t.Fatalf("Failed to read lock file: %v", err)
}
- // Empty network config without explicit firewall config does NOT enable AWF
- if strings.Contains(string(lockContent), "sudo -E awf") {
- t.Error("Should NOT contain AWF wrapper for network: {} without firewall config")
+ // AWF is enabled by default for Claude engine with network: {}
+ if !strings.Contains(string(lockContent), "sudo -E awf") {
+ t.Error("Should contain AWF wrapper for Claude engine with network: {}")
}
})