From c7ad293afc381a008f461e1a67404668d2ac4372 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 5 Apr 2026 08:52:08 +0000
Subject: [PATCH 1/5] Add GitHub rate limit logging to JavaScript helpers and
 artifact uploads

- Add GITHUB_RATE_LIMITS_JSONL_PATH constant to constants.cjs
- Create github_rate_limit_logger.cjs with three helpers:
  logRateLimitFromResponse, fetchAndLogRateLimit, createRateLimitAwareGithub
- Create github_rate_limit_logger.test.cjs with 15 unit tests
- Integrate rate limit logging into github_api_helpers.cjs and check_rate_limit.cjs
- Add GithubRateLimitsFilename constant to pkg/constants/job_constants.go
- Add github_rate_limits.jsonl to agent and activation artifact upload paths
- Update golden test files to reflect new artifact paths

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/0340db5e-d302-4aad-ade8-8820f38672d1

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 actions/setup/js/check_rate_limit.cjs         |   9 +-
 actions/setup/js/constants.cjs                |   9 +
 actions/setup/js/github_api_helpers.cjs       |   3 +
 actions/setup/js/github_rate_limit_logger.cjs | 218 +++++++++++
 .../js/github_rate_limit_logger.test.cjs      | 357 ++++++++++++++++++
 pkg/agentdrain/data/default_weights.json      |  79 +---
 pkg/constants/job_constants.go                |   5 +
 pkg/workflow/compiler_activation_job.go       |   2 +
 pkg/workflow/compiler_yaml_main_job.go        |   4 +
 .../basic-copilot.golden                      |   3 +
 .../with-imports.golden                       |   3 +
 11 files changed, 622 insertions(+), 70 deletions(-)
 create mode 100644 actions/setup/js/github_rate_limit_logger.cjs
 create mode 100644 actions/setup/js/github_rate_limit_logger.test.cjs

diff --git a/actions/setup/js/check_rate_limit.cjs b/actions/setup/js/check_rate_limit.cjs
index 59164f0f888..6c0a7883137 100644
--- a/actions/setup/js/check_rate_limit.cjs
+++ b/actions/setup/js/check_rate_limit.cjs
@@ -2,6 +2,7 @@
 /// <reference types="@actions/github-script" />
 
 const { getErrorMessage } = require("./error_helpers.cjs");
+const { logRateLimitFromResponse, fetchAndLogRateLimit } = require("./github_rate_limit_logger.cjs");
 
 /**
  * Rate limit check for per-user per-workflow triggers
@@ -15,6 +16,9 @@ async function main() {
   const eventName = context.eventName;
   const runId = context.runId;
 
+  // Capture a rate-limit snapshot at the start of the check for observability.
+  await fetchAndLogRateLimit(github, "check_rate_limit_start");
+
   // Get workflow file name from GITHUB_WORKFLOW_REF (format: "owner/repo/.github/workflows/file.yml@ref")
   // or fall back to GITHUB_WORKFLOW (workflow name)
   const workflowRef = process.env.GITHUB_WORKFLOW_REF || "";
@@ -50,12 +54,14 @@ async function main() {
 
   try {
     // Check user's permission level in the repository
-    const { data: permissionData } = await github.rest.repos.getCollaboratorPermissionLevel({
+    const permResponse = await github.rest.repos.getCollaboratorPermissionLevel({
       owner,
       repo,
       username: actor,
     });
+    logRateLimitFromResponse(permResponse, "repos.getCollaboratorPermissionLevel");
 
+    const { data: permissionData } = permResponse;
     const userPermission = permissionData.permission;
     core.info(`   User '${actor}' has permission level: ${userPermission}`);
 
@@ -130,6 +136,7 @@ async function main() {
         per_page: perPage,
         page,
       });
+      logRateLimitFromResponse(response, "actions.listWorkflowRuns");
 
       const runs = response.data.workflow_runs;
       core.info(`   Retrieved ${runs.length} runs from page ${page}`);
diff --git a/actions/setup/js/constants.cjs b/actions/setup/js/constants.cjs
index 5fa4be27b2d..92634c68f7a 100644
--- a/actions/setup/js/constants.cjs
+++ b/actions/setup/js/constants.cjs
@@ -87,6 +87,14 @@ const MANIFEST_FILE_PATH = `${TMP_GH_AW_PATH}/safe-output-items.jsonl`;
  */
 const OTEL_JSONL_PATH = `${TMP_GH_AW_PATH}/otel.jsonl`;
 
+/**
+ * Path to the GitHub API rate-limit log file.
+ * Each entry records the x-ratelimit-* headers (or rate-limit API snapshot)
+ * at the time of a GitHub REST API call, enabling post-run rate-limit analysis.
+ * @type {string}
+ */
+const GITHUB_RATE_LIMITS_JSONL_PATH = `${TMP_GH_AW_PATH}/github_rate_limits.jsonl`;
+
 /**
  * Filename of the threat detection log written by the detection engine via tee.
  * The detection copilot's stdout (containing THREAT_DETECTION_RESULT) is piped
@@ -106,5 +114,6 @@ module.exports = {
   RPC_MESSAGES_PATH,
   MANIFEST_FILE_PATH,
   OTEL_JSONL_PATH,
+  GITHUB_RATE_LIMITS_JSONL_PATH,
   DETECTION_LOG_FILENAME,
 };
diff --git a/actions/setup/js/github_api_helpers.cjs b/actions/setup/js/github_api_helpers.cjs
index 0383b01081a..d606815ef84 100644
--- a/actions/setup/js/github_api_helpers.cjs
+++ b/actions/setup/js/github_api_helpers.cjs
@@ -7,6 +7,7 @@
  */
 
 const { getErrorMessage } = require("./error_helpers.cjs");
+const { logRateLimitFromResponse } = require("./github_rate_limit_logger.cjs");
 
 /**
  * @typedef {Object} GraphQLErrorHints
@@ -75,6 +76,8 @@ async function getFileContent(github, owner, repo, path, ref) {
       ref,
     });
 
+    logRateLimitFromResponse(response, "repos.getContent");
+
     // Handle case where response is an array (directory listing)
     if (Array.isArray(response.data)) {
       core.info(`Path ${path} is a directory, not a file`);
diff --git a/actions/setup/js/github_rate_limit_logger.cjs b/actions/setup/js/github_rate_limit_logger.cjs
new file mode 100644
index 00000000000..6ac58984acf
--- /dev/null
+++ b/actions/setup/js/github_rate_limit_logger.cjs
@@ -0,0 +1,218 @@
+// @ts-check
+/// <reference types="@actions/github-script" />
+
+/**
+ * github_rate_limit_logger.cjs
+ *
+ * Helpers for capturing GitHub API rate-limit information to a JSONL file
+ * for observability.  Each entry is a single JSON line written to
+ * GITHUB_RATE_LIMITS_JSONL_PATH so the file can be included in the job
+ * artifact and inspected after a workflow run.
+ *
+ * Three usage patterns are supported:
+ *
+ * 1. **After a single REST call** – pass the response object to
+ *    `logRateLimitFromResponse(response, operation)` to record the
+ *    x-ratelimit-* headers returned by that call.
+ *
+ * 2. **On-demand snapshot** – call `fetchAndLogRateLimit(github, operation)`
+ *    to query the GitHub rate-limit API and record the current limits for
+ *    all resource categories.
+ *
+ * 3. **Automatic wrapping** – call `createRateLimitAwareGithub(github)` to
+ *    get a Proxy around the github REST client.  Every `github.rest.*.*(...)`
+ *    call will automatically log rate-limit headers from the response without
+ *    any further changes to call sites.
+ */
+
+const fs = require("fs");
+const path = require("path");
+const { getErrorMessage } = require("./error_helpers.cjs");
+const { GITHUB_RATE_LIMITS_JSONL_PATH } = require("./constants.cjs");
+
+// ---------------------------------------------------------------------------
+// Internal helpers
+// ---------------------------------------------------------------------------
+
+/**
+ * Ensure the directory containing the log file exists.
+ * @param {string} filePath
+ */
+function ensureDir(filePath) {
+  const dir = path.dirname(filePath);
+  if (!fs.existsSync(dir)) {
+    fs.mkdirSync(dir, { recursive: true });
+  }
+}
+
+/**
+ * Append a single rate-limit entry to the JSONL log file.
+ * Errors are non-fatal – a warning is emitted to the Actions log.
+ *
+ * @param {Record<string, unknown>} entry
+ */
+function appendEntry(entry) {
+  try {
+    ensureDir(GITHUB_RATE_LIMITS_JSONL_PATH);
+    const line = JSON.stringify(entry) + "\n";
+    fs.appendFileSync(GITHUB_RATE_LIMITS_JSONL_PATH, line);
+  } catch (err) {
+    core.warning(`github_rate_limit_logger: failed to write entry: ${getErrorMessage(err)}`);
+  }
+}
+
+/**
+ * Parse an x-ratelimit-reset Unix timestamp (seconds) into an ISO 8601 string.
+ * Returns null when the header is absent or unparseable.
+ *
+ * @param {string | undefined} resetHeader
+ * @returns {string | null}
+ */
+function parseResetTimestamp(resetHeader) {
+  if (!resetHeader) return null;
+  const seconds = parseInt(resetHeader, 10);
+  if (isNaN(seconds)) return null;
+  return new Date(seconds * 1000).toISOString();
+}
+
+// ---------------------------------------------------------------------------
+// Public API
+// ---------------------------------------------------------------------------
+
+/**
+ * Log GitHub API rate-limit information extracted from a REST response's
+ * headers.  Call this immediately after any `github.rest.*.*()` call to
+ * record the current rate-limit state without an extra API round-trip.
+ *
+ * @param {{ headers?: Record<string, string | undefined> }} response - The github.rest response object
+ * @param {string} operation - Human-readable description of the operation (e.g. "issues.listComments")
+ */
+function logRateLimitFromResponse(response, operation) {
+  const headers = response?.headers;
+  if (!headers) return;
+
+  const limit = headers["x-ratelimit-limit"];
+  const remaining = headers["x-ratelimit-remaining"];
+  const reset = headers["x-ratelimit-reset"];
+  const used = headers["x-ratelimit-used"];
+  const resource = headers["x-ratelimit-resource"];
+
+  // Skip if no rate-limit headers are present (e.g. GraphQL responses)
+  if (!limit && !remaining && !reset) return;
+
+  /** @type {Record<string, unknown>} */
+  const entry = {
+    timestamp: new Date().toISOString(),
+    source: "response_headers",
+    operation,
+  };
+
+  if (resource) entry.resource = resource;
+  if (limit !== undefined) entry.limit = limit !== undefined ? parseInt(limit, 10) : undefined;
+  if (remaining !== undefined) entry.remaining = remaining !== undefined ? parseInt(remaining, 10) : undefined;
+  if (used !== undefined) entry.used = used !== undefined ? parseInt(used, 10) : undefined;
+  if (reset) entry.reset = parseResetTimestamp(reset);
+
+  appendEntry(entry);
+}
+
+/**
+ * Fetch the current GitHub API rate-limit information via the rate-limit API
+ * and write a JSONL entry for each resource category.
+ *
+ * Use this for a point-in-time snapshot at the start or end of a script,
+ * rather than after every individual API call.
+ *
+ * @param {any} github - The github object injected by actions/github-script
+ * @param {string} [operation="fetch"] - Label recorded in each log entry
+ */
+async function fetchAndLogRateLimit(github, operation = "fetch") {
+  try {
+    const response = await github.rest.rateLimit.get();
+    const resources = response?.data?.resources;
+    if (!resources) return;
+
+    const timestamp = new Date().toISOString();
+    for (const [resource, data] of Object.entries(resources)) {
+      if (!data || typeof data !== "object") continue;
+      /** @type {Record<string, unknown>} */
+      const entry = {
+        timestamp,
+        source: "rate_limit_api",
+        operation,
+        resource,
+        limit: data.limit,
+        remaining: data.remaining,
+        used: data.used,
+        reset: data.reset ? new Date(data.reset * 1000).toISOString() : null,
+      };
+      appendEntry(entry);
+    }
+  } catch (err) {
+    core.warning(`github_rate_limit_logger: fetchAndLogRateLimit failed: ${getErrorMessage(err)}`);
+  }
+}
+
+/**
+ * Wrap a github object (as provided by actions/github-script) so that every
+ * `github.rest.*.*()` call automatically logs rate-limit headers from the
+ * response.
+ *
+ * Usage:
+ * ```js
+ * const { createRateLimitAwareGithub } = require('./github_rate_limit_logger.cjs');
+ * const gh = createRateLimitAwareGithub(github);
+ * // All calls via gh.rest.* will now log rate limits automatically.
+ * const { data } = await gh.rest.issues.get({ owner, repo, issue_number: 1 });
+ * ```
+ *
+ * @param {any} github - The github object injected by actions/github-script
+ * @returns {any} A proxied github object with automatic rate-limit logging
+ */
+function createRateLimitAwareGithub(github) {
+  /**
+   * Wrap a single REST namespace (e.g. github.rest.issues) so each method
+   * call intercepts the response and logs rate-limit headers.
+   *
+   * @param {any} namespace - The REST namespace object
+   * @param {string} namespaceName - Name used for logging (e.g. "issues")
+   * @returns {any}
+   */
+  function wrapNamespace(namespace, namespaceName) {
+    return new Proxy(namespace, {
+      get(target, method) {
+        const fn = target[method];
+        if (typeof fn !== "function") return fn;
+        return async (/** @type {any[]} */ ...args) => {
+          const response = await fn.apply(target, args);
+          logRateLimitFromResponse(response, `${namespaceName}.${String(method)}`);
+          return response;
+        };
+      },
+    });
+  }
+
+  // Wrap github.rest so every namespace access returns an instrumented proxy.
+  const restProxy = new Proxy(github.rest, {
+    get(target, namespaceName) {
+      const ns = target[namespaceName];
+      if (!ns || typeof ns !== "object") return ns;
+      return wrapNamespace(ns, String(namespaceName));
+    },
+  });
+
+  // Return a shallow proxy over github that replaces the `rest` property.
+  return new Proxy(github, {
+    get(target, prop) {
+      if (prop === "rest") return restProxy;
+      return target[prop];
+    },
+  });
+}
+
+module.exports = {
+  logRateLimitFromResponse,
+  fetchAndLogRateLimit,
+  createRateLimitAwareGithub,
+  GITHUB_RATE_LIMITS_JSONL_PATH,
+};
diff --git a/actions/setup/js/github_rate_limit_logger.test.cjs b/actions/setup/js/github_rate_limit_logger.test.cjs
new file mode 100644
index 00000000000..2f695c7124a
--- /dev/null
+++ b/actions/setup/js/github_rate_limit_logger.test.cjs
@@ -0,0 +1,357 @@
+// @ts-check
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+import fs from "fs";
+
+// ---------------------------------------------------------------------------
+// Globals injected by actions/github-script
+// ---------------------------------------------------------------------------
+
+const mockCore = {
+  info: vi.fn(),
+  warning: vi.fn(),
+  error: vi.fn(),
+  setFailed: vi.fn(),
+  setOutput: vi.fn(),
+};
+
+global.core = mockCore;
+
+// ---------------------------------------------------------------------------
+// Module import
+// ---------------------------------------------------------------------------
+
+const { logRateLimitFromResponse, fetchAndLogRateLimit, createRateLimitAwareGithub, GITHUB_RATE_LIMITS_JSONL_PATH } = await import("./github_rate_limit_logger.cjs?" + Date.now());
+
+// ---------------------------------------------------------------------------
+// logRateLimitFromResponse
+// ---------------------------------------------------------------------------
+
+describe("logRateLimitFromResponse", () => {
+  let existsSpy, mkdirSpy, appendSpy;
+
+  beforeEach(() => {
+    existsSpy = vi.spyOn(fs, "existsSync").mockReturnValue(true);
+    mkdirSpy = vi.spyOn(fs, "mkdirSync").mockImplementation(() => undefined);
+    appendSpy = vi.spyOn(fs, "appendFileSync").mockImplementation(() => undefined);
+    vi.clearAllMocks();
+    existsSpy.mockReturnValue(true);
+  });
+
+  afterEach(() => {
+    existsSpy.mockRestore();
+    mkdirSpy.mockRestore();
+    appendSpy.mockRestore();
+  });
+
+  it("appends a JSONL entry when all rate-limit headers are present", () => {
+    const response = {
+      headers: {
+        "x-ratelimit-limit": "5000",
+        "x-ratelimit-remaining": "4900",
+        "x-ratelimit-used": "100",
+        "x-ratelimit-reset": "1700000000",
+        "x-ratelimit-resource": "core",
+      },
+    };
+
+    logRateLimitFromResponse(response, "issues.get");
+
+    expect(appendSpy).toHaveBeenCalledOnce();
+    const [filePath, content] = appendSpy.mock.calls[0];
+    expect(filePath).toBe(GITHUB_RATE_LIMITS_JSONL_PATH);
+
+    const entry = JSON.parse(content.trimEnd());
+    expect(entry.source).toBe("response_headers");
+    expect(entry.operation).toBe("issues.get");
+    expect(entry.limit).toBe(5000);
+    expect(entry.remaining).toBe(4900);
+    expect(entry.used).toBe(100);
+    expect(entry.resource).toBe("core");
+    expect(typeof entry.timestamp).toBe("string");
+    expect(typeof entry.reset).toBe("string");
+
+    // JSONL: must end with a newline and contain no embedded newlines
+    expect(content).toMatch(/\n$/);
+    expect(content.trimEnd()).not.toContain("\n");
+  });
+
+  it("does nothing when there are no rate-limit headers", () => {
+    logRateLimitFromResponse({ headers: { "content-type": "application/json" } }, "repos.get");
+    expect(appendSpy).not.toHaveBeenCalled();
+  });
+
+  it("does nothing when headers property is absent", () => {
+    logRateLimitFromResponse({}, "repos.get");
+    expect(appendSpy).not.toHaveBeenCalled();
+  });
+
+  it("does nothing when response is null", () => {
+    logRateLimitFromResponse(null, "repos.get");
+    expect(appendSpy).not.toHaveBeenCalled();
+  });
+
+  it("does nothing when response is undefined", () => {
+    logRateLimitFromResponse(undefined, "repos.get");
+    expect(appendSpy).not.toHaveBeenCalled();
+  });
+
+  it("appends a separate entry per call", () => {
+    const response = {
+      headers: {
+        "x-ratelimit-limit": "5000",
+        "x-ratelimit-remaining": "4800",
+        "x-ratelimit-reset": "1700000000",
+      },
+    };
+
+    logRateLimitFromResponse(response, "issues.list");
+    logRateLimitFromResponse({ ...response }, "issues.create");
+
+    expect(appendSpy).toHaveBeenCalledTimes(2);
+    expect(JSON.parse(appendSpy.mock.calls[0][1].trimEnd()).operation).toBe("issues.list");
+    expect(JSON.parse(appendSpy.mock.calls[1][1].trimEnd()).operation).toBe("issues.create");
+  });
+
+  it("emits a warning when appendFileSync throws", () => {
+    appendSpy.mockImplementation(() => {
+      throw new Error("disk full");
+    });
+
+    const response = {
+      headers: {
+        "x-ratelimit-limit": "5000",
+        "x-ratelimit-remaining": "4900",
+        "x-ratelimit-reset": "1700000000",
+      },
+    };
+
+    // Must not throw
+    expect(() => logRateLimitFromResponse(response, "issues.get")).not.toThrow();
+    expect(mockCore.warning).toHaveBeenCalled();
+  });
+
+  it("converts reset Unix timestamp to ISO 8601 string", () => {
+    const resetSeconds = 1700000000;
+    const response = {
+      headers: {
+        "x-ratelimit-limit": "5000",
+        "x-ratelimit-remaining": "4900",
+        "x-ratelimit-reset": String(resetSeconds),
+      },
+    };
+
+    logRateLimitFromResponse(response, "repos.get");
+
+    const entry = JSON.parse(appendSpy.mock.calls[0][1].trimEnd());
+    expect(entry.reset).toBe(new Date(resetSeconds * 1000).toISOString());
+  });
+});
+
+// ---------------------------------------------------------------------------
+// fetchAndLogRateLimit
+// ---------------------------------------------------------------------------
+
+describe("fetchAndLogRateLimit", () => {
+  let existsSpy, mkdirSpy, appendSpy;
+
+  beforeEach(() => {
+    existsSpy = vi.spyOn(fs, "existsSync").mockReturnValue(true);
+    mkdirSpy = vi.spyOn(fs, "mkdirSync").mockImplementation(() => undefined);
+    appendSpy = vi.spyOn(fs, "appendFileSync").mockImplementation(() => undefined);
+    vi.clearAllMocks();
+    existsSpy.mockReturnValue(true);
+  });
+
+  afterEach(() => {
+    existsSpy.mockRestore();
+    mkdirSpy.mockRestore();
+    appendSpy.mockRestore();
+  });
+
+  it("writes one JSONL entry per resource category", async () => {
+    const mockGithub = {
+      rest: {
+        rateLimit: {
+          get: vi.fn().mockResolvedValue({
+            data: {
+              resources: {
+                core: { limit: 5000, remaining: 4900, used: 100, reset: 1700000000 },
+                search: { limit: 30, remaining: 28, used: 2, reset: 1700000000 },
+              },
+            },
+          }),
+        },
+      },
+    };
+
+    await fetchAndLogRateLimit(mockGithub, "startup");
+
+    expect(appendSpy).toHaveBeenCalledTimes(2);
+
+    const entries = appendSpy.mock.calls.map(([, content]) => JSON.parse(content.trimEnd()));
+    const coreEntry = entries.find(e => e.resource === "core");
+    const searchEntry = entries.find(e => e.resource === "search");
+
+    expect(coreEntry).toBeDefined();
+    expect(coreEntry.source).toBe("rate_limit_api");
+    expect(coreEntry.operation).toBe("startup");
+    expect(coreEntry.limit).toBe(5000);
+    expect(coreEntry.remaining).toBe(4900);
+    expect(typeof coreEntry.reset).toBe("string");
+
+    expect(searchEntry).toBeDefined();
+    expect(searchEntry.limit).toBe(30);
+  });
+
+  it("emits a warning and does not throw when the API call fails", async () => {
+    const mockGithub = {
+      rest: {
+        rateLimit: {
+          get: vi.fn().mockRejectedValue(new Error("API unavailable")),
+        },
+      },
+    };
+
+    await expect(fetchAndLogRateLimit(mockGithub)).resolves.toBeUndefined();
+    expect(mockCore.warning).toHaveBeenCalled();
+    expect(appendSpy).not.toHaveBeenCalled();
+  });
+
+  it("uses 'fetch' as the default operation label", async () => {
+    const mockGithub = {
+      rest: {
+        rateLimit: {
+          get: vi.fn().mockResolvedValue({
+            data: {
+              resources: {
+                core: { limit: 5000, remaining: 5000, used: 0, reset: 1700000000 },
+              },
+            },
+          }),
+        },
+      },
+    };
+
+    await fetchAndLogRateLimit(mockGithub);
+
+    const entry = JSON.parse(appendSpy.mock.calls[0][1].trimEnd());
+    expect(entry.operation).toBe("fetch");
+  });
+});
+
+// ---------------------------------------------------------------------------
+// createRateLimitAwareGithub
+// ---------------------------------------------------------------------------
+
+describe("createRateLimitAwareGithub", () => {
+  let existsSpy, mkdirSpy, appendSpy;
+
+  beforeEach(() => {
+    existsSpy = vi.spyOn(fs, "existsSync").mockReturnValue(true);
+    mkdirSpy = vi.spyOn(fs, "mkdirSync").mockImplementation(() => undefined);
+    appendSpy = vi.spyOn(fs, "appendFileSync").mockImplementation(() => undefined);
+    vi.clearAllMocks();
+    existsSpy.mockReturnValue(true);
+  });
+
+  afterEach(() => {
+    existsSpy.mockRestore();
+    mkdirSpy.mockRestore();
+    appendSpy.mockRestore();
+  });
+
+  it("proxies a REST call and logs rate-limit headers from the response", async () => {
+    const mockResponse = {
+      data: { id: 1 },
+      headers: {
+        "x-ratelimit-limit": "5000",
+        "x-ratelimit-remaining": "4999",
+        "x-ratelimit-reset": "1700000000",
+        "x-ratelimit-resource": "core",
+      },
+    };
+
+    const mockIssuesGet = vi.fn().mockResolvedValue(mockResponse);
+    const mockGithub = {
+      rest: {
+        issues: { get: mockIssuesGet },
+      },
+    };
+
+    const gh = createRateLimitAwareGithub(mockGithub);
+    const result = await gh.rest.issues.get({ owner: "o", repo: "r", issue_number: 1 });
+
+    // Original response is returned unchanged
+    expect(result).toBe(mockResponse);
+    // Underlying function was called with correct args
+    expect(mockIssuesGet).toHaveBeenCalledWith({ owner: "o", repo: "r", issue_number: 1 });
+
+    // Rate limit was logged
+    expect(appendSpy).toHaveBeenCalledOnce();
+    const entry = JSON.parse(appendSpy.mock.calls[0][1].trimEnd());
+    expect(entry.operation).toBe("issues.get");
+    expect(entry.remaining).toBe(4999);
+  });
+
+  it("passes through non-REST properties unchanged", () => {
+    const mockGraphql = vi.fn();
+    const mockGithub = {
+      rest: { issues: { get: vi.fn() } },
+      graphql: mockGraphql,
+      auth: "token abc",
+    };
+
+    const gh = createRateLimitAwareGithub(mockGithub);
+
+    expect(gh.graphql).toBe(mockGraphql);
+    expect(gh.auth).toBe("token abc");
+  });
+
+  it("does not log when response has no rate-limit headers", async () => {
+    const mockResponse = {
+      data: { id: 99 },
+      headers: { "content-type": "application/json" },
+    };
+
+    const mockGithub = {
+      rest: {
+        repos: { get: vi.fn().mockResolvedValue(mockResponse) },
+      },
+    };
+
+    const gh = createRateLimitAwareGithub(mockGithub);
+    const result = await gh.rest.repos.get({ owner: "o", repo: "r" });
+
+    expect(result).toBe(mockResponse);
+    expect(appendSpy).not.toHaveBeenCalled();
+  });
+
+  it("logs separate entries for consecutive calls in the same namespace", async () => {
+    const makeResponse = remaining => ({
+      data: {},
+      headers: {
+        "x-ratelimit-limit": "5000",
+        "x-ratelimit-remaining": String(remaining),
+        "x-ratelimit-reset": "1700000000",
+      },
+    });
+
+    const mockGithub = {
+      rest: {
+        issues: {
+          get: vi.fn().mockResolvedValueOnce(makeResponse(4999)).mockResolvedValueOnce(makeResponse(4998)),
+        },
+      },
+    };
+
+    const gh = createRateLimitAwareGithub(mockGithub);
+    await gh.rest.issues.get({ owner: "o", repo: "r", issue_number: 1 });
+    await gh.rest.issues.get({ owner: "o", repo: "r", issue_number: 2 });
+
+    expect(appendSpy).toHaveBeenCalledTimes(2);
+    const first = JSON.parse(appendSpy.mock.calls[0][1].trimEnd());
+    const second = JSON.parse(appendSpy.mock.calls[1][1].trimEnd());
+    expect(first.remaining).toBe(4999);
+    expect(second.remaining).toBe(4998);
+  });
+});
diff --git a/pkg/agentdrain/data/default_weights.json b/pkg/agentdrain/data/default_weights.json
index 26e14f1120d..5ed9cfb5f89 100644
--- a/pkg/agentdrain/data/default_weights.json
+++ b/pkg/agentdrain/data/default_weights.json
@@ -39,28 +39,7 @@
         "id": 5,
         "size": 1,
         "stage": "error",
-        "template": [
-          "stage=error",
-          "reason=The",
-          "Serena",
-          "MCP",
-          "server",
-          "is",
-          "not",
-          "available",
-          "in",
-          "this",
-          "environment.",
-          "No",
-          "serena-*",
-          "tools",
-          "are",
-          "registered.",
-          "tool=Serena",
-          "MCP",
-          "server",
-          "type=missing_tool"
-        ]
+        "template": ["stage=error", "reason=The", "Serena", "MCP", "server", "is", "not", "available", "in", "this", "environment.", "No", "serena-*", "tools", "are", "registered.", "tool=Serena", "MCP", "server", "type=missing_tool"]
       },
       {
         "id": 6,
@@ -234,12 +213,7 @@
     ],
     "config": {
       "Depth": 4,
-      "ExcludeFields": [
-        "session_id",
-        "trace_id",
-        "span_id",
-        "timestamp"
-      ],
+      "ExcludeFields": ["session_id", "trace_id", "span_id", "timestamp"],
       "MaskRules": [
         {
           "Name": "uuid",
@@ -285,21 +259,12 @@
         "id": 1,
         "size": 100,
         "stage": "finish",
-        "template": [
-          "stage=finish",
-          "\u003c*\u003e",
-          "tokens=\u003cNUM\u003e"
-        ]
+        "template": ["stage=finish", "\u003c*\u003e", "tokens=\u003cNUM\u003e"]
       }
     ],
     "config": {
       "Depth": 4,
-      "ExcludeFields": [
-        "session_id",
-        "trace_id",
-        "span_id",
-        "timestamp"
-      ],
+      "ExcludeFields": ["session_id", "trace_id", "span_id", "timestamp"],
       "MaskRules": [
         {
           "Name": "uuid",
@@ -345,21 +310,12 @@
         "id": 1,
         "size": 72,
         "stage": "plan",
-        "template": [
-          "stage=plan",
-          "errors=\u003cNUM\u003e",
-          "turns=\u003cNUM\u003e"
-        ]
+        "template": ["stage=plan", "errors=\u003cNUM\u003e", "turns=\u003cNUM\u003e"]
       }
     ],
     "config": {
       "Depth": 4,
-      "ExcludeFields": [
-        "session_id",
-        "trace_id",
-        "span_id",
-        "timestamp"
-      ],
+      "ExcludeFields": ["session_id", "trace_id", "span_id", "timestamp"],
       "MaskRules": [
         {
           "Name": "uuid",
@@ -403,12 +359,7 @@
     "clusters": null,
     "config": {
       "Depth": 4,
-      "ExcludeFields": [
-        "session_id",
-        "trace_id",
-        "span_id",
-        "timestamp"
-      ],
+      "ExcludeFields": ["session_id", "trace_id", "span_id", "timestamp"],
       "MaskRules": [
         {
           "Name": "uuid",
@@ -452,12 +403,7 @@
     "clusters": null,
     "config": {
       "Depth": 4,
-      "ExcludeFields": [
-        "session_id",
-        "trace_id",
-        "span_id",
-        "timestamp"
-      ],
+      "ExcludeFields": ["session_id", "trace_id", "span_id", "timestamp"],
       "MaskRules": [
         {
           "Name": "uuid",
@@ -1607,12 +1553,7 @@
     ],
     "config": {
       "Depth": 4,
-      "ExcludeFields": [
-        "session_id",
-        "trace_id",
-        "span_id",
-        "timestamp"
-      ],
+      "ExcludeFields": ["session_id", "trace_id", "span_id", "timestamp"],
       "MaskRules": [
         {
           "Name": "uuid",
@@ -1652,4 +1593,4 @@
     },
     "next_id": 15
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/constants/job_constants.go b/pkg/constants/job_constants.go
index f58c1903605..352aaa2da72 100644
--- a/pkg/constants/job_constants.go
+++ b/pkg/constants/job_constants.go
@@ -93,6 +93,11 @@ const SafeOutputsFilename = "safeoutputs.jsonl"
 // consume structured token data without parsing the step summary or GITHUB_OUTPUT.
 const TokenUsageFilename = "agent_usage.json"
 
+// GithubRateLimitsFilename is the filename of the GitHub API rate-limit log written to /tmp/gh-aw/.
+// Each line is a JSON object recording the x-ratelimit-* headers (or rate-limit API snapshot)
+// captured during github.rest API calls, enabling post-run analysis of rate-limit consumption.
+const GithubRateLimitsFilename = "github_rate_limits.jsonl"
+
 // ArtifactPrefixOutputName is the job output name that exposes the artifact name prefix.
 // In workflow_call context, the prefix is a stable hash derived from the workflow inputs,
 // ensuring artifact names are unique when the same workflow is called multiple times in
diff --git a/pkg/workflow/compiler_activation_job.go b/pkg/workflow/compiler_activation_job.go
index 0f372e7752c..3504e0ee7df 100644
--- a/pkg/workflow/compiler_activation_job.go
+++ b/pkg/workflow/compiler_activation_job.go
@@ -515,6 +515,8 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate
 	steps = append(steps, "          path: |\n")
 	steps = append(steps, "            /tmp/gh-aw/aw_info.json\n")
 	steps = append(steps, "            /tmp/gh-aw/aw-prompts/prompt.txt\n")
+	steps = append(steps, "            /tmp/gh-aw/"+constants.GithubRateLimitsFilename+"\n")
+	steps = append(steps, "          if-no-files-found: ignore\n")
 	steps = append(steps, "          retention-days: 1\n")
 
 	// Set permissions - activation job always needs contents:read for GitHub API access
diff --git a/pkg/workflow/compiler_yaml_main_job.go b/pkg/workflow/compiler_yaml_main_job.go
index 6485b6f1277..1d466596ad8 100644
--- a/pkg/workflow/compiler_yaml_main_job.go
+++ b/pkg/workflow/compiler_yaml_main_job.go
@@ -454,6 +454,10 @@ func (c *Compiler) generateMainJobSteps(yaml *strings.Builder, data *WorkflowDat
 	// (e.g., smoke-claude status summaries)
 	artifactPaths = append(artifactPaths, "/tmp/gh-aw/agent/")
 
+	// Collect GitHub API rate-limit log for observability.
+	// Written by github_rate_limit_logger.cjs during REST API calls.
+	artifactPaths = append(artifactPaths, "/tmp/gh-aw/"+constants.GithubRateLimitsFilename)
+
 	// Collect safe outputs and agent output paths for the unified artifact.
 	// These were previously uploaded as separate safe-output and agent-output artifacts.
 	if data.SafeOutputs != nil {
diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden
index df04bee26a8..041620288e8 100644
--- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden
+++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/basic-copilot.golden
@@ -218,6 +218,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -502,6 +504,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
           if-no-files-found: ignore
       - name: Upload firewall audit logs
         if: always()
diff --git a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden
index 06b6746cd57..3c85d17d0d2 100644
--- a/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden
+++ b/pkg/workflow/testdata/TestWasmGolden_CompileFixtures/with-imports.golden
@@ -219,6 +219,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -503,6 +505,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
           if-no-files-found: ignore
       - name: Upload firewall audit logs
         if: always()

From a6fd718e43133d62af76ae60da827f559b8a19f2 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 5 Apr 2026 08:54:21 +0000
Subject: [PATCH 2/5] Fix redundant condition checks in rate limit logger and
 revert unrelated JSON formatting

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/0340db5e-d302-4aad-ade8-8820f38672d1

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 actions/setup/js/github_rate_limit_logger.cjs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/actions/setup/js/github_rate_limit_logger.cjs b/actions/setup/js/github_rate_limit_logger.cjs
index 6ac58984acf..1ddd7d717c1 100644
--- a/actions/setup/js/github_rate_limit_logger.cjs
+++ b/actions/setup/js/github_rate_limit_logger.cjs
@@ -108,9 +108,9 @@ function logRateLimitFromResponse(response, operation) {
   };
 
   if (resource) entry.resource = resource;
-  if (limit !== undefined) entry.limit = limit !== undefined ? parseInt(limit, 10) : undefined;
-  if (remaining !== undefined) entry.remaining = remaining !== undefined ? parseInt(remaining, 10) : undefined;
-  if (used !== undefined) entry.used = used !== undefined ? parseInt(used, 10) : undefined;
+  if (limit !== undefined) entry.limit = parseInt(limit, 10);
+  if (remaining !== undefined) entry.remaining = parseInt(remaining, 10);
+  if (used !== undefined) entry.used = parseInt(used, 10);
   if (reset) entry.reset = parseResetTimestamp(reset);
 
   appendEntry(entry);

From 38106375fee1cb0a28220f5d9d853a0e46e1e130 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 5 Apr 2026 09:17:18 +0000
Subject: [PATCH 3/5] Instrument github object in setupGlobals to avoid double
 wrapping

Wrap the github object with createRateLimitAwareGithub in setupGlobals so
every github.rest.*.*() call across all scripts automatically logs rate
limits. Remove the now-redundant logRateLimitFromResponse calls from
check_rate_limit.cjs and github_api_helpers.cjs.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/29ec0ffe-a05e-4ac3-8c33-de88c2f4c404

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 .github/workflows/ace-editor.lock.yml                  |  3 +++
 .github/workflows/agent-performance-analyzer.lock.yml  |  3 +++
 .github/workflows/agent-persona-explorer.lock.yml      |  3 +++
 .github/workflows/agentic-observability-kit.lock.yml   |  3 +++
 .github/workflows/ai-moderator.lock.yml                |  3 +++
 .github/workflows/archie.lock.yml                      |  3 +++
 .github/workflows/artifacts-summary.lock.yml           |  3 +++
 .github/workflows/audit-workflows.lock.yml             |  3 +++
 .github/workflows/auto-triage-issues.lock.yml          |  3 +++
 .github/workflows/blog-auditor.lock.yml                |  3 +++
 .github/workflows/bot-detection.lock.yml               |  3 +++
 .github/workflows/brave.lock.yml                       |  3 +++
 .github/workflows/breaking-change-checker.lock.yml     |  3 +++
 .github/workflows/changeset.lock.yml                   |  3 +++
 .github/workflows/ci-coach.lock.yml                    |  3 +++
 .github/workflows/ci-doctor.lock.yml                   |  3 +++
 .../workflows/claude-code-user-docs-review.lock.yml    |  3 +++
 .github/workflows/cli-consistency-checker.lock.yml     |  3 +++
 .github/workflows/cli-version-checker.lock.yml         |  3 +++
 .github/workflows/cloclo.lock.yml                      |  3 +++
 .github/workflows/code-scanning-fixer.lock.yml         |  3 +++
 .github/workflows/code-simplifier.lock.yml             |  3 +++
 .../workflows/codex-github-remote-mcp-test.lock.yml    |  3 +++
 .github/workflows/commit-changes-analyzer.lock.yml     |  3 +++
 .github/workflows/constraint-solving-potd.lock.yml     |  3 +++
 .github/workflows/contribution-check.lock.yml          |  3 +++
 .github/workflows/copilot-agent-analysis.lock.yml      |  3 +++
 .github/workflows/copilot-cli-deep-research.lock.yml   |  3 +++
 .github/workflows/copilot-pr-merged-report.lock.yml    |  3 +++
 .github/workflows/copilot-pr-nlp-analysis.lock.yml     |  3 +++
 .github/workflows/copilot-pr-prompt-analysis.lock.yml  |  3 +++
 .github/workflows/copilot-session-insights.lock.yml    |  3 +++
 .github/workflows/copilot-token-audit.lock.yml         |  3 +++
 .github/workflows/copilot-token-optimizer.lock.yml     |  3 +++
 .github/workflows/craft.lock.yml                       |  3 +++
 .github/workflows/daily-architecture-diagram.lock.yml  |  3 +++
 .github/workflows/daily-assign-issue-to-user.lock.yml  |  3 +++
 .github/workflows/daily-choice-test.lock.yml           |  3 +++
 .github/workflows/daily-cli-performance.lock.yml       |  3 +++
 .github/workflows/daily-cli-tools-tester.lock.yml      |  3 +++
 .github/workflows/daily-code-metrics.lock.yml          |  3 +++
 .github/workflows/daily-community-attribution.lock.yml |  3 +++
 .github/workflows/daily-compiler-quality.lock.yml      |  3 +++
 .github/workflows/daily-doc-healer.lock.yml            |  3 +++
 .github/workflows/daily-doc-updater.lock.yml           |  3 +++
 .github/workflows/daily-fact.lock.yml                  |  3 +++
 .github/workflows/daily-file-diet.lock.yml             |  3 +++
 .github/workflows/daily-firewall-report.lock.yml       |  3 +++
 .github/workflows/daily-function-namer.lock.yml        |  3 +++
 .github/workflows/daily-integrity-analysis.lock.yml    |  3 +++
 .github/workflows/daily-issues-report.lock.yml         |  3 +++
 .github/workflows/daily-malicious-code-scan.lock.yml   |  3 +++
 .../workflows/daily-mcp-concurrency-analysis.lock.yml  |  3 +++
 .../workflows/daily-multi-device-docs-tester.lock.yml  |  3 +++
 .github/workflows/daily-news.lock.yml                  |  3 +++
 .github/workflows/daily-observability-report.lock.yml  |  3 +++
 .../daily-otel-instrumentation-advisor.lock.yml        |  3 +++
 .github/workflows/daily-performance-summary.lock.yml   |  3 +++
 .github/workflows/daily-regulatory.lock.yml            |  3 +++
 .../daily-rendering-scripts-verifier.lock.yml          |  3 +++
 .github/workflows/daily-repo-chronicle.lock.yml        |  3 +++
 .../workflows/daily-safe-output-integrator.lock.yml    |  3 +++
 .github/workflows/daily-safe-output-optimizer.lock.yml |  3 +++
 .../workflows/daily-safe-outputs-conformance.lock.yml  |  3 +++
 .github/workflows/daily-secrets-analysis.lock.yml      |  3 +++
 .github/workflows/daily-security-red-team.lock.yml     |  3 +++
 .github/workflows/daily-semgrep-scan.lock.yml          |  3 +++
 .github/workflows/daily-syntax-error-quality.lock.yml  |  3 +++
 .../workflows/daily-team-evolution-insights.lock.yml   |  3 +++
 .github/workflows/daily-team-status.lock.yml           |  3 +++
 .../workflows/daily-testify-uber-super-expert.lock.yml |  3 +++
 .github/workflows/daily-workflow-updater.lock.yml      |  3 +++
 .github/workflows/dead-code-remover.lock.yml           |  3 +++
 .github/workflows/deep-report.lock.yml                 |  3 +++
 .github/workflows/delight.lock.yml                     |  3 +++
 .github/workflows/dependabot-burner.lock.yml           |  3 +++
 .github/workflows/dependabot-go-checker.lock.yml       |  3 +++
 .github/workflows/dev-hawk.lock.yml                    |  3 +++
 .github/workflows/dev.lock.yml                         |  3 +++
 .github/workflows/developer-docs-consolidator.lock.yml |  3 +++
 .github/workflows/dictation-prompt.lock.yml            |  3 +++
 .github/workflows/discussion-task-miner.lock.yml       |  3 +++
 .github/workflows/docs-noob-tester.lock.yml            |  3 +++
 .github/workflows/draft-pr-cleanup.lock.yml            |  3 +++
 .github/workflows/duplicate-code-detector.lock.yml     |  3 +++
 .github/workflows/example-permissions-warning.lock.yml |  3 +++
 .github/workflows/example-workflow-analyzer.lock.yml   |  3 +++
 .github/workflows/firewall-escape.lock.yml             |  3 +++
 .github/workflows/firewall.lock.yml                    |  3 +++
 .github/workflows/functional-pragmatist.lock.yml       |  3 +++
 .../workflows/github-mcp-structural-analysis.lock.yml  |  3 +++
 .github/workflows/github-mcp-tools-report.lock.yml     |  3 +++
 .github/workflows/github-remote-mcp-auth-test.lock.yml |  3 +++
 .github/workflows/glossary-maintainer.lock.yml         |  3 +++
 .github/workflows/go-fan.lock.yml                      |  3 +++
 .github/workflows/go-logger.lock.yml                   |  3 +++
 .github/workflows/go-pattern-detector.lock.yml         |  3 +++
 .github/workflows/gpclean.lock.yml                     |  3 +++
 .github/workflows/grumpy-reviewer.lock.yml             |  3 +++
 .github/workflows/hourly-ci-cleaner.lock.yml           |  3 +++
 .github/workflows/instructions-janitor.lock.yml        |  3 +++
 .github/workflows/issue-arborist.lock.yml              |  3 +++
 .github/workflows/issue-monster.lock.yml               |  3 +++
 .github/workflows/issue-triage-agent.lock.yml          |  3 +++
 .github/workflows/jsweep.lock.yml                      |  3 +++
 .github/workflows/layout-spec-maintainer.lock.yml      |  3 +++
 .github/workflows/lockfile-stats.lock.yml              |  3 +++
 .github/workflows/mcp-inspector.lock.yml               |  3 +++
 .github/workflows/mergefest.lock.yml                   |  3 +++
 .github/workflows/metrics-collector.lock.yml           |  3 +++
 .github/workflows/notion-issue-summary.lock.yml        |  3 +++
 .github/workflows/org-health-report.lock.yml           |  3 +++
 .github/workflows/pdf-summary.lock.yml                 |  3 +++
 .github/workflows/plan.lock.yml                        |  3 +++
 .github/workflows/poem-bot.lock.yml                    |  3 +++
 .github/workflows/portfolio-analyst.lock.yml           |  3 +++
 .github/workflows/pr-nitpick-reviewer.lock.yml         |  3 +++
 .github/workflows/pr-triage-agent.lock.yml             |  3 +++
 .github/workflows/prompt-clustering-analysis.lock.yml  |  3 +++
 .github/workflows/python-data-charts.lock.yml          |  3 +++
 .github/workflows/q.lock.yml                           |  3 +++
 .github/workflows/refiner.lock.yml                     |  3 +++
 .github/workflows/release.lock.yml                     |  3 +++
 .github/workflows/repo-audit-analyzer.lock.yml         |  3 +++
 .github/workflows/repo-tree-map.lock.yml               |  3 +++
 .github/workflows/repository-quality-improver.lock.yml |  3 +++
 .github/workflows/research.lock.yml                    |  3 +++
 .github/workflows/safe-output-health.lock.yml          |  3 +++
 .github/workflows/schema-consistency-checker.lock.yml  |  3 +++
 .github/workflows/schema-feature-coverage.lock.yml     |  3 +++
 .github/workflows/scout.lock.yml                       |  3 +++
 .github/workflows/security-compliance.lock.yml         |  3 +++
 .github/workflows/security-review.lock.yml             |  3 +++
 .github/workflows/semantic-function-refactor.lock.yml  |  3 +++
 .github/workflows/sergo.lock.yml                       |  3 +++
 .github/workflows/slide-deck-maintainer.lock.yml       |  3 +++
 .github/workflows/smoke-agent-all-merged.lock.yml      |  3 +++
 .github/workflows/smoke-agent-all-none.lock.yml        |  3 +++
 .github/workflows/smoke-agent-public-approved.lock.yml |  3 +++
 .github/workflows/smoke-agent-public-none.lock.yml     |  3 +++
 .github/workflows/smoke-agent-scoped-approved.lock.yml |  3 +++
 .github/workflows/smoke-call-workflow.lock.yml         |  3 +++
 .github/workflows/smoke-claude.lock.yml                |  3 +++
 .github/workflows/smoke-codex.lock.yml                 |  3 +++
 .github/workflows/smoke-copilot-arm.lock.yml           |  3 +++
 .github/workflows/smoke-copilot.lock.yml               |  3 +++
 .github/workflows/smoke-create-cross-repo-pr.lock.yml  |  3 +++
 .github/workflows/smoke-gemini.lock.yml                |  3 +++
 .github/workflows/smoke-multi-pr.lock.yml              |  3 +++
 .github/workflows/smoke-project.lock.yml               |  3 +++
 .github/workflows/smoke-service-ports.lock.yml         |  3 +++
 .github/workflows/smoke-temporary-id.lock.yml          |  3 +++
 .github/workflows/smoke-test-tools.lock.yml            |  3 +++
 .github/workflows/smoke-update-cross-repo-pr.lock.yml  |  3 +++
 .../workflows/smoke-workflow-call-with-inputs.lock.yml |  3 +++
 .github/workflows/smoke-workflow-call.lock.yml         |  3 +++
 .github/workflows/stale-repo-identifier.lock.yml       |  3 +++
 .github/workflows/static-analysis-report.lock.yml      |  3 +++
 .github/workflows/step-name-alignment.lock.yml         |  3 +++
 .github/workflows/sub-issue-closer.lock.yml            |  3 +++
 .github/workflows/super-linter.lock.yml                |  3 +++
 .github/workflows/technical-doc-writer.lock.yml        |  3 +++
 .github/workflows/terminal-stylist.lock.yml            |  3 +++
 .../workflows/test-create-pr-error-handling.lock.yml   |  3 +++
 .github/workflows/test-dispatcher.lock.yml             |  3 +++
 .github/workflows/test-project-url-default.lock.yml    |  3 +++
 .github/workflows/test-workflow.lock.yml               |  3 +++
 .github/workflows/tidy.lock.yml                        |  3 +++
 .github/workflows/typist.lock.yml                      |  3 +++
 .github/workflows/ubuntu-image-analyzer.lock.yml       |  3 +++
 .github/workflows/unbloat-docs.lock.yml                |  3 +++
 .github/workflows/update-astro.lock.yml                |  3 +++
 .github/workflows/video-analyzer.lock.yml              |  3 +++
 .github/workflows/weekly-blog-post-writer.lock.yml     |  3 +++
 .github/workflows/weekly-editors-health-check.lock.yml |  3 +++
 .github/workflows/weekly-issue-summary.lock.yml        |  3 +++
 .../workflows/weekly-safe-outputs-spec-review.lock.yml |  3 +++
 .github/workflows/workflow-generator.lock.yml          |  3 +++
 .github/workflows/workflow-health-manager.lock.yml     |  3 +++
 .github/workflows/workflow-normalizer.lock.yml         |  3 +++
 .github/workflows/workflow-skill-extractor.lock.yml    |  3 +++
 actions/setup/js/check_rate_limit.cjs                  |  4 +---
 actions/setup/js/github_api_helpers.cjs                |  3 ---
 actions/setup/js/setup_globals.cjs                     | 10 +++++++++-
 184 files changed, 553 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/ace-editor.lock.yml b/.github/workflows/ace-editor.lock.yml
index 2431637827e..540b010f400 100644
--- a/.github/workflows/ace-editor.lock.yml
+++ b/.github/workflows/ace-editor.lock.yml
@@ -293,6 +293,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -566,6 +568,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
           if-no-files-found: ignore
       - name: Upload firewall audit logs
         if: always()
diff --git a/.github/workflows/agent-performance-analyzer.lock.yml b/.github/workflows/agent-performance-analyzer.lock.yml
index 2eaab07c469..fc7a18b2d79 100644
--- a/.github/workflows/agent-performance-analyzer.lock.yml
+++ b/.github/workflows/agent-performance-analyzer.lock.yml
@@ -276,6 +276,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -920,6 +922,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/agent-persona-explorer.lock.yml b/.github/workflows/agent-persona-explorer.lock.yml
index 5307a6f3f48..b9112fc9654 100644
--- a/.github/workflows/agent-persona-explorer.lock.yml
+++ b/.github/workflows/agent-persona-explorer.lock.yml
@@ -278,6 +278,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -875,6 +877,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/agentic-observability-kit.lock.yml b/.github/workflows/agentic-observability-kit.lock.yml
index 55f89223082..ec7a16f3b5f 100644
--- a/.github/workflows/agentic-observability-kit.lock.yml
+++ b/.github/workflows/agentic-observability-kit.lock.yml
@@ -265,6 +265,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -871,6 +873,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/ai-moderator.lock.yml b/.github/workflows/ai-moderator.lock.yml
index fd9ff79321d..69a4a940d5b 100644
--- a/.github/workflows/ai-moderator.lock.yml
+++ b/.github/workflows/ai-moderator.lock.yml
@@ -315,6 +315,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -845,6 +847,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
           if-no-files-found: ignore
diff --git a/.github/workflows/archie.lock.yml b/.github/workflows/archie.lock.yml
index 93e3a7d27b4..c242ba2cce5 100644
--- a/.github/workflows/archie.lock.yml
+++ b/.github/workflows/archie.lock.yml
@@ -356,6 +356,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -873,6 +875,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/artifacts-summary.lock.yml b/.github/workflows/artifacts-summary.lock.yml
index 17b95640e94..1ed3cd2443e 100644
--- a/.github/workflows/artifacts-summary.lock.yml
+++ b/.github/workflows/artifacts-summary.lock.yml
@@ -256,6 +256,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -751,6 +753,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml
index 93a94ecef63..141e4aaf533 100644
--- a/.github/workflows/audit-workflows.lock.yml
+++ b/.github/workflows/audit-workflows.lock.yml
@@ -298,6 +298,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1025,6 +1027,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/auto-triage-issues.lock.yml b/.github/workflows/auto-triage-issues.lock.yml
index d8f95a3b3b3..f7074b3d99b 100644
--- a/.github/workflows/auto-triage-issues.lock.yml
+++ b/.github/workflows/auto-triage-issues.lock.yml
@@ -276,6 +276,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -806,6 +808,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/blog-auditor.lock.yml b/.github/workflows/blog-auditor.lock.yml
index 7907c68b6c8..ea433381fdd 100644
--- a/.github/workflows/blog-auditor.lock.yml
+++ b/.github/workflows/blog-auditor.lock.yml
@@ -269,6 +269,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -885,6 +887,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/bot-detection.lock.yml b/.github/workflows/bot-detection.lock.yml
index 2f1482607be..4ac5dce881c 100644
--- a/.github/workflows/bot-detection.lock.yml
+++ b/.github/workflows/bot-detection.lock.yml
@@ -274,6 +274,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -835,6 +837,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
           if-no-files-found: ignore
diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml
index 605b898cad0..fa7de0a2bad 100644
--- a/.github/workflows/brave.lock.yml
+++ b/.github/workflows/brave.lock.yml
@@ -314,6 +314,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -820,6 +822,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/breaking-change-checker.lock.yml b/.github/workflows/breaking-change-checker.lock.yml
index 8b368aaf768..23eed94d170 100644
--- a/.github/workflows/breaking-change-checker.lock.yml
+++ b/.github/workflows/breaking-change-checker.lock.yml
@@ -265,6 +265,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -787,6 +789,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml
index bc0de0c7567..0b6b355ff7b 100644
--- a/.github/workflows/changeset.lock.yml
+++ b/.github/workflows/changeset.lock.yml
@@ -320,6 +320,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -859,6 +861,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml
index 583f7c99bf9..d5ba94d9e13 100644
--- a/.github/workflows/ci-coach.lock.yml
+++ b/.github/workflows/ci-coach.lock.yml
@@ -279,6 +279,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -851,6 +853,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/ci-doctor.lock.yml b/.github/workflows/ci-doctor.lock.yml
index 271b9ce8f7c..f0ccb1c8e9d 100644
--- a/.github/workflows/ci-doctor.lock.yml
+++ b/.github/workflows/ci-doctor.lock.yml
@@ -357,6 +357,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -990,6 +992,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/claude-code-user-docs-review.lock.yml b/.github/workflows/claude-code-user-docs-review.lock.yml
index e204419d06c..fb78364130a 100644
--- a/.github/workflows/claude-code-user-docs-review.lock.yml
+++ b/.github/workflows/claude-code-user-docs-review.lock.yml
@@ -274,6 +274,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -857,6 +859,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/cli-consistency-checker.lock.yml b/.github/workflows/cli-consistency-checker.lock.yml
index e1711477ad8..b99ffb19e4d 100644
--- a/.github/workflows/cli-consistency-checker.lock.yml
+++ b/.github/workflows/cli-consistency-checker.lock.yml
@@ -250,6 +250,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -754,6 +756,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/cli-version-checker.lock.yml b/.github/workflows/cli-version-checker.lock.yml
index a0182a918f2..9e72440e23e 100644
--- a/.github/workflows/cli-version-checker.lock.yml
+++ b/.github/workflows/cli-version-checker.lock.yml
@@ -274,6 +274,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -866,6 +868,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml
index 3394235a43f..01b967d883e 100644
--- a/.github/workflows/cloclo.lock.yml
+++ b/.github/workflows/cloclo.lock.yml
@@ -426,6 +426,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1208,6 +1210,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/code-scanning-fixer.lock.yml b/.github/workflows/code-scanning-fixer.lock.yml
index 3f3e2e228c6..a06dd1717c8 100644
--- a/.github/workflows/code-scanning-fixer.lock.yml
+++ b/.github/workflows/code-scanning-fixer.lock.yml
@@ -274,6 +274,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -843,6 +845,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/code-simplifier.lock.yml b/.github/workflows/code-simplifier.lock.yml
index f7c3970bc08..60f0e4af052 100644
--- a/.github/workflows/code-simplifier.lock.yml
+++ b/.github/workflows/code-simplifier.lock.yml
@@ -274,6 +274,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -779,6 +781,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/codex-github-remote-mcp-test.lock.yml b/.github/workflows/codex-github-remote-mcp-test.lock.yml
index 15c9bb10a45..90b74d3360a 100644
--- a/.github/workflows/codex-github-remote-mcp-test.lock.yml
+++ b/.github/workflows/codex-github-remote-mcp-test.lock.yml
@@ -251,6 +251,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -538,6 +540,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
           if-no-files-found: ignore
       - name: Upload firewall audit logs
         if: always()
diff --git a/.github/workflows/commit-changes-analyzer.lock.yml b/.github/workflows/commit-changes-analyzer.lock.yml
index b5378c50323..8285d5f4849 100644
--- a/.github/workflows/commit-changes-analyzer.lock.yml
+++ b/.github/workflows/commit-changes-analyzer.lock.yml
@@ -268,6 +268,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -818,6 +820,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/constraint-solving-potd.lock.yml b/.github/workflows/constraint-solving-potd.lock.yml
index e5d8d5f4a42..87c0de1fded 100644
--- a/.github/workflows/constraint-solving-potd.lock.yml
+++ b/.github/workflows/constraint-solving-potd.lock.yml
@@ -263,6 +263,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -769,6 +771,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/contribution-check.lock.yml b/.github/workflows/contribution-check.lock.yml
index 4885b2cf971..c81baa7016d 100644
--- a/.github/workflows/contribution-check.lock.yml
+++ b/.github/workflows/contribution-check.lock.yml
@@ -262,6 +262,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -803,6 +805,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/copilot-agent-analysis.lock.yml b/.github/workflows/copilot-agent-analysis.lock.yml
index 7ce56fe8eff..f28178fc638 100644
--- a/.github/workflows/copilot-agent-analysis.lock.yml
+++ b/.github/workflows/copilot-agent-analysis.lock.yml
@@ -293,6 +293,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -905,6 +907,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/copilot-cli-deep-research.lock.yml b/.github/workflows/copilot-cli-deep-research.lock.yml
index e6bd1d2e988..341c9c4ecb9 100644
--- a/.github/workflows/copilot-cli-deep-research.lock.yml
+++ b/.github/workflows/copilot-cli-deep-research.lock.yml
@@ -270,6 +270,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -809,6 +811,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/copilot-pr-merged-report.lock.yml b/.github/workflows/copilot-pr-merged-report.lock.yml
index 6d24e274178..b001fd9c8ee 100644
--- a/.github/workflows/copilot-pr-merged-report.lock.yml
+++ b/.github/workflows/copilot-pr-merged-report.lock.yml
@@ -273,6 +273,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -938,6 +940,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml
index 2484582e06b..2a3cd364e34 100644
--- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml
+++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml
@@ -293,6 +293,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -904,6 +906,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/copilot-pr-prompt-analysis.lock.yml b/.github/workflows/copilot-pr-prompt-analysis.lock.yml
index b0807bc76b6..eb00e9aaba0 100644
--- a/.github/workflows/copilot-pr-prompt-analysis.lock.yml
+++ b/.github/workflows/copilot-pr-prompt-analysis.lock.yml
@@ -286,6 +286,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -839,6 +841,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml
index 478167b2b88..ac22e5c5e3c 100644
--- a/.github/workflows/copilot-session-insights.lock.yml
+++ b/.github/workflows/copilot-session-insights.lock.yml
@@ -305,6 +305,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -968,6 +970,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/copilot-token-audit.lock.yml b/.github/workflows/copilot-token-audit.lock.yml
index 1d3de49d723..4bcdc0ddbd5 100644
--- a/.github/workflows/copilot-token-audit.lock.yml
+++ b/.github/workflows/copilot-token-audit.lock.yml
@@ -290,6 +290,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -942,6 +944,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/copilot-token-optimizer.lock.yml b/.github/workflows/copilot-token-optimizer.lock.yml
index 73253207cf6..ed58f669221 100644
--- a/.github/workflows/copilot-token-optimizer.lock.yml
+++ b/.github/workflows/copilot-token-optimizer.lock.yml
@@ -274,6 +274,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -836,6 +838,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/craft.lock.yml b/.github/workflows/craft.lock.yml
index 5fb4fd43f18..6d7616bc115 100644
--- a/.github/workflows/craft.lock.yml
+++ b/.github/workflows/craft.lock.yml
@@ -312,6 +312,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -824,6 +826,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-architecture-diagram.lock.yml b/.github/workflows/daily-architecture-diagram.lock.yml
index ed1093b1e8e..b749cbb7baf 100644
--- a/.github/workflows/daily-architecture-diagram.lock.yml
+++ b/.github/workflows/daily-architecture-diagram.lock.yml
@@ -268,6 +268,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -834,6 +836,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-assign-issue-to-user.lock.yml b/.github/workflows/daily-assign-issue-to-user.lock.yml
index 2977c2f9771..75c255ce503 100644
--- a/.github/workflows/daily-assign-issue-to-user.lock.yml
+++ b/.github/workflows/daily-assign-issue-to-user.lock.yml
@@ -252,6 +252,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -762,6 +764,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-choice-test.lock.yml b/.github/workflows/daily-choice-test.lock.yml
index c5e614e7448..e3912ed8d30 100644
--- a/.github/workflows/daily-choice-test.lock.yml
+++ b/.github/workflows/daily-choice-test.lock.yml
@@ -261,6 +261,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -817,6 +819,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-cli-performance.lock.yml b/.github/workflows/daily-cli-performance.lock.yml
index 071214cbbca..d0fb664eedb 100644
--- a/.github/workflows/daily-cli-performance.lock.yml
+++ b/.github/workflows/daily-cli-performance.lock.yml
@@ -307,6 +307,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -999,6 +1001,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-cli-tools-tester.lock.yml b/.github/workflows/daily-cli-tools-tester.lock.yml
index e488d9d4c1b..493362c45a5 100644
--- a/.github/workflows/daily-cli-tools-tester.lock.yml
+++ b/.github/workflows/daily-cli-tools-tester.lock.yml
@@ -268,6 +268,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -845,6 +847,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-code-metrics.lock.yml b/.github/workflows/daily-code-metrics.lock.yml
index 419e746a267..7a9dbcf4b99 100644
--- a/.github/workflows/daily-code-metrics.lock.yml
+++ b/.github/workflows/daily-code-metrics.lock.yml
@@ -294,6 +294,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -946,6 +948,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-community-attribution.lock.yml b/.github/workflows/daily-community-attribution.lock.yml
index 3af7ded9ad9..f949455688b 100644
--- a/.github/workflows/daily-community-attribution.lock.yml
+++ b/.github/workflows/daily-community-attribution.lock.yml
@@ -279,6 +279,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -845,6 +847,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-compiler-quality.lock.yml b/.github/workflows/daily-compiler-quality.lock.yml
index 9c36d3f6070..0b0d10c59ae 100644
--- a/.github/workflows/daily-compiler-quality.lock.yml
+++ b/.github/workflows/daily-compiler-quality.lock.yml
@@ -303,6 +303,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -883,6 +885,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-doc-healer.lock.yml b/.github/workflows/daily-doc-healer.lock.yml
index e534fb5b0f4..cf40d4b80f0 100644
--- a/.github/workflows/daily-doc-healer.lock.yml
+++ b/.github/workflows/daily-doc-healer.lock.yml
@@ -297,6 +297,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1005,6 +1007,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-doc-updater.lock.yml b/.github/workflows/daily-doc-updater.lock.yml
index 39b4d9580b9..f0d01637d58 100644
--- a/.github/workflows/daily-doc-updater.lock.yml
+++ b/.github/workflows/daily-doc-updater.lock.yml
@@ -296,6 +296,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -972,6 +974,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-fact.lock.yml b/.github/workflows/daily-fact.lock.yml
index 66e6bfeac5e..5921654ca08 100644
--- a/.github/workflows/daily-fact.lock.yml
+++ b/.github/workflows/daily-fact.lock.yml
@@ -333,6 +333,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -837,6 +839,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-file-diet.lock.yml b/.github/workflows/daily-file-diet.lock.yml
index 0aa24ebc80d..27d5916b4fc 100644
--- a/.github/workflows/daily-file-diet.lock.yml
+++ b/.github/workflows/daily-file-diet.lock.yml
@@ -303,6 +303,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -860,6 +862,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-firewall-report.lock.yml b/.github/workflows/daily-firewall-report.lock.yml
index 80f4861642f..fdc903d59f7 100644
--- a/.github/workflows/daily-firewall-report.lock.yml
+++ b/.github/workflows/daily-firewall-report.lock.yml
@@ -281,6 +281,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -929,6 +931,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-function-namer.lock.yml b/.github/workflows/daily-function-namer.lock.yml
index d6bf089b5fb..f27ce5d3ebb 100644
--- a/.github/workflows/daily-function-namer.lock.yml
+++ b/.github/workflows/daily-function-namer.lock.yml
@@ -309,6 +309,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -923,6 +925,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-integrity-analysis.lock.yml b/.github/workflows/daily-integrity-analysis.lock.yml
index bbf9d70d799..d81f04044a3 100644
--- a/.github/workflows/daily-integrity-analysis.lock.yml
+++ b/.github/workflows/daily-integrity-analysis.lock.yml
@@ -283,6 +283,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -946,6 +948,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml
index a8c11e16283..d60466620ad 100644
--- a/.github/workflows/daily-issues-report.lock.yml
+++ b/.github/workflows/daily-issues-report.lock.yml
@@ -297,6 +297,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -915,6 +917,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-malicious-code-scan.lock.yml b/.github/workflows/daily-malicious-code-scan.lock.yml
index a642c8c544c..e3a66f4dc20 100644
--- a/.github/workflows/daily-malicious-code-scan.lock.yml
+++ b/.github/workflows/daily-malicious-code-scan.lock.yml
@@ -257,6 +257,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -766,6 +768,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
           if-no-files-found: ignore
diff --git a/.github/workflows/daily-mcp-concurrency-analysis.lock.yml b/.github/workflows/daily-mcp-concurrency-analysis.lock.yml
index ff73ccb5bdc..cbee0a5aab7 100644
--- a/.github/workflows/daily-mcp-concurrency-analysis.lock.yml
+++ b/.github/workflows/daily-mcp-concurrency-analysis.lock.yml
@@ -301,6 +301,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -900,6 +902,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-multi-device-docs-tester.lock.yml b/.github/workflows/daily-multi-device-docs-tester.lock.yml
index 42a127a917e..6ea43880a6d 100644
--- a/.github/workflows/daily-multi-device-docs-tester.lock.yml
+++ b/.github/workflows/daily-multi-device-docs-tester.lock.yml
@@ -280,6 +280,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -937,6 +939,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml
index b840d662f4e..ec10030ee05 100644
--- a/.github/workflows/daily-news.lock.yml
+++ b/.github/workflows/daily-news.lock.yml
@@ -291,6 +291,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -980,6 +982,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-observability-report.lock.yml b/.github/workflows/daily-observability-report.lock.yml
index 39eef8b3e5a..df17bca11d4 100644
--- a/.github/workflows/daily-observability-report.lock.yml
+++ b/.github/workflows/daily-observability-report.lock.yml
@@ -277,6 +277,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -872,6 +874,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-otel-instrumentation-advisor.lock.yml b/.github/workflows/daily-otel-instrumentation-advisor.lock.yml
index 6232ba42a9d..8bf5249042b 100644
--- a/.github/workflows/daily-otel-instrumentation-advisor.lock.yml
+++ b/.github/workflows/daily-otel-instrumentation-advisor.lock.yml
@@ -269,6 +269,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -843,6 +845,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-performance-summary.lock.yml b/.github/workflows/daily-performance-summary.lock.yml
index 44d10b11fe7..5e6b5df98ce 100644
--- a/.github/workflows/daily-performance-summary.lock.yml
+++ b/.github/workflows/daily-performance-summary.lock.yml
@@ -281,6 +281,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1338,6 +1340,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-regulatory.lock.yml b/.github/workflows/daily-regulatory.lock.yml
index 3d9c83e16d7..e59541b889b 100644
--- a/.github/workflows/daily-regulatory.lock.yml
+++ b/.github/workflows/daily-regulatory.lock.yml
@@ -267,6 +267,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1248,6 +1250,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-rendering-scripts-verifier.lock.yml b/.github/workflows/daily-rendering-scripts-verifier.lock.yml
index 1166c7ac8a3..a190725babb 100644
--- a/.github/workflows/daily-rendering-scripts-verifier.lock.yml
+++ b/.github/workflows/daily-rendering-scripts-verifier.lock.yml
@@ -290,6 +290,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -985,6 +987,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-repo-chronicle.lock.yml b/.github/workflows/daily-repo-chronicle.lock.yml
index 33e2601cf0a..43cd44f6338 100644
--- a/.github/workflows/daily-repo-chronicle.lock.yml
+++ b/.github/workflows/daily-repo-chronicle.lock.yml
@@ -272,6 +272,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -847,6 +849,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-safe-output-integrator.lock.yml b/.github/workflows/daily-safe-output-integrator.lock.yml
index 51e478de403..ed7f1ca90fa 100644
--- a/.github/workflows/daily-safe-output-integrator.lock.yml
+++ b/.github/workflows/daily-safe-output-integrator.lock.yml
@@ -261,6 +261,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -801,6 +803,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-safe-output-optimizer.lock.yml b/.github/workflows/daily-safe-output-optimizer.lock.yml
index 5ab423722bd..90e559f3b13 100644
--- a/.github/workflows/daily-safe-output-optimizer.lock.yml
+++ b/.github/workflows/daily-safe-output-optimizer.lock.yml
@@ -289,6 +289,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -973,6 +975,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-safe-outputs-conformance.lock.yml b/.github/workflows/daily-safe-outputs-conformance.lock.yml
index 7c9637b1f7d..94f550f3339 100644
--- a/.github/workflows/daily-safe-outputs-conformance.lock.yml
+++ b/.github/workflows/daily-safe-outputs-conformance.lock.yml
@@ -265,6 +265,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -822,6 +824,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-secrets-analysis.lock.yml b/.github/workflows/daily-secrets-analysis.lock.yml
index 897385dd717..55c1a525ff1 100644
--- a/.github/workflows/daily-secrets-analysis.lock.yml
+++ b/.github/workflows/daily-secrets-analysis.lock.yml
@@ -258,6 +258,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -755,6 +757,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-security-red-team.lock.yml b/.github/workflows/daily-security-red-team.lock.yml
index 6d05097abad..f87ab19587d 100644
--- a/.github/workflows/daily-security-red-team.lock.yml
+++ b/.github/workflows/daily-security-red-team.lock.yml
@@ -269,6 +269,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -826,6 +828,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-semgrep-scan.lock.yml b/.github/workflows/daily-semgrep-scan.lock.yml
index 19d14f5e973..ed59195d3ec 100644
--- a/.github/workflows/daily-semgrep-scan.lock.yml
+++ b/.github/workflows/daily-semgrep-scan.lock.yml
@@ -263,6 +263,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -792,6 +794,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-syntax-error-quality.lock.yml b/.github/workflows/daily-syntax-error-quality.lock.yml
index 83099366950..2ceae869949 100644
--- a/.github/workflows/daily-syntax-error-quality.lock.yml
+++ b/.github/workflows/daily-syntax-error-quality.lock.yml
@@ -257,6 +257,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -792,6 +794,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-team-evolution-insights.lock.yml b/.github/workflows/daily-team-evolution-insights.lock.yml
index b5a7ef4fa14..d06e9aa9436 100644
--- a/.github/workflows/daily-team-evolution-insights.lock.yml
+++ b/.github/workflows/daily-team-evolution-insights.lock.yml
@@ -266,6 +266,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -819,6 +821,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-team-status.lock.yml b/.github/workflows/daily-team-status.lock.yml
index a34e0f02fe3..7b715fd80f8 100644
--- a/.github/workflows/daily-team-status.lock.yml
+++ b/.github/workflows/daily-team-status.lock.yml
@@ -274,6 +274,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -776,6 +778,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-testify-uber-super-expert.lock.yml b/.github/workflows/daily-testify-uber-super-expert.lock.yml
index 3383c1d9f7f..3c709720e2c 100644
--- a/.github/workflows/daily-testify-uber-super-expert.lock.yml
+++ b/.github/workflows/daily-testify-uber-super-expert.lock.yml
@@ -317,6 +317,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -897,6 +899,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/daily-workflow-updater.lock.yml b/.github/workflows/daily-workflow-updater.lock.yml
index 1276036e0a6..d9550d0d3c4 100644
--- a/.github/workflows/daily-workflow-updater.lock.yml
+++ b/.github/workflows/daily-workflow-updater.lock.yml
@@ -257,6 +257,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -763,6 +765,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/dead-code-remover.lock.yml b/.github/workflows/dead-code-remover.lock.yml
index 6f741766018..b384c2f9448 100644
--- a/.github/workflows/dead-code-remover.lock.yml
+++ b/.github/workflows/dead-code-remover.lock.yml
@@ -279,6 +279,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -821,6 +823,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml
index a1d55569058..9bfec1364e8 100644
--- a/.github/workflows/deep-report.lock.yml
+++ b/.github/workflows/deep-report.lock.yml
@@ -296,6 +296,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1052,6 +1054,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/delight.lock.yml b/.github/workflows/delight.lock.yml
index 7dae79b3f72..d8f9536785d 100644
--- a/.github/workflows/delight.lock.yml
+++ b/.github/workflows/delight.lock.yml
@@ -273,6 +273,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -849,6 +851,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/dependabot-burner.lock.yml b/.github/workflows/dependabot-burner.lock.yml
index b9c331b35ff..f3cf2fc4f6c 100644
--- a/.github/workflows/dependabot-burner.lock.yml
+++ b/.github/workflows/dependabot-burner.lock.yml
@@ -264,6 +264,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -766,6 +768,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/dependabot-go-checker.lock.yml b/.github/workflows/dependabot-go-checker.lock.yml
index 78efd98af8e..cf021405dda 100644
--- a/.github/workflows/dependabot-go-checker.lock.yml
+++ b/.github/workflows/dependabot-go-checker.lock.yml
@@ -260,6 +260,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -783,6 +785,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/dev-hawk.lock.yml b/.github/workflows/dev-hawk.lock.yml
index 3ea2bb6c4dc..951dd68b21e 100644
--- a/.github/workflows/dev-hawk.lock.yml
+++ b/.github/workflows/dev-hawk.lock.yml
@@ -284,6 +284,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -862,6 +864,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml
index 55359b62602..aae835d8ba7 100644
--- a/.github/workflows/dev.lock.yml
+++ b/.github/workflows/dev.lock.yml
@@ -335,6 +335,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -893,6 +895,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml
index 0f07a147f88..4333650b9b8 100644
--- a/.github/workflows/developer-docs-consolidator.lock.yml
+++ b/.github/workflows/developer-docs-consolidator.lock.yml
@@ -342,6 +342,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1089,6 +1091,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/dictation-prompt.lock.yml b/.github/workflows/dictation-prompt.lock.yml
index d7377127b58..5f9523e0f48 100644
--- a/.github/workflows/dictation-prompt.lock.yml
+++ b/.github/workflows/dictation-prompt.lock.yml
@@ -279,6 +279,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -842,6 +844,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/discussion-task-miner.lock.yml b/.github/workflows/discussion-task-miner.lock.yml
index 9aa2942ea66..1811e0c9599 100644
--- a/.github/workflows/discussion-task-miner.lock.yml
+++ b/.github/workflows/discussion-task-miner.lock.yml
@@ -272,6 +272,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -839,6 +841,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/docs-noob-tester.lock.yml b/.github/workflows/docs-noob-tester.lock.yml
index 25fe79bfa60..f41c6badf0c 100644
--- a/.github/workflows/docs-noob-tester.lock.yml
+++ b/.github/workflows/docs-noob-tester.lock.yml
@@ -264,6 +264,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -806,6 +808,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/draft-pr-cleanup.lock.yml b/.github/workflows/draft-pr-cleanup.lock.yml
index a41a1a68e96..9e33c3a5685 100644
--- a/.github/workflows/draft-pr-cleanup.lock.yml
+++ b/.github/workflows/draft-pr-cleanup.lock.yml
@@ -250,6 +250,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -792,6 +794,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml
index 2d88927bc09..6b2a9510000 100644
--- a/.github/workflows/duplicate-code-detector.lock.yml
+++ b/.github/workflows/duplicate-code-detector.lock.yml
@@ -307,6 +307,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -865,6 +867,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/example-permissions-warning.lock.yml b/.github/workflows/example-permissions-warning.lock.yml
index 18d14538d63..01e43abcb71 100644
--- a/.github/workflows/example-permissions-warning.lock.yml
+++ b/.github/workflows/example-permissions-warning.lock.yml
@@ -247,6 +247,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -533,6 +535,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
           if-no-files-found: ignore
       - name: Upload firewall audit logs
         if: always()
diff --git a/.github/workflows/example-workflow-analyzer.lock.yml b/.github/workflows/example-workflow-analyzer.lock.yml
index 68a104df475..e07115cef79 100644
--- a/.github/workflows/example-workflow-analyzer.lock.yml
+++ b/.github/workflows/example-workflow-analyzer.lock.yml
@@ -266,6 +266,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -891,6 +893,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/firewall-escape.lock.yml b/.github/workflows/firewall-escape.lock.yml
index f3489c90b97..6b6df4975c5 100644
--- a/.github/workflows/firewall-escape.lock.yml
+++ b/.github/workflows/firewall-escape.lock.yml
@@ -297,6 +297,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -838,6 +840,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/firewall.lock.yml b/.github/workflows/firewall.lock.yml
index 600b8180d26..7827014a7b3 100644
--- a/.github/workflows/firewall.lock.yml
+++ b/.github/workflows/firewall.lock.yml
@@ -249,6 +249,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -535,6 +537,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
           if-no-files-found: ignore
       - name: Upload firewall audit logs
         if: always()
diff --git a/.github/workflows/functional-pragmatist.lock.yml b/.github/workflows/functional-pragmatist.lock.yml
index 4350fc0e8dd..d04aec1fa67 100644
--- a/.github/workflows/functional-pragmatist.lock.yml
+++ b/.github/workflows/functional-pragmatist.lock.yml
@@ -265,6 +265,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -770,6 +772,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/github-mcp-structural-analysis.lock.yml b/.github/workflows/github-mcp-structural-analysis.lock.yml
index d18c31d21c4..0201c5924b2 100644
--- a/.github/workflows/github-mcp-structural-analysis.lock.yml
+++ b/.github/workflows/github-mcp-structural-analysis.lock.yml
@@ -278,6 +278,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -914,6 +916,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml
index 47c21413cfd..1c28672d27b 100644
--- a/.github/workflows/github-mcp-tools-report.lock.yml
+++ b/.github/workflows/github-mcp-tools-report.lock.yml
@@ -276,6 +276,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -897,6 +899,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/github-remote-mcp-auth-test.lock.yml b/.github/workflows/github-remote-mcp-auth-test.lock.yml
index 89858eeead2..ac201b4ba78 100644
--- a/.github/workflows/github-remote-mcp-auth-test.lock.yml
+++ b/.github/workflows/github-remote-mcp-auth-test.lock.yml
@@ -265,6 +265,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -769,6 +771,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml
index 0909c2b7911..bee4f9ef224 100644
--- a/.github/workflows/glossary-maintainer.lock.yml
+++ b/.github/workflows/glossary-maintainer.lock.yml
@@ -342,6 +342,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -990,6 +992,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/go-fan.lock.yml b/.github/workflows/go-fan.lock.yml
index f4dc8a28c44..8b41bca992b 100644
--- a/.github/workflows/go-fan.lock.yml
+++ b/.github/workflows/go-fan.lock.yml
@@ -310,6 +310,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -944,6 +946,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml
index c77a89ccfe0..3a74cf342db 100644
--- a/.github/workflows/go-logger.lock.yml
+++ b/.github/workflows/go-logger.lock.yml
@@ -275,6 +275,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1061,6 +1063,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/go-pattern-detector.lock.yml b/.github/workflows/go-pattern-detector.lock.yml
index b537b883f5e..c960ff1c035 100644
--- a/.github/workflows/go-pattern-detector.lock.yml
+++ b/.github/workflows/go-pattern-detector.lock.yml
@@ -269,6 +269,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -845,6 +847,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/gpclean.lock.yml b/.github/workflows/gpclean.lock.yml
index 2bbcc5b7228..3b57f9d473a 100644
--- a/.github/workflows/gpclean.lock.yml
+++ b/.github/workflows/gpclean.lock.yml
@@ -270,6 +270,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -804,6 +806,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/grumpy-reviewer.lock.yml b/.github/workflows/grumpy-reviewer.lock.yml
index c0d38831b67..ee693587404 100644
--- a/.github/workflows/grumpy-reviewer.lock.yml
+++ b/.github/workflows/grumpy-reviewer.lock.yml
@@ -337,6 +337,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -902,6 +904,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/hourly-ci-cleaner.lock.yml b/.github/workflows/hourly-ci-cleaner.lock.yml
index 4896629747e..7864431bf11 100644
--- a/.github/workflows/hourly-ci-cleaner.lock.yml
+++ b/.github/workflows/hourly-ci-cleaner.lock.yml
@@ -280,6 +280,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -883,6 +885,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/instructions-janitor.lock.yml b/.github/workflows/instructions-janitor.lock.yml
index a4f46f800ed..6d5601f4b65 100644
--- a/.github/workflows/instructions-janitor.lock.yml
+++ b/.github/workflows/instructions-janitor.lock.yml
@@ -269,6 +269,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -882,6 +884,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/issue-arborist.lock.yml b/.github/workflows/issue-arborist.lock.yml
index dc691402080..952c691a188 100644
--- a/.github/workflows/issue-arborist.lock.yml
+++ b/.github/workflows/issue-arborist.lock.yml
@@ -268,6 +268,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -854,6 +856,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/issue-monster.lock.yml b/.github/workflows/issue-monster.lock.yml
index 9c14bb0ded3..5f41d1c2f3c 100644
--- a/.github/workflows/issue-monster.lock.yml
+++ b/.github/workflows/issue-monster.lock.yml
@@ -643,6 +643,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1155,6 +1157,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/issue-triage-agent.lock.yml b/.github/workflows/issue-triage-agent.lock.yml
index dec5dfe8147..96f5b2fc85e 100644
--- a/.github/workflows/issue-triage-agent.lock.yml
+++ b/.github/workflows/issue-triage-agent.lock.yml
@@ -262,6 +262,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -754,6 +756,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/jsweep.lock.yml b/.github/workflows/jsweep.lock.yml
index 336930f8d83..afdb655e808 100644
--- a/.github/workflows/jsweep.lock.yml
+++ b/.github/workflows/jsweep.lock.yml
@@ -307,6 +307,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -877,6 +879,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/layout-spec-maintainer.lock.yml b/.github/workflows/layout-spec-maintainer.lock.yml
index 1909a89c3ed..348cb6847bf 100644
--- a/.github/workflows/layout-spec-maintainer.lock.yml
+++ b/.github/workflows/layout-spec-maintainer.lock.yml
@@ -262,6 +262,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -803,6 +805,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/lockfile-stats.lock.yml b/.github/workflows/lockfile-stats.lock.yml
index 8879d88fc21..0c88f30430c 100644
--- a/.github/workflows/lockfile-stats.lock.yml
+++ b/.github/workflows/lockfile-stats.lock.yml
@@ -272,6 +272,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -853,6 +855,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml
index e9572a79519..80b9d6d90be 100644
--- a/.github/workflows/mcp-inspector.lock.yml
+++ b/.github/workflows/mcp-inspector.lock.yml
@@ -353,6 +353,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1323,6 +1325,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/mergefest.lock.yml b/.github/workflows/mergefest.lock.yml
index b7a4ebfc52f..d459c436a05 100644
--- a/.github/workflows/mergefest.lock.yml
+++ b/.github/workflows/mergefest.lock.yml
@@ -314,6 +314,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -842,6 +844,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/metrics-collector.lock.yml b/.github/workflows/metrics-collector.lock.yml
index 21c2995ee9f..4e48d54d979 100644
--- a/.github/workflows/metrics-collector.lock.yml
+++ b/.github/workflows/metrics-collector.lock.yml
@@ -274,6 +274,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -657,6 +659,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
           if-no-files-found: ignore
       - name: Upload firewall audit logs
         if: always()
diff --git a/.github/workflows/notion-issue-summary.lock.yml b/.github/workflows/notion-issue-summary.lock.yml
index f64292e1cbe..8557c0cdc00 100644
--- a/.github/workflows/notion-issue-summary.lock.yml
+++ b/.github/workflows/notion-issue-summary.lock.yml
@@ -266,6 +266,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -771,6 +773,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/org-health-report.lock.yml b/.github/workflows/org-health-report.lock.yml
index b515b45e849..2ad1bd79f15 100644
--- a/.github/workflows/org-health-report.lock.yml
+++ b/.github/workflows/org-health-report.lock.yml
@@ -278,6 +278,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -856,6 +858,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml
index 9e03cceb3a6..9efc9b61a7c 100644
--- a/.github/workflows/pdf-summary.lock.yml
+++ b/.github/workflows/pdf-summary.lock.yml
@@ -358,6 +358,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -912,6 +914,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml
index d2a8eca1950..dceb24ee08a 100644
--- a/.github/workflows/plan.lock.yml
+++ b/.github/workflows/plan.lock.yml
@@ -315,6 +315,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -845,6 +847,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml
index 4e672f629c4..7f2fc2717ac 100644
--- a/.github/workflows/poem-bot.lock.yml
+++ b/.github/workflows/poem-bot.lock.yml
@@ -353,6 +353,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1201,6 +1203,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/portfolio-analyst.lock.yml b/.github/workflows/portfolio-analyst.lock.yml
index 519a5c2b339..47ebfed14ac 100644
--- a/.github/workflows/portfolio-analyst.lock.yml
+++ b/.github/workflows/portfolio-analyst.lock.yml
@@ -282,6 +282,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -946,6 +948,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/pr-nitpick-reviewer.lock.yml b/.github/workflows/pr-nitpick-reviewer.lock.yml
index 5e33afd4eae..e5c33f932e2 100644
--- a/.github/workflows/pr-nitpick-reviewer.lock.yml
+++ b/.github/workflows/pr-nitpick-reviewer.lock.yml
@@ -332,6 +332,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -909,6 +911,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/pr-triage-agent.lock.yml b/.github/workflows/pr-triage-agent.lock.yml
index ca2e0342bce..67a67ca1407 100644
--- a/.github/workflows/pr-triage-agent.lock.yml
+++ b/.github/workflows/pr-triage-agent.lock.yml
@@ -276,6 +276,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -837,6 +839,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/prompt-clustering-analysis.lock.yml b/.github/workflows/prompt-clustering-analysis.lock.yml
index ea098ec641b..c24de855f14 100644
--- a/.github/workflows/prompt-clustering-analysis.lock.yml
+++ b/.github/workflows/prompt-clustering-analysis.lock.yml
@@ -288,6 +288,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -997,6 +999,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/python-data-charts.lock.yml b/.github/workflows/python-data-charts.lock.yml
index df3a4f40b92..dd8b833912d 100644
--- a/.github/workflows/python-data-charts.lock.yml
+++ b/.github/workflows/python-data-charts.lock.yml
@@ -279,6 +279,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -925,6 +927,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml
index 34fb96901b7..17ede46841f 100644
--- a/.github/workflows/q.lock.yml
+++ b/.github/workflows/q.lock.yml
@@ -399,6 +399,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1073,6 +1075,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/refiner.lock.yml b/.github/workflows/refiner.lock.yml
index 85a2fa790d9..0d3cf210cbe 100644
--- a/.github/workflows/refiner.lock.yml
+++ b/.github/workflows/refiner.lock.yml
@@ -298,6 +298,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -821,6 +823,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml
index 72b826bef13..b4b8a2b1d3d 100644
--- a/.github/workflows/release.lock.yml
+++ b/.github/workflows/release.lock.yml
@@ -281,6 +281,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -808,6 +810,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/repo-audit-analyzer.lock.yml b/.github/workflows/repo-audit-analyzer.lock.yml
index 2df0941c861..a5cb40cc74f 100644
--- a/.github/workflows/repo-audit-analyzer.lock.yml
+++ b/.github/workflows/repo-audit-analyzer.lock.yml
@@ -276,6 +276,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -797,6 +799,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/repo-tree-map.lock.yml b/.github/workflows/repo-tree-map.lock.yml
index 8f06d434898..455f33c60a8 100644
--- a/.github/workflows/repo-tree-map.lock.yml
+++ b/.github/workflows/repo-tree-map.lock.yml
@@ -260,6 +260,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -755,6 +757,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/repository-quality-improver.lock.yml b/.github/workflows/repository-quality-improver.lock.yml
index edcaccb1ddb..3111eebbb80 100644
--- a/.github/workflows/repository-quality-improver.lock.yml
+++ b/.github/workflows/repository-quality-improver.lock.yml
@@ -306,6 +306,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -858,6 +860,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/research.lock.yml b/.github/workflows/research.lock.yml
index 2f23cd11b72..1f1c024af99 100644
--- a/.github/workflows/research.lock.yml
+++ b/.github/workflows/research.lock.yml
@@ -270,6 +270,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -786,6 +788,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/safe-output-health.lock.yml b/.github/workflows/safe-output-health.lock.yml
index 66948a8606a..699005ad749 100644
--- a/.github/workflows/safe-output-health.lock.yml
+++ b/.github/workflows/safe-output-health.lock.yml
@@ -280,6 +280,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -957,6 +959,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/schema-consistency-checker.lock.yml b/.github/workflows/schema-consistency-checker.lock.yml
index 536ecb8a138..a2394df193e 100644
--- a/.github/workflows/schema-consistency-checker.lock.yml
+++ b/.github/workflows/schema-consistency-checker.lock.yml
@@ -271,6 +271,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -853,6 +855,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/schema-feature-coverage.lock.yml b/.github/workflows/schema-feature-coverage.lock.yml
index 14464c897b1..25cfda0cab9 100644
--- a/.github/workflows/schema-feature-coverage.lock.yml
+++ b/.github/workflows/schema-feature-coverage.lock.yml
@@ -269,6 +269,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -789,6 +791,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml
index b26ee31aaeb..8a924a7a99e 100644
--- a/.github/workflows/scout.lock.yml
+++ b/.github/workflows/scout.lock.yml
@@ -395,6 +395,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1092,6 +1094,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/security-compliance.lock.yml b/.github/workflows/security-compliance.lock.yml
index 62949a66b8e..dc7d66a8f74 100644
--- a/.github/workflows/security-compliance.lock.yml
+++ b/.github/workflows/security-compliance.lock.yml
@@ -290,6 +290,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -808,6 +810,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/security-review.lock.yml b/.github/workflows/security-review.lock.yml
index 5ab9fdeb772..d5f5eda2774 100644
--- a/.github/workflows/security-review.lock.yml
+++ b/.github/workflows/security-review.lock.yml
@@ -333,6 +333,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -960,6 +962,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/semantic-function-refactor.lock.yml b/.github/workflows/semantic-function-refactor.lock.yml
index c711f76c879..8963410f616 100644
--- a/.github/workflows/semantic-function-refactor.lock.yml
+++ b/.github/workflows/semantic-function-refactor.lock.yml
@@ -299,6 +299,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -921,6 +923,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/sergo.lock.yml b/.github/workflows/sergo.lock.yml
index 6f2ef73894a..61ffb071d75 100644
--- a/.github/workflows/sergo.lock.yml
+++ b/.github/workflows/sergo.lock.yml
@@ -308,6 +308,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -933,6 +935,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/slide-deck-maintainer.lock.yml b/.github/workflows/slide-deck-maintainer.lock.yml
index f942e80f6cb..2fde7f76df3 100644
--- a/.github/workflows/slide-deck-maintainer.lock.yml
+++ b/.github/workflows/slide-deck-maintainer.lock.yml
@@ -296,6 +296,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -893,6 +895,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-agent-all-merged.lock.yml b/.github/workflows/smoke-agent-all-merged.lock.yml
index e806e84a031..797d69ec4b9 100644
--- a/.github/workflows/smoke-agent-all-merged.lock.yml
+++ b/.github/workflows/smoke-agent-all-merged.lock.yml
@@ -303,6 +303,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -803,6 +805,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-agent-all-none.lock.yml b/.github/workflows/smoke-agent-all-none.lock.yml
index a149d46ee21..df1c03c4b31 100644
--- a/.github/workflows/smoke-agent-all-none.lock.yml
+++ b/.github/workflows/smoke-agent-all-none.lock.yml
@@ -303,6 +303,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -803,6 +805,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-agent-public-approved.lock.yml b/.github/workflows/smoke-agent-public-approved.lock.yml
index 560dcf5d038..1b683da0377 100644
--- a/.github/workflows/smoke-agent-public-approved.lock.yml
+++ b/.github/workflows/smoke-agent-public-approved.lock.yml
@@ -306,6 +306,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -833,6 +835,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-agent-public-none.lock.yml b/.github/workflows/smoke-agent-public-none.lock.yml
index d0e683b0d5e..dd4aef80124 100644
--- a/.github/workflows/smoke-agent-public-none.lock.yml
+++ b/.github/workflows/smoke-agent-public-none.lock.yml
@@ -303,6 +303,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -803,6 +805,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-agent-scoped-approved.lock.yml b/.github/workflows/smoke-agent-scoped-approved.lock.yml
index ccfaa0fe9a2..ce862ca48cd 100644
--- a/.github/workflows/smoke-agent-scoped-approved.lock.yml
+++ b/.github/workflows/smoke-agent-scoped-approved.lock.yml
@@ -305,6 +305,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -810,6 +812,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-call-workflow.lock.yml b/.github/workflows/smoke-call-workflow.lock.yml
index d98cfc4a302..c8c1b55463f 100644
--- a/.github/workflows/smoke-call-workflow.lock.yml
+++ b/.github/workflows/smoke-call-workflow.lock.yml
@@ -285,6 +285,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -785,6 +787,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml
index 30ecd06738c..ec1061b119d 100644
--- a/.github/workflows/smoke-claude.lock.yml
+++ b/.github/workflows/smoke-claude.lock.yml
@@ -735,6 +735,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -2359,6 +2361,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml
index 80a2a734603..b9bbdb6f273 100644
--- a/.github/workflows/smoke-codex.lock.yml
+++ b/.github/workflows/smoke-codex.lock.yml
@@ -396,6 +396,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1368,6 +1370,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-copilot-arm.lock.yml b/.github/workflows/smoke-copilot-arm.lock.yml
index a075c58c8d9..1175f0aa056 100644
--- a/.github/workflows/smoke-copilot-arm.lock.yml
+++ b/.github/workflows/smoke-copilot-arm.lock.yml
@@ -373,6 +373,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1737,6 +1739,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml
index a48acdcc427..c1c841ab6a0 100644
--- a/.github/workflows/smoke-copilot.lock.yml
+++ b/.github/workflows/smoke-copilot.lock.yml
@@ -382,6 +382,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1789,6 +1791,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-create-cross-repo-pr.lock.yml b/.github/workflows/smoke-create-cross-repo-pr.lock.yml
index b10e69a8db9..4cfb9db27ad 100644
--- a/.github/workflows/smoke-create-cross-repo-pr.lock.yml
+++ b/.github/workflows/smoke-create-cross-repo-pr.lock.yml
@@ -308,6 +308,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -872,6 +874,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-gemini.lock.yml b/.github/workflows/smoke-gemini.lock.yml
index 66eee9d61ea..a95b361fcd8 100644
--- a/.github/workflows/smoke-gemini.lock.yml
+++ b/.github/workflows/smoke-gemini.lock.yml
@@ -334,6 +334,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1027,6 +1029,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-multi-pr.lock.yml b/.github/workflows/smoke-multi-pr.lock.yml
index 08fec133110..98a0d6c1949 100644
--- a/.github/workflows/smoke-multi-pr.lock.yml
+++ b/.github/workflows/smoke-multi-pr.lock.yml
@@ -319,6 +319,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -865,6 +867,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-project.lock.yml b/.github/workflows/smoke-project.lock.yml
index 069bc2ae8c8..7fa2775f4a4 100644
--- a/.github/workflows/smoke-project.lock.yml
+++ b/.github/workflows/smoke-project.lock.yml
@@ -317,6 +317,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -999,6 +1001,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-service-ports.lock.yml b/.github/workflows/smoke-service-ports.lock.yml
index b098901a0a0..9e7e8c32610 100644
--- a/.github/workflows/smoke-service-ports.lock.yml
+++ b/.github/workflows/smoke-service-ports.lock.yml
@@ -281,6 +281,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -774,6 +776,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-temporary-id.lock.yml b/.github/workflows/smoke-temporary-id.lock.yml
index 44805ffbecb..290efd0882e 100644
--- a/.github/workflows/smoke-temporary-id.lock.yml
+++ b/.github/workflows/smoke-temporary-id.lock.yml
@@ -312,6 +312,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -850,6 +852,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-test-tools.lock.yml b/.github/workflows/smoke-test-tools.lock.yml
index 3d30cf9f481..0aac71a928e 100644
--- a/.github/workflows/smoke-test-tools.lock.yml
+++ b/.github/workflows/smoke-test-tools.lock.yml
@@ -306,6 +306,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -816,6 +818,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-update-cross-repo-pr.lock.yml b/.github/workflows/smoke-update-cross-repo-pr.lock.yml
index f6febbd724d..7b1eb158253 100644
--- a/.github/workflows/smoke-update-cross-repo-pr.lock.yml
+++ b/.github/workflows/smoke-update-cross-repo-pr.lock.yml
@@ -317,6 +317,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -897,6 +899,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-workflow-call-with-inputs.lock.yml b/.github/workflows/smoke-workflow-call-with-inputs.lock.yml
index 819f259ae2e..69d920779c0 100644
--- a/.github/workflows/smoke-workflow-call-with-inputs.lock.yml
+++ b/.github/workflows/smoke-workflow-call-with-inputs.lock.yml
@@ -310,6 +310,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -827,6 +829,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/smoke-workflow-call.lock.yml b/.github/workflows/smoke-workflow-call.lock.yml
index 7360b23d230..f5a13db2c2f 100644
--- a/.github/workflows/smoke-workflow-call.lock.yml
+++ b/.github/workflows/smoke-workflow-call.lock.yml
@@ -310,6 +310,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -815,6 +817,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml
index 651513b8f5d..6d0349e42d4 100644
--- a/.github/workflows/stale-repo-identifier.lock.yml
+++ b/.github/workflows/stale-repo-identifier.lock.yml
@@ -294,6 +294,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -926,6 +928,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/static-analysis-report.lock.yml b/.github/workflows/static-analysis-report.lock.yml
index d81ef872c9b..09259b93dea 100644
--- a/.github/workflows/static-analysis-report.lock.yml
+++ b/.github/workflows/static-analysis-report.lock.yml
@@ -275,6 +275,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -948,6 +950,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/step-name-alignment.lock.yml b/.github/workflows/step-name-alignment.lock.yml
index 36af667a85c..d359ef68811 100644
--- a/.github/workflows/step-name-alignment.lock.yml
+++ b/.github/workflows/step-name-alignment.lock.yml
@@ -265,6 +265,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -870,6 +872,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/sub-issue-closer.lock.yml b/.github/workflows/sub-issue-closer.lock.yml
index 3bc7c08a046..5eec9ce44bc 100644
--- a/.github/workflows/sub-issue-closer.lock.yml
+++ b/.github/workflows/sub-issue-closer.lock.yml
@@ -256,6 +256,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -797,6 +799,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml
index 335bf00e268..47b703cfec8 100644
--- a/.github/workflows/super-linter.lock.yml
+++ b/.github/workflows/super-linter.lock.yml
@@ -277,6 +277,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -814,6 +816,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml
index b780377b976..a53253c44db 100644
--- a/.github/workflows/technical-doc-writer.lock.yml
+++ b/.github/workflows/technical-doc-writer.lock.yml
@@ -315,6 +315,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -992,6 +994,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/terminal-stylist.lock.yml b/.github/workflows/terminal-stylist.lock.yml
index 5de784b85b8..e5b0e96bd0e 100644
--- a/.github/workflows/terminal-stylist.lock.yml
+++ b/.github/workflows/terminal-stylist.lock.yml
@@ -297,6 +297,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -819,6 +821,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/test-create-pr-error-handling.lock.yml b/.github/workflows/test-create-pr-error-handling.lock.yml
index 0bb7e6dd678..56adc13c1b3 100644
--- a/.github/workflows/test-create-pr-error-handling.lock.yml
+++ b/.github/workflows/test-create-pr-error-handling.lock.yml
@@ -266,6 +266,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -855,6 +857,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/test-dispatcher.lock.yml b/.github/workflows/test-dispatcher.lock.yml
index a1623c42826..9c9ad077088 100644
--- a/.github/workflows/test-dispatcher.lock.yml
+++ b/.github/workflows/test-dispatcher.lock.yml
@@ -251,6 +251,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -739,6 +741,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/test-project-url-default.lock.yml b/.github/workflows/test-project-url-default.lock.yml
index adfda915270..4bbaed52be2 100644
--- a/.github/workflows/test-project-url-default.lock.yml
+++ b/.github/workflows/test-project-url-default.lock.yml
@@ -252,6 +252,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -800,6 +802,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/test-workflow.lock.yml b/.github/workflows/test-workflow.lock.yml
index 6a3f48471c3..9d210adceb1 100644
--- a/.github/workflows/test-workflow.lock.yml
+++ b/.github/workflows/test-workflow.lock.yml
@@ -250,6 +250,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -534,6 +536,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
           if-no-files-found: ignore
       - name: Upload firewall audit logs
         if: always()
diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml
index 6593ea26d5c..9425c6fdb49 100644
--- a/.github/workflows/tidy.lock.yml
+++ b/.github/workflows/tidy.lock.yml
@@ -332,6 +332,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -895,6 +897,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/typist.lock.yml b/.github/workflows/typist.lock.yml
index 03e55117a68..7c732274505 100644
--- a/.github/workflows/typist.lock.yml
+++ b/.github/workflows/typist.lock.yml
@@ -298,6 +298,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -894,6 +896,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/ubuntu-image-analyzer.lock.yml b/.github/workflows/ubuntu-image-analyzer.lock.yml
index 97a53203f34..031e7e1f4c7 100644
--- a/.github/workflows/ubuntu-image-analyzer.lock.yml
+++ b/.github/workflows/ubuntu-image-analyzer.lock.yml
@@ -271,6 +271,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -803,6 +805,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml
index 6d075d7f1b8..849de9ab5fd 100644
--- a/.github/workflows/unbloat-docs.lock.yml
+++ b/.github/workflows/unbloat-docs.lock.yml
@@ -354,6 +354,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -1148,6 +1150,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/update-astro.lock.yml b/.github/workflows/update-astro.lock.yml
index 78eb4488e01..a484afc6421 100644
--- a/.github/workflows/update-astro.lock.yml
+++ b/.github/workflows/update-astro.lock.yml
@@ -278,6 +278,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -785,6 +787,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/video-analyzer.lock.yml b/.github/workflows/video-analyzer.lock.yml
index 73ada53d937..5b85d95c4b1 100644
--- a/.github/workflows/video-analyzer.lock.yml
+++ b/.github/workflows/video-analyzer.lock.yml
@@ -267,6 +267,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -792,6 +794,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/weekly-blog-post-writer.lock.yml b/.github/workflows/weekly-blog-post-writer.lock.yml
index 3694d959339..da28f42b4ee 100644
--- a/.github/workflows/weekly-blog-post-writer.lock.yml
+++ b/.github/workflows/weekly-blog-post-writer.lock.yml
@@ -309,6 +309,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -967,6 +969,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/weekly-editors-health-check.lock.yml b/.github/workflows/weekly-editors-health-check.lock.yml
index b125b68e6c7..b732caa6f6e 100644
--- a/.github/workflows/weekly-editors-health-check.lock.yml
+++ b/.github/workflows/weekly-editors-health-check.lock.yml
@@ -264,6 +264,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -834,6 +836,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/weekly-issue-summary.lock.yml b/.github/workflows/weekly-issue-summary.lock.yml
index ddb565be0da..f511379dabe 100644
--- a/.github/workflows/weekly-issue-summary.lock.yml
+++ b/.github/workflows/weekly-issue-summary.lock.yml
@@ -280,6 +280,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -838,6 +840,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/weekly-safe-outputs-spec-review.lock.yml b/.github/workflows/weekly-safe-outputs-spec-review.lock.yml
index 8defca7f9a2..f4c5655d6ed 100644
--- a/.github/workflows/weekly-safe-outputs-spec-review.lock.yml
+++ b/.github/workflows/weekly-safe-outputs-spec-review.lock.yml
@@ -264,6 +264,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -769,6 +771,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/workflow-generator.lock.yml b/.github/workflows/workflow-generator.lock.yml
index 1e591f424dd..8466134990b 100644
--- a/.github/workflows/workflow-generator.lock.yml
+++ b/.github/workflows/workflow-generator.lock.yml
@@ -299,6 +299,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -847,6 +849,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/workflow-health-manager.lock.yml b/.github/workflows/workflow-health-manager.lock.yml
index f257a9f2f3b..8083b4f4de0 100644
--- a/.github/workflows/workflow-health-manager.lock.yml
+++ b/.github/workflows/workflow-health-manager.lock.yml
@@ -279,6 +279,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -875,6 +877,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/workflow-normalizer.lock.yml b/.github/workflows/workflow-normalizer.lock.yml
index ddb40fd8f3c..50146fb9e60 100644
--- a/.github/workflows/workflow-normalizer.lock.yml
+++ b/.github/workflows/workflow-normalizer.lock.yml
@@ -265,6 +265,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -842,6 +844,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/.github/workflows/workflow-skill-extractor.lock.yml b/.github/workflows/workflow-skill-extractor.lock.yml
index 1f2984b4877..f03e9c85b4d 100644
--- a/.github/workflows/workflow-skill-extractor.lock.yml
+++ b/.github/workflows/workflow-skill-extractor.lock.yml
@@ -260,6 +260,8 @@ jobs:
           path: |
             /tmp/gh-aw/aw_info.json
             /tmp/gh-aw/aw-prompts/prompt.txt
+            /tmp/gh-aw/github_rate_limits.jsonl
+          if-no-files-found: ignore
           retention-days: 1
 
   agent:
@@ -810,6 +812,7 @@ jobs:
             /tmp/gh-aw/agent_usage.json
             /tmp/gh-aw/agent-stdio.log
             /tmp/gh-aw/agent/
+            /tmp/gh-aw/github_rate_limits.jsonl
             /tmp/gh-aw/safeoutputs.jsonl
             /tmp/gh-aw/agent_output.json
             /tmp/gh-aw/aw-*.patch
diff --git a/actions/setup/js/check_rate_limit.cjs b/actions/setup/js/check_rate_limit.cjs
index 6c0a7883137..1ed2bea9cf1 100644
--- a/actions/setup/js/check_rate_limit.cjs
+++ b/actions/setup/js/check_rate_limit.cjs
@@ -2,7 +2,7 @@
 /// <reference types="@actions/github-script" />
 
 const { getErrorMessage } = require("./error_helpers.cjs");
-const { logRateLimitFromResponse, fetchAndLogRateLimit } = require("./github_rate_limit_logger.cjs");
+const { fetchAndLogRateLimit } = require("./github_rate_limit_logger.cjs");
 
 /**
  * Rate limit check for per-user per-workflow triggers
@@ -59,7 +59,6 @@ async function main() {
       repo,
       username: actor,
     });
-    logRateLimitFromResponse(permResponse, "repos.getCollaboratorPermissionLevel");
 
     const { data: permissionData } = permResponse;
     const userPermission = permissionData.permission;
@@ -136,7 +135,6 @@ async function main() {
         per_page: perPage,
         page,
       });
-      logRateLimitFromResponse(response, "actions.listWorkflowRuns");
 
       const runs = response.data.workflow_runs;
       core.info(`   Retrieved ${runs.length} runs from page ${page}`);
diff --git a/actions/setup/js/github_api_helpers.cjs b/actions/setup/js/github_api_helpers.cjs
index d606815ef84..0383b01081a 100644
--- a/actions/setup/js/github_api_helpers.cjs
+++ b/actions/setup/js/github_api_helpers.cjs
@@ -7,7 +7,6 @@
  */
 
 const { getErrorMessage } = require("./error_helpers.cjs");
-const { logRateLimitFromResponse } = require("./github_rate_limit_logger.cjs");
 
 /**
  * @typedef {Object} GraphQLErrorHints
@@ -76,8 +75,6 @@ async function getFileContent(github, owner, repo, path, ref) {
       ref,
     });
 
-    logRateLimitFromResponse(response, "repos.getContent");
-
     // Handle case where response is an array (directory listing)
     if (Array.isArray(response.data)) {
       core.info(`Path ${path} is a directory, not a file`);
diff --git a/actions/setup/js/setup_globals.cjs b/actions/setup/js/setup_globals.cjs
index ea67e28e2d9..bacfcb1aec1 100644
--- a/actions/setup/js/setup_globals.cjs
+++ b/actions/setup/js/setup_globals.cjs
@@ -7,10 +7,16 @@
  * This allows required modules to access these objects without needing to pass them as parameters
  */
 
+const { createRateLimitAwareGithub } = require("./github_rate_limit_logger.cjs");
+
 /**
  * Stores GitHub Actions builtin objects (core, github, context, exec, io) in the global scope
  * This must be called before requiring any script that depends on these globals
  *
+ * The github object is wrapped with a rate-limit-aware proxy so that every
+ * github.rest.*.*() call automatically logs rate-limit headers to
+ * /tmp/gh-aw/github_rate_limits.jsonl for post-run observability.
+ *
  * @param {typeof core} coreModule - The @actions/core module
  * @param {typeof github} githubModule - The @actions/github module
  * @param {typeof context} contextModule - The GitHub context object
@@ -21,7 +27,9 @@ function setupGlobals(coreModule, githubModule, contextModule, execModule, ioMod
   // @ts-expect-error - Assigning to global properties that are declared as const
   global.core = coreModule;
   // @ts-expect-error - Assigning to global properties that are declared as const
-  global.github = githubModule;
+  // Wrap the github object so every github.rest.*.*() call automatically logs
+  // x-ratelimit-* headers to github_rate_limits.jsonl for observability.
+  global.github = createRateLimitAwareGithub(githubModule);
   // @ts-expect-error - Assigning to global properties that are declared as const
   global.context = contextModule;
   // @ts-expect-error - Assigning to global properties that are declared as const

From 7e0a53f5f4d73b2b03e44d81c7e1913939f1761f Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sun, 5 Apr 2026 09:29:46 +0000
Subject: [PATCH 4/5] Add changeset

---
 .changeset/patch-github-rate-limit-observability.md | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 .changeset/patch-github-rate-limit-observability.md

diff --git a/.changeset/patch-github-rate-limit-observability.md b/.changeset/patch-github-rate-limit-observability.md
new file mode 100644
index 00000000000..ef1e60ba515
--- /dev/null
+++ b/.changeset/patch-github-rate-limit-observability.md
@@ -0,0 +1,5 @@
+---
+"gh-aw": patch
+---
+
+Add GitHub API rate limit observability by logging rate-limit data to `github_rate_limits.jsonl` during workflow execution and uploading it in activation and agent artifacts.

From bb7b5d73200bde7d28d0d2be42cd1763664cef2f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 5 Apr 2026 09:29:55 +0000
Subject: [PATCH 5/5] Enrich conclusion OTLP span with last GitHub rate-limit
 entry

Read the last entry from github_rate_limits.jsonl in sendJobConclusionSpan
and include gh-aw.github.rate_limit.{remaining,limit,used,resource} as span
attributes so rate-limit headroom is visible in the OTLP trace.

Also add readLastRateLimitEntry helper + 10 new tests (101 total pass).

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/cd4d7dff-3509-4d45-bd42-1c49839e6e49

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 actions/setup/js/send_otlp_span.cjs      |  59 +++++++
 actions/setup/js/send_otlp_span.test.cjs | 189 ++++++++++++++++++++++-
 2 files changed, 246 insertions(+), 2 deletions(-)

diff --git a/actions/setup/js/send_otlp_span.cjs b/actions/setup/js/send_otlp_span.cjs
index c6016a02c00..d13a8d71bb8 100644
--- a/actions/setup/js/send_otlp_span.cjs
+++ b/actions/setup/js/send_otlp_span.cjs
@@ -424,6 +424,43 @@ function readJSONIfExists(filePath) {
   }
 }
 
+/**
+ * Path to the GitHub rate-limit JSONL log file.
+ * Mirrors GITHUB_RATE_LIMITS_JSONL_PATH from constants.cjs without introducing
+ * a runtime require() dependency on that module.
+ * @type {string}
+ */
+const GITHUB_RATE_LIMITS_JSONL_PATH = "/tmp/gh-aw/github_rate_limits.jsonl";
+
+/**
+ * @typedef {Object} RateLimitEntry
+ * @property {string} [resource]   - GitHub rate-limit resource category (e.g. "core", "graphql")
+ * @property {number} [limit]      - Total request quota for the window
+ * @property {number} [remaining]  - Requests remaining in the current window
+ * @property {number} [used]       - Requests consumed in the current window
+ * @property {string} [reset]      - ISO 8601 timestamp when the window resets
+ * @property {string} [operation]  - API operation that produced this entry
+ */
+
+/**
+ * Read the last entry from the GitHub rate-limit JSONL log file.
+ * Returns the parsed entry or `null` when the file is absent, empty, or
+ * contains no valid JSON lines.  Errors are silently swallowed — this is
+ * an observability enrichment and must never break the workflow.
+ *
+ * @returns {RateLimitEntry | null}
+ */
+function readLastRateLimitEntry() {
+  try {
+    const content = fs.readFileSync(GITHUB_RATE_LIMITS_JSONL_PATH, "utf8");
+    const lines = content.split("\n").filter(l => l.trim() !== "");
+    if (lines.length === 0) return null;
+    return JSON.parse(lines[lines.length - 1]);
+  } catch {
+    return null;
+  }
+}
+
 // ---------------------------------------------------------------------------
 // High-level: job conclusion span
 // ---------------------------------------------------------------------------
@@ -546,6 +583,26 @@ async function sendJobConclusionSpan(spanName, options = {}) {
     attributes.push(buildAttr("gh-aw.error.messages", errorMessages.join(" | ")));
   }
 
+  // Enrich span with the most recent GitHub API rate-limit snapshot for post-run
+  // observability.  Reads the last entry from github_rate_limits.jsonl so that
+  // rate-limit headroom at conclusion time is visible in the OTLP span without
+  // requiring a live collector to parse the artifact separately.
+  const lastRateLimit = readLastRateLimitEntry();
+  if (lastRateLimit) {
+    if (typeof lastRateLimit.remaining === "number") {
+      attributes.push(buildAttr("gh-aw.github.rate_limit.remaining", lastRateLimit.remaining));
+    }
+    if (typeof lastRateLimit.limit === "number") {
+      attributes.push(buildAttr("gh-aw.github.rate_limit.limit", lastRateLimit.limit));
+    }
+    if (typeof lastRateLimit.used === "number") {
+      attributes.push(buildAttr("gh-aw.github.rate_limit.used", lastRateLimit.used));
+    }
+    if (lastRateLimit.resource) {
+      attributes.push(buildAttr("gh-aw.github.rate_limit.resource", String(lastRateLimit.resource)));
+    }
+  }
+
   const resourceAttributes = [buildAttr("github.repository", repository), buildAttr("github.run_id", runId)];
   if (eventName) {
     resourceAttributes.push(buildAttr("github.event_name", eventName));
@@ -580,6 +637,8 @@ module.exports = {
   parseOTLPHeaders,
   sendOTLPSpan,
   readJSONIfExists,
+  readLastRateLimitEntry,
+  GITHUB_RATE_LIMITS_JSONL_PATH,
   sendJobSetupSpan,
   sendJobConclusionSpan,
   OTEL_JSONL_PATH,
diff --git a/actions/setup/js/send_otlp_span.test.cjs b/actions/setup/js/send_otlp_span.test.cjs
index 528ed0e25f6..210b32be404 100644
--- a/actions/setup/js/send_otlp_span.test.cjs
+++ b/actions/setup/js/send_otlp_span.test.cjs
@@ -5,8 +5,23 @@ import fs from "fs";
 // Module import
 // ---------------------------------------------------------------------------
 
-const { isValidTraceId, isValidSpanId, generateTraceId, generateSpanId, toNanoString, buildAttr, buildOTLPPayload, parseOTLPHeaders, sendOTLPSpan, sendJobSetupSpan, sendJobConclusionSpan, OTEL_JSONL_PATH, appendToOTLPJSONL } =
-  await import("./send_otlp_span.cjs");
+const {
+  isValidTraceId,
+  isValidSpanId,
+  generateTraceId,
+  generateSpanId,
+  toNanoString,
+  buildAttr,
+  buildOTLPPayload,
+  parseOTLPHeaders,
+  sendOTLPSpan,
+  sendJobSetupSpan,
+  sendJobConclusionSpan,
+  readLastRateLimitEntry,
+  GITHUB_RATE_LIMITS_JSONL_PATH,
+  OTEL_JSONL_PATH,
+  appendToOTLPJSONL,
+} = await import("./send_otlp_span.cjs");
 
 // ---------------------------------------------------------------------------
 // isValidTraceId
@@ -364,6 +379,73 @@ describe("sendOTLPSpan", () => {
   });
 });
 
+// ---------------------------------------------------------------------------
+// readLastRateLimitEntry
+// ---------------------------------------------------------------------------
+
+describe("readLastRateLimitEntry", () => {
+  let readFileSpy;
+
+  beforeEach(() => {
+    readFileSpy = vi.spyOn(fs, "readFileSync").mockImplementation(() => {
+      throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+    });
+  });
+
+  afterEach(() => {
+    readFileSpy.mockRestore();
+  });
+
+  it("returns null when the file does not exist", () => {
+    expect(readLastRateLimitEntry()).toBeNull();
+  });
+
+  it("returns null when the file is empty", () => {
+    readFileSpy.mockImplementation(filePath => {
+      if (filePath === GITHUB_RATE_LIMITS_JSONL_PATH) return "";
+      throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+    });
+    expect(readLastRateLimitEntry()).toBeNull();
+  });
+
+  it("returns null when the file contains only blank lines", () => {
+    readFileSpy.mockImplementation(filePath => {
+      if (filePath === GITHUB_RATE_LIMITS_JSONL_PATH) return "\n\n  \n";
+      throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+    });
+    expect(readLastRateLimitEntry()).toBeNull();
+  });
+
+  it("returns the parsed entry for a single-line file", () => {
+    const entry = { resource: "core", limit: 5000, remaining: 4823, used: 177 };
+    readFileSpy.mockImplementation(filePath => {
+      if (filePath === GITHUB_RATE_LIMITS_JSONL_PATH) return JSON.stringify(entry) + "\n";
+      throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+    });
+    expect(readLastRateLimitEntry()).toEqual(entry);
+  });
+
+  it("returns the last entry for a multi-line file", () => {
+    const first = { resource: "core", remaining: 4900 };
+    const last = { resource: "core", remaining: 4500 };
+    readFileSpy.mockImplementation(filePath => {
+      if (filePath === GITHUB_RATE_LIMITS_JSONL_PATH) {
+        return JSON.stringify(first) + "\n" + JSON.stringify(last) + "\n";
+      }
+      throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+    });
+    expect(readLastRateLimitEntry()).toEqual(last);
+  });
+
+  it("returns null when the last line is invalid JSON", () => {
+    readFileSpy.mockImplementation(filePath => {
+      if (filePath === GITHUB_RATE_LIMITS_JSONL_PATH) return "not valid json\n";
+      throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+    });
+    expect(readLastRateLimitEntry()).toBeNull();
+  });
+});
+
 // ---------------------------------------------------------------------------
 // appendToOTLPJSONL
 // ---------------------------------------------------------------------------
@@ -1292,4 +1374,107 @@ describe("sendJobConclusionSpan", () => {
       expect(span.status.message).toBe("agent failure");
     });
   });
+
+  describe("rate-limit enrichment in conclusion span", () => {
+    let readFileSpy;
+
+    beforeEach(() => {
+      readFileSpy = vi.spyOn(fs, "readFileSync").mockImplementation(() => {
+        throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+      });
+    });
+
+    afterEach(() => {
+      readFileSpy.mockRestore();
+    });
+
+    it("includes rate-limit attributes when github_rate_limits.jsonl has entries", async () => {
+      const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
+      vi.stubGlobal("fetch", mockFetch);
+
+      process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "https://traces.example.com";
+
+      const entry = { timestamp: "2026-04-05T09:00:00.000Z", source: "response_headers", operation: "issues.get", resource: "core", limit: 5000, remaining: 4823, used: 177, reset: "2026-04-05T09:30:00.000Z" };
+      readFileSpy.mockImplementation(filePath => {
+        if (filePath === GITHUB_RATE_LIMITS_JSONL_PATH) {
+          return JSON.stringify(entry) + "\n";
+        }
+        throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+      });
+
+      await sendJobConclusionSpan("gh-aw.job.conclusion");
+
+      const body = JSON.parse(mockFetch.mock.calls[0][1].body);
+      const span = body.resourceSpans[0].scopeSpans[0].spans[0];
+      const attrs = Object.fromEntries(span.attributes.map(a => [a.key, a.value.intValue ?? a.value.stringValue]));
+      expect(attrs["gh-aw.github.rate_limit.remaining"]).toBe(4823);
+      expect(attrs["gh-aw.github.rate_limit.limit"]).toBe(5000);
+      expect(attrs["gh-aw.github.rate_limit.used"]).toBe(177);
+      expect(attrs["gh-aw.github.rate_limit.resource"]).toBe("core");
+    });
+
+    it("uses the last entry when the file contains multiple lines", async () => {
+      const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
+      vi.stubGlobal("fetch", mockFetch);
+
+      process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "https://traces.example.com";
+
+      const first = { resource: "core", limit: 5000, remaining: 4900, used: 100 };
+      const last = { resource: "core", limit: 5000, remaining: 4500, used: 500 };
+      readFileSpy.mockImplementation(filePath => {
+        if (filePath === GITHUB_RATE_LIMITS_JSONL_PATH) {
+          return JSON.stringify(first) + "\n" + JSON.stringify(last) + "\n";
+        }
+        throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+      });
+
+      await sendJobConclusionSpan("gh-aw.job.conclusion");
+
+      const body = JSON.parse(mockFetch.mock.calls[0][1].body);
+      const span = body.resourceSpans[0].scopeSpans[0].spans[0];
+      const attrs = Object.fromEntries(span.attributes.map(a => [a.key, a.value.intValue ?? a.value.stringValue]));
+      expect(attrs["gh-aw.github.rate_limit.remaining"]).toBe(4500);
+      expect(attrs["gh-aw.github.rate_limit.used"]).toBe(500);
+    });
+
+    it("omits rate-limit attributes when github_rate_limits.jsonl is absent", async () => {
+      const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
+      vi.stubGlobal("fetch", mockFetch);
+
+      process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "https://traces.example.com";
+
+      // readFileSpy already throws ENOENT for all paths
+
+      await sendJobConclusionSpan("gh-aw.job.conclusion");
+
+      const body = JSON.parse(mockFetch.mock.calls[0][1].body);
+      const span = body.resourceSpans[0].scopeSpans[0].spans[0];
+      const keys = span.attributes.map(a => a.key);
+      expect(keys).not.toContain("gh-aw.github.rate_limit.remaining");
+      expect(keys).not.toContain("gh-aw.github.rate_limit.limit");
+      expect(keys).not.toContain("gh-aw.github.rate_limit.used");
+      expect(keys).not.toContain("gh-aw.github.rate_limit.resource");
+    });
+
+    it("omits rate-limit attributes when the file contains only invalid JSON", async () => {
+      const mockFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, statusText: "OK" });
+      vi.stubGlobal("fetch", mockFetch);
+
+      process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "https://traces.example.com";
+
+      readFileSpy.mockImplementation(filePath => {
+        if (filePath === GITHUB_RATE_LIMITS_JSONL_PATH) {
+          return "not valid json\n";
+        }
+        throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
+      });
+
+      await sendJobConclusionSpan("gh-aw.job.conclusion");
+
+      const body = JSON.parse(mockFetch.mock.calls[0][1].body);
+      const span = body.resourceSpans[0].scopeSpans[0].spans[0];
+      const keys = span.attributes.map(a => a.key);
+      expect(keys).not.toContain("gh-aw.github.rate_limit.remaining");
+    });
+  });
 });
