Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions scratchpad/dev.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Developer Instructions

**Version**: 5.2
**Last Updated**: 2026-04-04
**Version**: 5.3
**Last Updated**: 2026-04-05
**Purpose**: Consolidated development guidelines for GitHub Agentic Workflows

This document consolidates specifications from the scratchpad directory into unified developer instructions. It provides architecture patterns, security guidelines, code organization rules, and testing practices.
Expand Down Expand Up @@ -2144,6 +2144,37 @@ func GetMCPLogLevel() string {
}
```

### GitHub API Rate Limit Observability

GitHub API rate-limit data is logged to a JSONL file during workflow execution, uploaded as a job artifact, and surfaced in OTLP conclusion spans.

**Log file**: `/tmp/gh-aw/github_rate_limits.jsonl` (constant: `GithubRateLimitsFilename`)

**Entry format**:
```json
{"timestamp":"2026-04-05T08:30:00.000Z","source":"response_headers","operation":"issues.listComments","resource":"core","limit":5000,"remaining":4823,"used":177,"reset":"2026-04-05T09:00:00.000Z"}
```

**JS helper** (`actions/setup/js/github_rate_limit_logger.cjs`) — three usage patterns:

| Pattern | Function | When to Use |
|---------|----------|-------------|
| Per-call | `logRateLimitFromResponse(response, op)` | After individual REST calls |
| Snapshot | `fetchAndLogRateLimit(github, op)` | Job start/end |
| Auto-wrap | `createRateLimitAwareGithub(github)` | Zero call-site change |

`setupGlobals` wraps the injected `github` object with `createRateLimitAwareGithub` automatically, so all scripts using `global.github` get rate-limit logging without per-file changes.

**Artifact upload**: included in both activation and agent job artifacts (`if-no-files-found: ignore`, 1-day retention). See `compiler_activation_job.go` and `compiler_yaml_main_job.go`.

**OTLP span attributes** (added to conclusion span by `send_otlp_span.cjs`):
- `gh-aw.github.rate_limit.remaining`
- `gh-aw.github.rate_limit.limit`
- `gh-aw.github.rate_limit.used`
- `gh-aw.github.rate_limit.resource`

See `scratchpad/github-rate-limit-observability.md` for full details including debugging with `jq`.

---

## Go Type Patterns
Expand Down Expand Up @@ -2704,6 +2735,7 @@ These files are loaded automatically by compatible AI tools (e.g., GitHub Copilo
- [Agent Sessions Terminology Migration](./agent-sessions.md) - Migration plan for renaming "agent task" to "agent session": schema updates, codemod in `fix_codemods.go`, Go/JavaScript code changes, documentation updates, and backward compatibility strategy
- [Safe Output Handler Factory Pattern](./safe-output-handlers-refactoring.md) - Refactoring status for all 11 safe output handlers to the handler factory pattern (`main(config)` returns a message handler function): per-handler status, testing strategy, and handler manager compatibility
- [Serena Tools Statistical Analysis](./serena-tools-analysis.md) - Deep statistical analysis of Serena MCP tool usage in workflow run 21560089409: tool adoption rates (26% of registered tools used), call distributions, and unused tool identification
- [GitHub API Rate Limit Observability](./github-rate-limit-observability.md) - JSONL artifact logging and OTLP span enrichment for GitHub API rate-limit visibility: `github_rate_limit_logger.cjs` helper, three usage patterns, artifact upload paths, and `jq` debugging commands

### External References

Expand All @@ -2715,6 +2747,7 @@ These files are loaded automatically by compatible AI tools (e.g., GitHub Copilo
---

**Document History**:
- v5.3 (2026-04-05): Added GitHub API Rate Limit Observability subsection to MCP Integration (from PR #24694: `github_rate_limit_logger.cjs`, `GithubRateLimitsFilename` constant, artifact upload paths, OTLP span enrichment). Created new spec file `scratchpad/github-rate-limit-observability.md`. Added 1 new Related Documentation link. Coverage: 73 spec files (1 new).
- v5.2 (2026-04-04): Added Secrets in Custom Steps Validation subsection to Compiler Validation (from PR #24450: `pkg/workflow/strict_mode_steps_validation.go`). Documents `validateStepsSecrets()` behavior in strict vs. non-strict mode, `secrets.GITHUB_TOKEN` exemption, and migration guidance. Coverage: 72 spec files (no new spec files; new Go implementation only).
- v5.1 (2026-04-03): Maintenance tone scan — 0 tone issues found across 3 previously uncovered spec files. Added 3 new Related Documentation links: `agent-sessions.md` (terminology migration plan), `safe-output-handlers-refactoring.md` (handler factory pattern status), `serena-tools-analysis.md` (Serena tool usage statistics). Coverage: 72 spec files (3 new).
- v5.0 (2026-04-02): Maintenance tone scan — fixed 3 tone issues across 2 previously uncovered spec files: `capitalization.md` (2 fixes: "maintains professional consistency"→removed, "simplifies both user comprehension"→"reduces ambiguity for contributors"), `mdflow.md` ("significantly exceeds"→"supports capabilities not currently available in"). Added 7 new Related Documentation links for 7 previously uncovered spec files (capitalization.md, labels.md, gastown.md, mdflow.md, mdflow-comparison.md, oh-my-code.md). Coverage: 69 spec files (7 new).
Expand Down
119 changes: 119 additions & 0 deletions scratchpad/github-rate-limit-observability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# GitHub API Rate Limit Observability

> Added in PR #24694 (2026-04-05)

## Overview

GitHub API rate limits are a failure mode in high-volume workflows with no post-run visibility.
This feature logs rate-limit data to a JSONL artifact during workflow execution and enriches OTLP
conclusion spans with rate-limit attributes.

## Log File

Each job writes rate-limit entries to `/tmp/gh-aw/github_rate_limits.jsonl`.

**Entry format** (one JSON object per line):

```json
{
"timestamp": "2026-04-05T08:30:00.000Z",
"source": "response_headers",
"operation": "issues.listComments",
"resource": "core",
"limit": 5000,
"remaining": 4823,
"used": 177,
"reset": "2026-04-05T09:00:00.000Z"
}
```

**`source` values**:
- `"response_headers"` — extracted from `x-ratelimit-*` response headers after a REST call
- `"rate_limit_api"` — fetched via the GitHub rate-limit API (multi-resource snapshot)

**Constant**: `constants.GithubRateLimitsFilename = "github_rate_limits.jsonl"` (Go); `GITHUB_RATE_LIMITS_JSONL_PATH` (JS).

## JS Helper: `github_rate_limit_logger.cjs`

Located at `actions/setup/js/github_rate_limit_logger.cjs`. Provides three usage patterns:

### 1. Per-call logging (from response headers)

```js
logRateLimitFromResponse(response, "issues.listComments");
```

Reads `x-ratelimit-*` headers from the REST response. No additional API call. Skips silently when headers are absent (e.g., GraphQL responses).

### 2. On-demand snapshot (rate-limit API)

```js
await fetchAndLogRateLimit(github, "startup");
```

Calls `github.rest.rateLimit.get()` and writes one entry per resource category (core, search, graphql, etc.). Use at job start/end for a comprehensive view.

### 3. Automatic wrapping (zero call-site changes)

```js
const gh = createRateLimitAwareGithub(github);
await gh.rest.issues.get({ owner, repo, issue_number: 1 });
// Every gh.rest.*.*() call now auto-logs rate-limit headers
```

Creates a `Proxy` around the GitHub REST client. Every `github.rest.*.*()` invocation
automatically logs rate-limit headers from the response without modifying call sites.

## Integration via `setup_globals.cjs`

`setupGlobals` wraps the injected `github` object with `createRateLimitAwareGithub` automatically.
All scripts that use `global.github` get rate-limit logging for `github.rest.*.*()` calls without
per-file changes.

`check_rate_limit.cjs` retains a `fetchAndLogRateLimit` call at startup for a full multi-resource
snapshot via the rate-limit API.

## Artifact Upload

`github_rate_limits.jsonl` is included in artifact uploads for both activation and agent jobs.

Relevant compiler files:
- `pkg/workflow/compiler_activation_job.go`
- `pkg/workflow/compiler_yaml_main_job.go`

The upload step uses `if-no-files-found: ignore`, so it is a no-op when no API calls were made.
The artifact has a 1-day retention period.

## OTLP Span Enrichment

`sendJobConclusionSpan` in `send_otlp_span.cjs` reads the **last entry** from
`github_rate_limits.jsonl` and includes rate-limit attributes in the OTLP conclusion span:

| Attribute | Description |
|-----------|-------------|
| `gh-aw.github.rate_limit.remaining` | Remaining API calls at job end |
| `gh-aw.github.rate_limit.limit` | Total API call quota |
| `gh-aw.github.rate_limit.used` | API calls consumed |
| `gh-aw.github.rate_limit.resource` | Resource category (e.g. `core`) |

This makes rate-limit headroom at job conclusion time visible in any connected OTLP collector
or tracing UI without requiring artifact inspection.

## Debugging Rate Limit Issues

To inspect rate limit consumption after a workflow run:

1. Download the job artifact.
2. Open `github_rate_limits.jsonl`.
3. Parse entries with `jq`:

```bash
# Show all entries sorted by timestamp
jq -s 'sort_by(.timestamp)' github_rate_limits.jsonl

# Show only low-remaining entries (< 500 calls left)
jq 'select(.remaining < 500)' github_rate_limits.jsonl

# Show final snapshot
jq -s 'last' github_rate_limits.jsonl
```