Bug: Copilot CLI launcher preamble leaks into goal slugs / branch names
Evidence (reproducible)
This very worktree is checked out on branch:
feat/issue-1-nodeoptions-max-old-space-size32768-saved-preferen
The nodeoptions-max-old-space-size32768-saved-preferen segment is a slugified
copy of the Copilot CLI launcher preamble:
ℹ NODE_OPTIONS=--max-old-space-size=32768 (saved preference). To change: /home/azureuser/.amplihack/config
The real title of issue #1 is "Implement the first high-quality version of
Simard…" — it has nothing to do with NODE_OPTIONS. So a description/title
string that still contained the launcher banner was fed into slug generation.
Root cause
crate::goals::goal_slug (src/goals/types.rs:183) is a pure slugifier — it
does not strip launcher/recipe noise. Its ingestion callers pass externally
sourced descriptions straight in without first running the established
noise chokepoint recipe_output::extract::strip_recipe_noise:
src/ooda_loop/curate.rs:169 — goal_slug(&decision.description)
src/ooda_loop/curate.rs:219 — goal_slug(&item.description)
src/ooda_loop/cycle.rs:534 — goal_slug(&directive.title)
When the upstream meeting/handoff extraction misses the banner, it survives into
decision.description, then into the goal ID, then into the
feat/issue-N-<goal-slug> branch/worktree name.
The codebase already has a documented single chokepoint for exactly this class
of noise (strip_recipe_noise / is_copilot_launcher_line, issues #2496,
#2570, #2426, #3181) — this path just isn't routed through it.
Secondary gap
is_copilot_launcher_line (src/recipe_output/extract.rs:178) only matches the
ℹ NODE_OPTIONS= line when it ALSO contains (saved preference). A real
launcher variant without that marker exists in-tree
(src/tests_base_type_copilot.rs:531: ℹ NODE_OPTIONS=--max-old-space-size=8192),
so the shared chokepoint misses it while the per-path handler in
src/base_type_copilot/transcript.rs:208 catches it. These two handlers
disagree.
Proposed fix direction (needs a design decision, hence an issue not a blind edit)
- Route externally sourced goal titles/descriptions through
strip_recipe_noise (or a title-specific variant) before goal_slug, and
decide the contract when the entire title is noise (reject / fall back to a
placeholder id) so slugs never become empty.
- Reconcile
is_copilot_launcher_line with the base_type_copilot handler so a
ℹ NODE_OPTIONS= line is dropped regardless of the (saved preference)
marker.
- Add a regression test asserting a banner-contaminated description slugifies to
a clean id (no nodeoptions/max-old-space-size tokens).
Context
Surfaced while executing an ecosystem OODA step whose task input itself arrived
contaminated with this same banner. No code changed on this branch; filing so the
correct extraction chokepoint is fixed with maintainer context rather than a
speculative unilateral edit to the deliberately-conservative filter.
Bug: Copilot CLI launcher preamble leaks into goal slugs / branch names
Evidence (reproducible)
This very worktree is checked out on branch:
The
nodeoptions-max-old-space-size32768-saved-preferensegment is a slugifiedcopy of the Copilot CLI launcher preamble:
The real title of issue #1 is "Implement the first high-quality version of
Simard…" — it has nothing to do with
NODE_OPTIONS. So a description/titlestring that still contained the launcher banner was fed into slug generation.
Root cause
crate::goals::goal_slug(src/goals/types.rs:183) is a pure slugifier — itdoes not strip launcher/recipe noise. Its ingestion callers pass externally
sourced descriptions straight in without first running the established
noise chokepoint
recipe_output::extract::strip_recipe_noise:src/ooda_loop/curate.rs:169—goal_slug(&decision.description)src/ooda_loop/curate.rs:219—goal_slug(&item.description)src/ooda_loop/cycle.rs:534—goal_slug(&directive.title)When the upstream meeting/handoff extraction misses the banner, it survives into
decision.description, then into the goal ID, then into thefeat/issue-N-<goal-slug>branch/worktree name.The codebase already has a documented single chokepoint for exactly this class
of noise (
strip_recipe_noise/is_copilot_launcher_line, issues #2496,#2570, #2426, #3181) — this path just isn't routed through it.
Secondary gap
is_copilot_launcher_line(src/recipe_output/extract.rs:178) only matches theℹ NODE_OPTIONS=line when it ALSO contains(saved preference). A reallauncher variant without that marker exists in-tree
(
src/tests_base_type_copilot.rs:531:ℹ NODE_OPTIONS=--max-old-space-size=8192),so the shared chokepoint misses it while the per-path handler in
src/base_type_copilot/transcript.rs:208catches it. These two handlersdisagree.
Proposed fix direction (needs a design decision, hence an issue not a blind edit)
strip_recipe_noise(or a title-specific variant) beforegoal_slug, anddecide the contract when the entire title is noise (reject / fall back to a
placeholder id) so slugs never become empty.
is_copilot_launcher_linewith the base_type_copilot handler so aℹ NODE_OPTIONS=line is dropped regardless of the(saved preference)marker.
a clean id (no
nodeoptions/max-old-space-sizetokens).Context
Surfaced while executing an ecosystem OODA step whose task input itself arrived
contaminated with this same banner. No code changed on this branch; filing so the
correct extraction chokepoint is fixed with maintainer context rather than a
speculative unilateral edit to the deliberately-conservative filter.