Skip to content

feat(should-flag-change): discover repo-specific flag context - #137

Open
bradsimantel wants to merge 6 commits into
mainfrom
bsimantel/should-flag-change-repo-context
Open

feat(should-flag-change): discover repo-specific flag context#137
bradsimantel wants to merge 6 commits into
mainfrom
bsimantel/should-flag-change-repo-context

Conversation

@bradsimantel

@bradsimantel bradsimantel commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What

Teach should-flag-change to discover repo-specific flag context instead of relying on a single hardcoded overlay path.

Today the skill applies a generic rubric. Gonfalon proved out a repo overlay by hardcoding one path (.agents/skills/should-flag-change/repo-context.md) — but that only works for a vendored copy co-located with the skill. For the distributed skill, the overlay has to be found by a repo-relative convention.

Change

At the top of Step 2, add a search-and-gather sweep across the places teams actually keep repo guidance:

  1. A dedicated LaunchDarkly file (**/*launchdarkly*.md, .launchdarkly/**/*.md, **/*flag*context*.md, plus the back-compat Gonfalon path).
  2. A repo skill about flagging (**/skills/*flag*/SKILL.md, .cursor/rules/*flag*.mdc, …).
  3. An AGENTS.md / CLAUDE.md section (heading matching flag / launchdarkly / feature toggle).

Discovered decision inputs — posture, this repo's flag-SDK signatures, generated-file exclusions, candidate environments, ancestor-state resolution — fold into the existing framework. Three rules keep it safe:

  • Precedence on conflict: dedicated file > flagging skill > AGENTS/CLAUDE section; the source is named in reasons.
  • Inputs, never override: discovered context can tighten the call but cannot weaken the safety spine (user-observability test, false-negative-over-false-positive still win).
  • Absent is normal: no context found → proceed generically, silently.

Also wires the two existing hooks to the discovered context (item 2 prefers discovered SDK signatures over generic grep terms; the posture tie-breaker uses a discovered default), and bumps to 0.3.0-experimental.

Portability is preserved — discovery is plain Read/Grep/Glob, no new tool or MCP dependency, so it still runs in CI, Devin, and Cursor.

Eval coverage

Added six agentic fixtures to evals/should-flag-change/promptfooconfig.yaml exercising the discovery sweep and its three rules. Each fixture's discovered context is outcome-determining — the same diff would land differently without it:

  1. Posture tie-break — an AGENTS.md low-overhead posture tips a genuinely balanced, customer-visible change to recommend: true.
  2. In-house SDK wrapper — the repo gates via a house features.enabled() / @acme/flags wrapper the generic grep terms miss; the agent learns the signature from the context file and flags the ungated new route.
  3. Generated path excluded — a change confined to a codegen *.gen.ts path the context file marks generated → not-suited.
  4. Guardrail (inputs never override) — a user-reaching auth loosening under /internal is flagged despite a local "never flag /internal" rule, with the reasons stating the safety spine overrode the rule.
  5. No-context control — with no guidance anywhere, the agent proceeds generically and does not hallucinate a discovered overlay.
  6. Precedence on conflict — a dedicated launchdarkly.md outranks a conflicting AGENTS.md posture.

New discovery-specific assertions (discovered_context, context_attributed, and guardrail_held for #4) sit alongside the reused verdict_match / verdict_taxonomy / stayed_advisory / explored_before_deciding checks. The suite-wide verdict_contract and read_only_guard invariants still hold on every new fixture.

This also fixes a latent gap in the eval harness: the recommend-flag tool schema (evals/tools/definitions.json) was missing the verdict property, so the Agent SDK stripped verdict from every call and the verdict_taxonomy assertions never actually observed it. Adding the field makes those checks pass suite-wide.

The full should-flag-change suite (16 fixtures) passes green.


Note

Low Risk
Changes are limited to advisory skill instructions, eval harness/schema, and version metadata—no runtime product or auth paths.

Overview
should-flag-change now discovers repo-specific flagging guidance at the start of Step 2 (via Glob/Grep/Read on dedicated LaunchDarkly docs, repo flag skills, and AGENTS.md/CLAUDE.md) instead of relying on a single hardcoded overlay path. Discovered inputs feed posture tie-breaks, SDK grep signatures, and generated-path exclusions, with precedence, inputs-never-override (safety spine still wins), and silent generic fallback when nothing is found; product/plugin flag skills are explicitly excluded from context.

The skill bumps to 0.3.0-experimental. The eval recommend-flag tool schema gains a verdict enum so agent runs preserve verdict and verdict_taxonomy assertions work suite-wide.

Six new agentic promptfoo fixtures exercise outcome-determining discovery (posture, house SDK wrapper, codegen exclusions, guardrail override, no-context + plugin decoy, conflicting-source precedence), with discovered_context, context_attributed, and guardrail_held checks.

Reviewed by Cursor Bugbot for commit 741e5bb. Bugbot is set up for automated code reviews on this repo. Configure here.

Generalize the single hardcoded overlay path (proven out in Gonfalon)
into a search-and-gather sweep at the top of Step 2: a dedicated
LaunchDarkly file, a repo skill about flagging, or an AGENTS.md /
CLAUDE.md section. Fold discovered decision inputs (posture, this
repo's flag-SDK signatures, generated-file exclusions, candidate
environments, ancestor-state resolution) into the generic framework.

Add precedence-on-conflict, inputs-never-override (the safety spine
still wins), and silent graceful fallback when nothing is found.
Wire the two existing hooks: item 2 prefers discovered SDK signatures
over generic grep terms, and the posture tie-breaker uses a discovered
default. Bump to 0.3.0-experimental.
@bradsimantel
bradsimantel requested a review from nieblara July 29, 2026 22:02
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

Skill eval results

Skill Before After Δ
agentcontrol/configs-create 100/100 (4/4) 100/100 (4/4) no change
agentcontrol/configs-update 80/100 (4/5) 80/100 (4/5) no change
agentcontrol/configs-variations 80/100 (4/5) 80/100 (4/5) no change
agentcontrol/tools 75/100 (3/4) 75/100 (3/4) no change
feature-flags/flag-and-release-change - 100/100 (4/4) new
feature-flags/flag-release - 100/100 (5/5) new
feature-flags/launchdarkly-flag-command - 100/100 (3/3) new
feature-flags/launchdarkly-flag-create 100/100 (3/3) 100/100 (4/4) no change
feature-flags/launchdarkly-flag-drift - 100/100 (4/4) new
feature-flags/should-flag-change - 100/100 (16/16) new

Only suites whose source actually changed since their last recorded score were re-run. Soft-failing while we stabilise the baseline.

Add six agentic fixtures covering Step 2's "discover the repo's flag
context first" sweep, each with outcome-determining repo context:

1. posture tie-break (AGENTS.md low-overhead posture tips a balanced
   customer-visible change to a flag)
2. in-house SDK wrapper recognized (learns the repo's features.enabled /
   @acme/flags signature the generic grep terms miss)
3. generated path excluded (a codegen *.gen.ts change the context file
   marks not-suited)
4. guardrail: inputs never override (recommends a flag for a user-reaching
   auth loosening under /internal DESPITE a local never-flag rule, and
   states it overrode the rule on safety grounds)
5. no-context control (proceeds generically, does not hallucinate an overlay)
6. precedence on conflict (dedicated launchdarkly.md outranks a conflicting
   AGENTS.md posture)

Assertions reuse the existing verdict_match / verdict_taxonomy /
stayed_advisory / explored_before_deciding patterns and add discovery
checks: discovered_context (the sweep read a repo-context source) and
context_attributed (the reasons name the source used, inverted for the
no-context control), plus guardrail_held for fixture 4. The suite-wide
verdict_contract and read_only_guard invariants still hold on every new
fixture.

Also add the `verdict` property to the recommend-flag tool schema in
evals/tools/definitions.json: it was documented in the skill and asserted
by verdict_taxonomy but missing from the tool schema, so the Agent SDK
stripped it from every call and the taxonomy checks never observed a
verdict. With the field present, verdict_taxonomy passes suite-wide.
@bradsimantel
bradsimantel marked this pull request as ready for review July 29, 2026 23:13
@bradsimantel
bradsimantel requested a review from a team as a code owner July 29, 2026 23:13
The skill's version bump in SKILL.md was not reflected in the generated
catalog, failing the validate job's `generate_catalog.py --check` step.
Comment thread evals/should-flag-change/promptfooconfig.yaml Outdated
Comment thread skills/feature-flags/should-flag-change/SKILL.md Outdated
…matching globs

Two issues from PR review:

- Discovery 2's `discovered_context` still used the shared regex, which
  does not match the fixture's renamed `launchdarkly.md` context file — so
  a correct Read of it failed the check while empty Globs of the standard
  patterns could pass it. Switch it to the same `/launchdarkly/i` Read/Grep
  check Discovery 6 uses (requires actually consuming the file), and fix a
  stale comment that named `.launchdarkly/flagging.md`.

- The Step 2 "repo skill about flagging" Globs (`**/skills/*flag*/SKILL.md`,
  etc.) match this skill's own slug, so the skill could discover ITSELF as
  repo context and Discovery 5's "no guidance anywhere" premise was leaky.
  Tell the agent to exclude its own skill directory from those matches, and
  note in the Discovery 5 fixture that the self-installed skill is excluded.

Full should-flag-change suite (16 fixtures) still passes green.
Comment thread evals/should-flag-change/promptfooconfig.yaml Outdated
…ntext source

The discovered_context check in Discovery fixtures 1, 3, and 4 still used
the shared regex, which counts a bare Glob of the skill's standard patterns
(matching flag.*context / .launchdarkly/) as success — so the metric could
pass without the agent ever reading the outcome-determining source. Make all
discovery fixtures require a Read/Grep of the concrete file (AGENTS.md for
fixture 1, flagging.md for 3 and 4), matching the filename WITH extension so
a generic SDK grep that includes the term "launchdarkly" cannot false-pass.
Also tighten fixtures 2 and 6 from /launchdarkly/ to /launchdarkly.md/ for
the same reason. Verified all six discovery fixtures pass because the source
was actually read.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 12f0d01. Configure here.

Comment thread skills/feature-flags/should-flag-change/SKILL.md Outdated
…iscovery

The Step 2 repo-skill discovery globs (`**/.claude/skills/*flag*/SKILL.md`,
etc.) match not just this skill but its LaunchDarkly plugin siblings —
launchdarkly-flag-create, flag-and-release-change, flag-cleanup, remove-flag,
launchdarkly-flag-drift — which install flat under `.claude/skills/`. Those
are product/action skills (create/edit/toggle/remove/release), so ingesting
them as "discovered repo flagging context" could fabricate a false overlay or
pull this read-only advisory skill toward acting. Broaden the exclusion in
SKILL.md beyond the skill's own directory to cover plugin/vendored product
skills, and reinforce that a discovered skill's action instructions are never
followed.

Harden the Discovery 5 control to prove it: it now scaffolds a sibling
`launchdarkly-flag-create` product skill under `.claude/skills/` and asserts
the agent ignores it as context and stays advisory (read_only_guard /
stayed_advisory hold). Full should-flag-change suite (16 fixtures) passes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant