Skip to content

fix(experiments): hypothesis skill semantic validity + JSON output mode (EXPT-4644) - #134

Merged
hsadhvani merged 1 commit into
feat/experiment-hypothesis-builderfrom
harsh/expt-4644-hypothesis-semantic-validity
Jul 29, 2026
Merged

hsadhvani merged 1 commit into
feat/experiment-hypothesis-builderfrom
harsh/expt-4644-hypothesis-semantic-validity

Conversation

@hsadhvani

@hsadhvani hsadhvani commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes over-lenient grading where a structurally-valid but nonsense hypothesis ("If apple pie, then elephant, because purple") scored 3/3 "Looks strong" on the Fast path (EXPT-4644; the Agent/Sonnet path already rejected it). Adds a semantic-validity rule: a slot counts only if its content is genuinely that component, and the change / measurement / rationale must be causally connected; If/then/because filled with non-sequiturs routes to junk.

Also adds a structured output mode: when the caller requests JSON only (the experiment builder's headless entry point), the skill emits the machine contract (schema_version / route / components / hypothesis-with-holes / measurements), matching the o11y experiment-hypothesis skill. The conversational flow and handoff payload are unchanged. This is the shared, portable structured section so the o11y skill can pull from this one later.

Targets feat/experiment-hypothesis-builder (stacks on the in-progress skill).

Note: the skill validator currently fails on a pre-existing name vs directory mismatch (...-assistant vs ...-builder), unrelated to this change.

Testing approaches

  • No unit tests (skill prompt content); graded behavior validated against the EXPT-4644 nonsense repro. The o11y-side change carries the deterministic contract test.

Feature flags

  • N/A

Note

Low Risk
Prompt-only skill documentation with no runtime or auth changes; main risk is inconsistent LLM grading until validated by existing o11y contract tests.

Overview
Fixes over-lenient grading where grammatically correct If/then/because text could score 3/3 despite nonsense. A new semantic validity rule says Change / Measurement / Rationale slots count only when the content is genuinely that component and causally linked; non-sequiturs are treated as absent and routed to junk instead of “Looks strong.”

Adds structured output mode for headless callers (experiment builder): when JSON-only is requested, the skill must return a single object (schema_version, route, components, hypothesis with {{component:hint}} holes, measurements) matching the o11y experiment-hypothesis contract. Conversational flow and the existing handoff payload are unchanged.

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

Comment thread skills/experiments/launchdarkly-experiment-hypothesis-builder/SKILL.md Outdated
@github-actions

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
experiments/launchdarkly-experiment-hypothesis-builder - 0/100 (0/5) new
feature-flags/launchdarkly-flag-command - 100/100 (3/3) new
feature-flags/launchdarkly-flag-create 100/100 (3/3) 100/100 (3/3) no change

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

@hsadhvani
hsadhvani force-pushed the harsh/expt-4644-hypothesis-semantic-validity branch from 71c5603 to 8c6daf4 Compare July 28, 2026 22:46

@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 8c6daf4. Configure here.

Comment thread skills/experiments/launchdarkly-experiment-hypothesis-builder/SKILL.md Outdated
@hsadhvani
hsadhvani force-pushed the harsh/expt-4644-hypothesis-semantic-validity branch from 8c6daf4 to 747caee Compare July 28, 2026 23:57
@hsadhvani
hsadhvani marked this pull request as ready for review July 29, 2026 17:26
@hsadhvani
hsadhvani requested a review from a team as a code owner July 29, 2026 17:26
@hsadhvani
hsadhvani merged commit 849ee1e into feat/experiment-hypothesis-builder Jul 29, 2026
2 checks passed
@hsadhvani
hsadhvani deleted the harsh/expt-4644-hypothesis-semantic-validity branch July 29, 2026 17:34
ericoh-ld added a commit that referenced this pull request Aug 3, 2026
…#141)

* fix(experiments): unblock hypothesis-builder validate and eval checks

Two independent breakages on this branch turned 4 checks red. Neither came
from #139 — it only touched SKILL.md, which is what diff-changed-skills.js
uses to decide the suite must re-run, so it surfaced both.

validate: SKILL.md declared name: launchdarkly-experiment-hypothesis-assistant
while the directory is ...-builder, and validate_skills.py requires the two to
match. Landed in 7e486ab (v0.3.0). Everything else in the repo already said
-builder (_manifest.js, the evals/<suite> dir, the provider's skill_slug, the
eval:hypothesis-builder script), so the frontmatter was the lone outlier.
Renamed it, plus the handoffFrom value where the skill names itself — the only
other occurrence in the repo, with no consumer matching the literal.

This also realigns the eval's forced invocation: the provider invokes
/<skill_slug> = /launchdarkly-experiment-hypothesis-builder, which did not
match the name the skill declared.

Evaluate suite: all 5 tests errored in 0s with "Template render error [Line 190,
Column 90] expected variable end" — none reached an API call. The suite
registered SKILL.md as promptfoo's prompt, promptfoo renders prompts through
nunjucks, and SKILL.md documents its own hole syntax ({{measurement:...}},
{{component:hint}}) in the output-contract examples. Nunjucks reads
`measurement` as a variable, hits the `:`, and throws. Landed in 849ee1e (#134),
whose CI never ran these checks.

Replaced the prompt with a suite-local function prompt that returns SKILL.md
wrapped in {% raw %}. A function prompt does not skip nunjucks — renderPrompt
assigns the return value to basePrompt and still calls renderString on it — and
promptfoo's own autoWrapRawIfPartialNunjucks only fires on unclosed tags, so
closed-but-invalid {{measurement:...}} sails through. Wrapping supplies the
{% raw %} that helper would have added; renderString then returns the file
byte-for-byte, so results.json still shows the exact skill text and SKILL.md on
disk keeps its hole syntax byte-identical to the o11y contract.

Kept suite-local rather than in evals/shared/, which is a GLOBAL_TRIGGERS entry
and would force all 7 suites to re-run.

Verified: validate_skills.py passes 46/46; nunjucks reproduces the exact
Line 190 Column 90 failure on the bare file and renders the wrapped prompt
byte-identically; npm test 70/70; one live suite test passes in 1m2s (was
5 errors in 0s).

Aggregate scores and Evaluate gate need no separate fix — both were cascades of
the errored suite.

* update comments

* fix evals to match new skill
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