feat: add copilot CLI steering hooks for time and run budgets#30500
feat: add copilot CLI steering hooks for time and run budgets#30500
Conversation
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d69918d3-92bc-47f8-be39-1a214fbbf7cd Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d69918d3-92bc-47f8-be39-1a214fbbf7cd Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d69918d3-92bc-47f8-be39-1a214fbbf7cd Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d69918d3-92bc-47f8-be39-1a214fbbf7cd Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d69918d3-92bc-47f8-be39-1a214fbbf7cd Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d69918d3-92bc-47f8-be39-1a214fbbf7cd Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d69918d3-92bc-47f8-be39-1a214fbbf7cd Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds Copilot CLI “steering” hook support to the Copilot harness to warn/block when the session is nearing time or run-budget exhaustion.
Changes:
- Install a runtime Copilot hook config (
.github/hooks/gh-aw-steering.json) before launching the Copilot CLI and export env vars used by the hook. - Add a new
copilot_steering_hook.cjscommand hook that persists per-session state and emits warning/critical “block” steering decisions based on remaining time/runs. - Clean up the per-run steering state file after harness completion and extend Vitest coverage for autopilot parsing and hook config generation.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/copilot_steering_hook.cjs | New hook script that tracks session state and emits steering decisions on low time/run budgets. |
| actions/setup/js/copilot_steering_hook.test.cjs | Unit tests for config loading, state initialization, and warning/critical decision behavior. |
| actions/setup/js/copilot_harness.cjs | Installs hook config + per-run state path/env vars; parses max autopilot continues; cleans up steering state file. |
| actions/setup/js/copilot_harness.test.cjs | Tests for autopilot/run-budget helpers and hook config command quoting. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 4/4 changed files
- Comments generated: 2
| function saveState(statePath, state) { | ||
| fs.writeFileSync(statePath, JSON.stringify(state), "utf8"); | ||
| } |
| function loadState(statePath) { | ||
| try { | ||
| if (!fs.existsSync(statePath)) { | ||
| return null; | ||
| } | ||
| const raw = fs.readFileSync(statePath, "utf8"); | ||
| return /** @type {SteeringState} */ JSON.parse(raw); | ||
| } catch { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
Ugh, me agree! loadState trust too much. Me caveman but me know: always validate data before use. Good catch!
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · ● 18.2M
|
@copilot review all comments |
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/10b67751-6800-491f-97fd-2b102bbee5ca Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed all actionable review threads in commit
Validation passed with targeted JS tests and Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
|
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 |
|
🚀 Smoke Pi MISSION COMPLETE! Pi delivered. 🥧 |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal! This PR adds Copilot CLI steering hook support with solid test coverage. The new copilot_steering_hook.cjs is well-structured. Run 25417832826 ✅
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
💥 [THE END] — Illustrated by Smoke Claude · ● 303K
| const PROMPT_FILE_INLINE_THRESHOLD_BYTES = 100 * 1024; | ||
| const PROMPT_FILE_INLINE_THRESHOLD_LABEL = "100KB"; | ||
| const STEERING_HOOK_CONFIG_FILENAME = "gh-aw-steering.json"; | ||
| const DEFAULT_STEERING_STATE_PATH = "/tmp/gh-aw/copilot-steering-state.json"; |
There was a problem hiding this comment.
💡 Consider using a more descriptive constant name, e.g., STEERING_HOOK_CONFIG_FILE for clarity. Also, moving these constants near the top with other configuration constants could improve readability.
| * runsWarningRemaining: number, | ||
| * runsCriticalRemaining: number, | ||
| * maxRuns: number, | ||
| * statePath: string |
There was a problem hiding this comment.
🔍 The loadSteeringConfig function looks solid. One suggestion: consider adding a comment explaining that GH_AW_COPILOT_MAX_RUNS=0 acts as a sentinel for "no run limit" — this would improve maintainability.
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/e601ff46-a312-4e8a-9d6b-a799d5701053 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed in commit I investigated the failing run/job logs and fixed the JS typecheck/lint issue in Revalidated with:
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
Agent-Logs-U**/*.json ode_modules/.bin/node /repos/actions/gnode --jq cal/bin/node git` (http block)
|
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/294ea110-b23b-4a05-a10c-438f596a35c9 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/294ea110-b23b-4a05-a10c-438f596a35c9 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed in commits I aligned the runtime hook config with the current Copilot CLI hook docs/lifecycle by adding Revalidated with:
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
|
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
🚀 Smoke Pi MISSION COMPLETE! Pi delivered. 🥧 |
Agent Container Tool Check
Result: 11/12 tools available
|
|
PRs: #30568 [docs] Update glossary - daily scan; #30565 [spec-extractor] Update package specifications for agentdrain, cli, console, constants Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
|
UGH! Smoke test caveman was here! Me run test. Me find GitHub! Big fire, much code. Test pass! 🔥🦴 Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
|
🦴 OOG! Me Copilot caveman! Me visit this discussion! Smoke test run — fire big, build strong, code good! All system go! Me leave now to find more tests to smash. GRUG APPROVE! 🔥🦕 Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
Oog! Caveman review PR. Good steering hooks! Two small thoughts left as inline comments.
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
📰 BREAKING: Report filed by Smoke Copilot · ● 14.2M
| @@ -67,6 +67,9 @@ const MAX_SCHEDULED_EXIT2_RETRIES = 1; | |||
| // If prompt files are larger than this threshold, avoid inlining into argv. | |||
| const PROMPT_FILE_INLINE_THRESHOLD_BYTES = 100 * 1024; | |||
| const PROMPT_FILE_INLINE_THRESHOLD_LABEL = "100KB"; | |||
There was a problem hiding this comment.
Oog! Me see DEFAULT_MAX_AUTOPILOT_RUNS = 1. Maybe add comment explain why 1 is good default? Cave brain want know.
| } | ||
|
|
||
| /** | ||
| * Parse --max-autopilot-continues from copilot CLI args. |
There was a problem hiding this comment.
Ugh! parseMaxAutopilotContinues good function. Me think return 0 when not found - maybe return DEFAULT_MAX_AUTOPILOT_RUNS instead for consistent behavior? Just caveman thought.
💨 Smoke Test Results — Run 25432297510
Tests 1–18 pass. Test 19 (Close PR) Warning Firewall blocked 6 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
|
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal!
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.com
To allow these domains, add them to the
network.allowedlist in your workflow frontmatter:
network:
allowed:
- defaults
- "accounts.google.com"
- "android.clients.google.com"
- "clients2.google.com"
- "contentautofill.googleapis.com"
- "safebrowsingohttpgateway.googleapis.com"
- "www.google.com"See Network Configuration for more information.
💥 [THE END] — Illustrated by Smoke Claude · ● 405K
| * maxRuns: number, | ||
| * statePath: string | ||
| * }} | ||
| */ |
There was a problem hiding this comment.
Smoke test review comment #1 🔍
The loadSteeringConfig function cleanly reads all steering config from environment variables with sensible defaults. The use of parsePositiveNumber for validation is a nice defensive pattern. Consider documenting the expected env var names in a JSDoc comment for easier discoverability.
|
|
||
| await checkCommandAccessible(command); | ||
| const resolvedArgs = resolvePromptFileArgs(args); | ||
| installCopilotSteeringHooks(resolvedArgs); |
There was a problem hiding this comment.
Smoke test review comment #2 🔍
installCopilotSteeringHooks(resolvedArgs) is called right after resolvePromptFileArgs, which is a good placement — hooks are installed before the agent run starts. The function wraps failures in try/catch and logs warnings rather than failing the whole harness, which is appropriate for a non-critical enhancement.
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
Summary
.github/hooks/gh-aw-steering.jsonhook configuration before agent executionactions/setup/js/copilot_steering_hook.cjscommand hook that tracks session state and injects warning/critical steering prompts on low time or low run budgetsessionStart,sessionEnd, andagentStopcommand hookssessionEndValidation
make build && make fmtnpm run typecheck(inactions/setup/js)npm run lint:cjs(inactions/setup/js)npm run test:js -- copilot_harness.test.cjs copilot_steering_hook.test.cjs --no-file-parallelism(inactions/setup/js)make agent-report-progresssecret_scanningon changed filesparallel_validation(Code Review + CodeQL)Notes
make agent-report-progresswas rerun when unrelated flakypkg/cliprogress-notification tests intermittently failed; final run passed.Changeset
> Generated by Changeset Generator for issue #30500 · ◷
✨ PR Review Safe Output Test - Run 25432297510
Warning
Firewall blocked 6 domains
The following domains were blocked by the firewall during workflow execution:
accounts.google.comandroid.clients.google.comclients2.google.comcontentautofill.googleapis.comsafebrowsingohttpgateway.googleapis.comwww.google.comSee Network Configuration for more information.