feat(shared/apm.md): expose target input for slim per-harness bundles#1184
Merged
Conversation
The gh-aw shared workflow at .github/workflows/shared/apm.md previously
hardcoded `target: all` on its apm-action call, forcing every consumer
bundle to include all eight harness layouts (.github/, .claude/, .cursor/,
.opencode/, .codex/, .gemini/, .windsurf/, .agents/) regardless of which
engine the workflow actually used.
Expose `target` as an import-schema input (string CSV; default `all`)
so consumers can opt into slim, single-harness bundles. Wire it into the
Pack step via `${{ github.aw.import-inputs.target || 'all' }}` -- the
fallback preserves byte-for-byte back-compat for every existing import
that omits the field.
Notes on precedence: shared/apm.md runs apm-action with
`isolated: 'true'`, which intentionally ignores any apm.yml in the
consumer repo. The `target` input is therefore the sole target signal --
there is no apm.yml to honor or override in this context. Consumers who
target a single engine (claude / copilot / etc.) should set
`target: <engine>` for materially smaller bundles and faster restores.
Phase 2 (separate, in microsoft/gh-aw): teach gh-aw's compile step to
auto-inject `target: <engine>` from the workflow's declared engine when
the consumer omits the field, so slim bundles become zero-config for
single-engine workflows.
Recompiles the two lock workflows that import shared/apm.md
(pr-review-panel.lock.yml, triage-panel.lock.yml) so the new expression
ships in CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the gh-aw shared workflow shared/apm.md to let importing workflows choose an APM target (defaulting to all) so packed bundles can be slimmed to only the needed harness layout(s), instead of always packing every supported layout when running in isolated: true mode.
Changes:
- Add a new optional
targetinput toimport-schema(defaultall) and thread it into themicrosoft/apm-actionPack step. - Regenerate/update the compiled lock workflows to use the new
target: ${{ github.aw.import-inputs.target || 'all' }}expression. - Add an Unreleased CHANGELOG entry for the workflow feature and update
uv.lock’s editable package version.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/shared/apm.md |
Adds target as an import input and passes it to apm-action during pack. |
.github/workflows/pr-review-panel.lock.yml |
Regenerated lock workflow to pass through the new target input with a fallback to all. |
.github/workflows/triage-panel.lock.yml |
Regenerated lock workflow to pass through the new target input with a fallback to all. |
CHANGELOG.md |
Adds an Unreleased entry describing the new shared workflow capability. |
uv.lock |
Updates the editable apm-cli lock entry version metadata. |
Copilot's findings
- Files reviewed: 4/5 changed files
- Comments generated: 2
|
|
||
| ### Added | ||
|
|
||
| - `shared/apm.md` gh-aw shared workflow exposes a `target:` import input (default `all`) so consumer workflows can ship slim, single-harness bundles instead of always packing every layout. (#1184) |
Comment on lines
+154
to
+159
| list. Valid tokens: copilot, claude, cursor, codex, opencode, gemini, | ||
| windsurf, agent-skills, all. Default: all (every supported harness). | ||
| Set this to match the engine your gh-aw workflow targets for smaller, | ||
| faster bundles. The shared workflow runs apm-action in isolated mode, | ||
| so any apm.yml in the consumer repo is intentionally ignored -- this | ||
| input is the sole target signal. |
danielmeppiel
pushed a commit
that referenced
this pull request
May 7, 2026
#1185) The bare-expression regex in gh-aw's importInputsExprRegex (pkg/parser/import_field_extractor.go) only matches `${{ github.aw.import-inputs.X }}` -- the `|| 'all'` belt-and-suspenders introduced in #1184 made the regex skip substitution entirely, so consumer-supplied `with: target: copilot` was silently ignored and the unresolved expression survived into the lock workflow (yielding empty runtime env, which apm then treats as the default). The schema default `default: all` declared in import-schema is already applied by gh-aw's applyImportSchemaDefaultsFromFrontmatter BEFORE substitution, so the fallback was redundant anyway. Dropping it lets gh-aw substitute literal values into the lock workflow. Verified: `gh aw compile` now emits `target: all` (literal) into the two consuming lock workflows. With `with: target: copilot` set on the import, gh-aw will substitute `target: copilot` instead. Closes #1185. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
danielmeppiel
pushed a commit
that referenced
this pull request
May 7, 2026
#1185) The bare-expression regex in gh-aw's importInputsExprRegex (pkg/parser/import_field_extractor.go) only matches `${{ github.aw.import-inputs.X }}`. The `|| 'all'` belt-and-suspenders introduced in #1184 made the regex skip substitution entirely, so consumer-supplied `with: target: copilot` was silently ignored -- the unresolved expression survived into the lock workflow and the runtime env ended up empty (which apm-action then treated as `all`). The schema default `default: all` declared in import-schema is already applied by gh-aw's applyImportSchemaDefaultsFromFrontmatter BEFORE substitution, so the fallback was redundant anyway. Dropping it lets gh-aw substitute literal values into consuming lock workflows. Verified locally: the two consuming lock workflows (pr-review-panel.lock.yml, triage-panel.lock.yml) now carry the literal substituted value `target: all` after recompile (since neither import sets `target:`). Consumers who pass `with: target: copilot` will see `target: copilot` substituted into their lock. Edits to the lock files are surgical (single line each) -- the frontmatter_hash in the gh-aw-metadata header only covers the .md frontmatter, not the body, so they remain valid. Closes #1185. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
danielmeppiel
pushed a commit
that referenced
this pull request
May 7, 2026
#1185) The bare-expression regex in gh-aw's importInputsExprRegex (pkg/parser/import_field_extractor.go) only matches `${{ github.aw.import-inputs.X }}`. The `|| 'all'` belt-and-suspenders introduced in #1184 made the regex skip substitution entirely, so consumer-supplied `with: target: copilot` was silently ignored: the unresolved expression survived into the lock workflow and the runtime env was empty (which apm-action then treated as `all`). The schema default `default: all` declared in import-schema is already applied by gh-aw's applyImportSchemaDefaultsFromFrontmatter BEFORE substitution, so the fallback was redundant. Dropping it lets gh-aw substitute literal values into consuming lock workflows. Recompiled with gh-aw v0.71.5 (matching the version stamped in lock metadata). The two consuming lock workflows now carry the literal substituted value `target: all` since neither import sets `target:`. Consumers who pass `with: target: copilot` will get `target: copilot`. Closes #1185. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
danielmeppiel
added a commit
that referenced
this pull request
May 7, 2026
#1185) (#1186) The bare-expression regex in gh-aw's importInputsExprRegex (pkg/parser/import_field_extractor.go) only matches `${{ github.aw.import-inputs.X }}`. The `|| 'all'` belt-and-suspenders introduced in #1184 made the regex skip substitution entirely, so consumer-supplied `with: target: copilot` was silently ignored: the unresolved expression survived into the lock workflow and the runtime env was empty (which apm-action then treated as `all`). The schema default `default: all` declared in import-schema is already applied by gh-aw's applyImportSchemaDefaultsFromFrontmatter BEFORE substitution, so the fallback was redundant. Dropping it lets gh-aw substitute literal values into consuming lock workflows. Recompiled with gh-aw v0.71.5 (matching the version stamped in lock metadata). The two consuming lock workflows now carry the literal substituted value `target: all` since neither import sets `target:`. Consumers who pass `with: target: copilot` will get `target: copilot`. Closes #1185. Co-authored-by: Daniel Meppiel <copilot-rework@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
danielmeppiel
added a commit
that referenced
this pull request
May 7, 2026
…1192) Both panels run on the gh-aw default Copilot CLI engine, so they only need the 'copilot' layout from the apm package. Pinning target=copilot (via the new shared/apm.md input from #1184) ships a slim per-harness bundle instead of installing all seven harnesses on every panel run. This also side-steps the cowork-in-all crash that hit the apm self-check (run 25511043293) before #1191 landed; the panels now explicitly request a single supported harness, so an experimental target leaking into 'all' could not regress these workflows again. Co-authored-by: Daniel Meppiel <copilot-rework@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
shared/apm.md(the gh-aw shared workflow) hardcodedtarget: allon itsapm-actioncall, forcing every consumer bundle to ship all 8 harness layouts (.github/,.claude/,.cursor/,.opencode/,.codex/,.gemini/,.windsurf/,.agents/) regardless of which engine actually consumed it. This PR exposestargetas animport-schemainput (defaultall) so consumers can opt into slim, single-harness bundles. Zero behavior change for any existing import.Problem (WHY)
The shared workflow runs
apm-actionwithisolated: 'true'andtarget: allbaked into the Pack step (.github/workflows/shared/apm.mdwas at line 265). Two consequences:shared/apm.mdpacks every harness's deploy tree into the artifact, even when the agent step downstream only consumes one. For a single-engine gh-aw workflow this is roughly 8x more files than necessary.shared/apm.md'simport-schema-- they would have had to fork the file.The natural follow-up question -- "why not honor the consumer repo's
apm.yml target:?" -- doesn't apply:isolated: 'true'makesapm-actionignore any consumer apm.yml entirely (it generates a synthetic one from the inlinedependencies:input, working in/tmp/gh-aw/apm-workspace). There is no apm.yml to honor in this code path. The shared workflow is the sole signal, so it needs an input.Approach (WHAT)
Add a single optional
targetinput toimport-schema, defaultall, and thread it into the Pack step via${{ github.aw.import-inputs.target || 'all' }}.target(singular) -- matches theapm.ymlkey, theapm-actioninput, and the--targetCLI flag.string(CSV when multiple targets are needed) -- matchesapm-action's native format. Avoids forcing a YAML-array-to-CSV conversion in the workflow.all-- byte-for-byte back-compat with the previous hardcoded value. No existing import changes behavior.|| 'all'belt-and-suspenders covers gh-aw versions that emit empty strings rather than honoringdefault:in the schema. Keeps the contract deterministic regardless of which gh-aw version compiles the workflow.Rejected alternatives
apmjob runs withpermissions: {}and no checkout; adding one costs ~15s for a heuristic the consumer can replace with one line.engine:sibling inputtarget:in theapps[]schemaImplementation (HOW)
Three surgical edits to
.github/workflows/shared/apm.md:targettoimport-schemawith description text enumerating valid tokens (copilot,claude,cursor,codex,opencode,gemini,windsurf,agent-skills,all) and noting the isolated-mode contract (apm.yml is intentionally ignored).target: allin the Pack step withtarget: ${{ github.aw.import-inputs.target || 'all' }}.Recompile via
gh aw compileregenerates the two consuming lock workflows (pr-review-panel.lock.yml,triage-panel.lock.yml) so the new expression ships in CI. CHANGELOG entry added under[Unreleased].Trade-offs
allkeeps the bundle-bloat default. This is intentional for back-compat. Slim bundles are now an opt-in. Phase 2 (gh-aw side) makes them zero-config for single-engine workflows.target: copilot(or whichever) explicitly -- one line.default: allin import-schema is documentation-grade. The expression-level|| 'all'is what actually guarantees the runtime behavior. We accept the small redundancy because gh-aw's import-input default substitution semantics vary across versions.Validation
uv run --extra dev ruff check src/ tests/ && uv run --extra dev ruff format --check src/ tests/-- silent.gh aw compile-- 5 workflows recompiled, 0 errors. The two lock files that importshared/apm.mdnow containtarget: ${{ github.aw.import-inputs.target || 'all' }}. At runtime, undefinedgithub.aw.import-inputs.targetevaluates to empty in${{ }}expressions, so the||fallback yields'all'-- preserving the previous behavior exactly.How to test
pr-review-panel.lock.yml/triage-panel.lock.ymlworkflows that importshared/apm.mdwithout settingtarget:continue to receivetarget: all. No change in CI behavior expected.target: copilotto awith:block and recompile -- thetarget:value flows through toapm-actionand the resulting bundle should contain only.github/(not the other 7 harness trees).Follow-up
Open a sibling issue in
microsoft/gh-aw: "Pass workflow engine astargetto shared/apm.md" -- gh-aw's compile step knows the engine declared in the workflow front-matter and could injecttarget: <engine>automatically when the consumer omits the field. Makes slim bundles zero-config for single-engine workflows.