Skip to content

Adventure: πŸ§ͺ Blind by Design β€” 🟑 Intermediate#43

Merged
KatharinaSick merged 6 commits into
off-on-dev:mainfrom
aepfli:adventure/blind-by-design-intermediate
May 11, 2026
Merged

Adventure: πŸ§ͺ Blind by Design β€” 🟑 Intermediate#43
KatharinaSick merged 6 commits into
off-on-dev:mainfrom
aepfli:adventure/blind-by-design-intermediate

Conversation

@aepfli
Copy link
Copy Markdown
Contributor

@aepfli aepfli commented Apr 30, 2026

Summary

Outcome by cohort: layer the three OpenFeature evaluation-context tiers (global, transaction, invocation) onto the Spring Boot lab and register a custom audit Hook, so the targeting in flags.json fires per cohort (species, country, dose) and every evaluation lands in the audit log.

What this PR ships

  • adventures/planned/00-blind-by-design/docs/index.md β€” adds the 🟑 Intermediate card to the Choose Your Level grid
  • adventures/planned/00-blind-by-design/docs/intermediate.md β€” challenge doc
  • adventures/planned/00-blind-by-design/docs/solutions/intermediate.md β€” solution walkthrough (kept in repo, hidden from mkdocs.yaml nav until challenge launch)
  • adventures/planned/00-blind-by-design/intermediate/ β€” broken-state Spring Boot project + verify.sh + run-austria.sh / run-germany.sh
  • .devcontainer/00-blind-by-design_02-intermediate/

Stacking

This is PR 2 of 3, branched from adventure/blind-by-design-beginner (#42). The diff currently includes Beginner's content because this PR is stacked on top of it. Review #42 first β€” once it merges into main, the Intermediate-only delta will become apparent here automatically.

The original full-state PR #40 is kept open for reference and will be closed once all three per-level PRs land.

Part of #41

@aepfli aepfli requested a review from a team as a code owner April 30, 2026 09:23
@aepfli aepfli force-pushed the adventure/blind-by-design-intermediate branch from fc2303b to d8b9639 Compare April 30, 2026 13:12
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
@aepfli aepfli force-pushed the adventure/blind-by-design-intermediate branch from d8b9639 to 515140a Compare April 30, 2026 13:17
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
…only PR

Per @KatharinaSick's first instinct on review β€” and on reflection
the author agrees: when the placeholder stubs are reachable from
the side-nav they create more confusion than they resolve. The
stub files stay on disk so docs/index.md's links don't 404, but
they're not surfaced in navigation. Intermediate and Expert come
back into the nav in off-on-dev#43 and off-on-dev#44 once their content is real.

Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
@aepfli aepfli force-pushed the adventure/blind-by-design-intermediate branch from 515140a to 4a8fca7 Compare April 30, 2026 13:23
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
…inner-only PR

The two stub level-docs and the matching index.md cards were
carried in solely so docs/index.md links did not 404. With the
nav already trimmed (per @KatharinaSick on PR off-on-dev#42), and now with
the cards out of the landing page, the Beginner PR is genuinely
scoped to a single level. Intermediate and Expert each add their
own card + level doc as part of their respective PRs (off-on-dev#43 / off-on-dev#44).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
@aepfli aepfli force-pushed the adventure/blind-by-design-intermediate branch from 4a8fca7 to 890b011 Compare April 30, 2026 13:38
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
@aepfli aepfli force-pushed the adventure/blind-by-design-intermediate branch from 890b011 to 3709227 Compare April 30, 2026 14:06
KatharinaSick pushed a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
…only PR

Per @KatharinaSick's first instinct on review β€” and on reflection
the author agrees: when the placeholder stubs are reachable from
the side-nav they create more confusion than they resolve. The
stub files stay on disk so docs/index.md's links don't 404, but
they're not surfaced in navigation. Intermediate and Expert come
back into the nav in off-on-dev#43 and off-on-dev#44 once their content is real.

Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
KatharinaSick pushed a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
…inner-only PR

The two stub level-docs and the matching index.md cards were
carried in solely so docs/index.md links did not 404. With the
nav already trimmed (per @KatharinaSick on PR off-on-dev#42), and now with
the cards out of the landing page, the Beginner PR is genuinely
scoped to a single level. Intermediate and Expert each add their
own card + level doc as part of their respective PRs (off-on-dev#43 / off-on-dev#44).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request Apr 30, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
aepfli and others added 4 commits May 6, 2026 23:55
Layer the three OpenFeature evaluation-context tiers (global,
transaction, invocation) onto the Spring Boot lab and register a
custom audit Hook so the targeting in flags.json fires per cohort
(species, country, dose) and every evaluation lands in the audit log.

Replaces the placeholder intermediate.md stub with the full level
doc, ships the Intermediate solution walkthrough, broken-state code,
verify.sh, and devcontainer.

Stacked on top of off-on-dev#42 (🟒 Beginner). Review that one first.

Part of off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
- rename 'πŸ§ͺ The story (optional)' β†’ 'πŸͺ The Backstory'
- pin flagd image to v0.15.4 (was: ':latest')
- devcontainer: forward only :8080 (was: 8080+8013+8014+8015+8016)
- drop the published flagd ports β€” sidecar reaches the lab on the
  docker-internal network as flagd:8013
- drop the inline solutions/intermediate.md cross-link and the
  closing 'Spoiler ahead?' callout (solutions are unpublished
  pre-deadline)
- replace 'Run the Verification Script' wording with the Adventure 03
  template (verify.sh + Certificate of Completion)
- verify.sh: lean on lib/scripts/http.sh test_http_endpoint for the
  reachability check

Refs: PR off-on-dev#42 review by @KatharinaSick

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Mirror @KatharinaSick's Beginner pattern (605dabc): a thin Makefile
for discoverability + remove the solution doc since solutions are
not meant to be published before the challenge launch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Mirrors the structure Beginner adopted in PR off-on-dev#42 review (06789e7) β€” a
discrete "Start the Lab" step before any forwarded-port click, so users
who open the Ports tab early don't hit a 502. Renumbers downstream
sub-steps (3a/b/c β†’ 4a/b/c) and renames the post-fix run section to
"Re-run the Lab with a Cohort" to disambiguate from the new step 2.

Carries the same review feedback Katharina left on the Beginner level
forward to the Intermediate level so the per-level shape stays
consistent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aepfli aepfli force-pushed the adventure/blind-by-design-intermediate branch from 3709227 to fa2720c Compare May 6, 2026 21:58
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request May 6, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
Copy link
Copy Markdown
Contributor

@KatharinaSick KatharinaSick left a comment

Choose a reason for hiding this comment

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

I didn't play it yet but looks great! Left a couple of comments :)

Comment thread .devcontainer/00-blind-by-design_01-beginner/devcontainer.json
πŸ“‚ Challenge directory:
$CHALLENGE_DIR

πŸ§ͺ Sibling services already running (managed by devcontainer compose):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There are multiple ports mentioned here but only 8080 is forwarded in devcontainer.json. is that intended?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As everything happens in teh terminal: do we even need to forward any port?


The lab and a flagd sidecar run as siblings in the devcontainer's compose stack. The OpenFeature client uses `Resolver.RPC` to reach `flagd:8013`; flagd is the one watching `flags.json` and serving evaluations from it. The targeting rules live entirely inside `flags.json`; your job is to make sure the attributes the rules reference (`species`, `country`, `dose`) are populated on every evaluation.

## 🎯 Objective
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I always try to keep the objective focused on outcomes not on how to get there. Further, there should be only a hand full (3-5). Would it be possible to change that? Or is it important for the challenge to have all the detail in here? If it's the latter, I'm good with it :)

- **`targetingKey`** β€” a special slot on the eval context that flag implementations use as the bucketing key for fractional rollouts. The SDK exposes it via `ec.getTargetingKey()` rather than `ec.getValue("targetingKey")`; the `ImmutableContext(targetingKey, attributes)` constructor sets it explicitly. In real apps it's typically a stable user id β€” i.e. the canonical PII identifier you do **not** want flowing into audit logs.
- **`Hook`** β€” interceptor for flag evaluations. `before`/`after`/`error`/`finallyAfter` fire around every `client.getXxxDetails(...)`. `HookContext.getCtx()` exposes the **merged** context β€” that's what makes an audit trail useful instead of a "got here" log line.

## 🧠 What You'll Learn
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What's the difference of what you'll learn and concepts you'll touch?

- In `afterCompletion`, clears the transaction context. Servlet threads are pooled β€” if you don't clear, the previous request's species or targetingKey leaks into whichever request lands on the thread next.
- In a static initialiser, registers a `ThreadLocalTransactionContextPropagator` once on the OpenFeature API. Without it the SDK has no way to carry per-request context across the call into the controller, and the transaction context silently stays empty.

> ℹ️ The Intermediate `verify.sh` doesn't exercise the `?userId=` branch (no Intermediate flag uses `targetingKey`). If you skip that branch, Intermediate still passes β€” but the Expert level's variant-distribution panel will collapse to a single bucket. The wiring is forward-looking on purpose.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It woudl be great if intermediate would fail too if it's not solved

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That's also one of the reason I like outcome based objectives more. It doesn't matter how the user gets there but the otucome can be verified :)

- Rewrite Objective as 5 outcome-based bullets β€” drop the mechanism-heavy
  list; mechanism moves into the per-step instructions where it earns
  its place.
- Drop the "Concepts you'll touch" section; its load-bearing content
  migrates inline: HandlerInterceptor Javadoc into 4a, three-context-layer
  precedence rule into 4b, Hook lifecycle into 4d.
- Add an explicit step 4c "Pass the dose as invocation context from
  Trial" β€” the dose-passing was an objective bullet with no
  corresponding implementation step.
- Drop targetingKey / ?userId= wiring from Intermediate. No Intermediate
  flag uses it, the verifier didn't exercise it, and the PII callout it
  motivated belongs in Expert (where eval context flows into OTel spans
  and the leak surface is real). Architecture diagram + lead paragraph
  + step 4a + step 4d trimmed accordingly.
- Devcontainer: drop forwardPorts. Intermediate is API-only β€” every
  curl runs from inside the Codespace terminal, so host-side forwarding
  adds noise without value. The post-start banner stops claiming flagd
  ports are forwarded (they were never forwarded; the banner was lying).
- verify.sh: sync OBJECTIVE block to the new outcome-based docs; tighten
  the AuditHook check to grep for the literal '[AUDIT]' format the docs
  specify (was matching 'AUDIT|Before hook|After hook', too lenient).

Addresses Katharina's review comments on intermediate.md:51 (objective
shape), :77 (Learn vs Concepts overlap), :165 (verifier exercises the
objective), and the post-start.sh:14 port-hygiene comments.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request May 8, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request May 8, 2026
Mirrors the Intermediate cleanup (8bcf885) on Expert, plus picks up the
targetingKey + PII discipline that was deferred from Intermediate.

- Rewrite Objective as 5 outcome-based bullets β€” drop the
  mechanism-heavy list, drop the parenthetical "verified: SpeciesInterceptor
  wires userId" note (now redundant: targetingKey lives at the
  implementation level here, not the objective level).
- Drop the "Concepts you'll touch" section. Its load-bearing content
  migrates inline to the per-step instructions: TracerProvider vs
  MeterProvider gloss into 4a, TracesHook/MetricsHook gloss into 4b,
  the ContextSpanHook authoring guide into a new 4c, and the
  fractional + targetingKey explanation into 4d.
- Add explicit step 4c "Author and register your own ContextSpanHook"
  β€” the ContextSpanHook was an objective bullet with no corresponding
  implementation step (analogous to the missing dose-passing step on
  Intermediate).
- Move the PII allowlist callout to step 4c β€” Expert is where it earns
  its place, since eval context is about to flow onto OTel spans that
  ship to SIEM-grade backends. The Intermediate cross-link goes away;
  the discipline lives here standalone.
- Lift "Start the Lab" out of step 1 into its own step 2 β€” mirrors the
  Intermediate / Beginner shape, so a player who clicks the Ports tab
  before reading further doesn't see a 502.
- Format Deadline + Community thread sections as Coming Soon callouts,
  matching Intermediate.
- Sync verify.sh OBJECTIVE block to the new outcome-based docs.

Addresses Katharina's review themes carried over from off-on-dev#43 (objective
shape, Concepts vs Learn overlap, verifier exercises objective).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@KatharinaSick KatharinaSick left a comment

Choose a reason for hiding this comment

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

I removed 2 little cd commands from the docs that are not needed. apart from that it looks good - playing was fun :)

please sign your commits and we're good to merge

@KatharinaSick KatharinaSick merged commit 66e016a into off-on-dev:main May 11, 2026
2 of 3 checks passed
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request May 18, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request May 18, 2026
Mirrors the Intermediate cleanup (8bcf885) on Expert, plus picks up the
targetingKey + PII discipline that was deferred from Intermediate.

- Rewrite Objective as 5 outcome-based bullets β€” drop the
  mechanism-heavy list, drop the parenthetical "verified: SpeciesInterceptor
  wires userId" note (now redundant: targetingKey lives at the
  implementation level here, not the objective level).
- Drop the "Concepts you'll touch" section. Its load-bearing content
  migrates inline to the per-step instructions: TracerProvider vs
  MeterProvider gloss into 4a, TracesHook/MetricsHook gloss into 4b,
  the ContextSpanHook authoring guide into a new 4c, and the
  fractional + targetingKey explanation into 4d.
- Add explicit step 4c "Author and register your own ContextSpanHook"
  β€” the ContextSpanHook was an objective bullet with no corresponding
  implementation step (analogous to the missing dose-passing step on
  Intermediate).
- Move the PII allowlist callout to step 4c β€” Expert is where it earns
  its place, since eval context is about to flow onto OTel spans that
  ship to SIEM-grade backends. The Intermediate cross-link goes away;
  the discipline lives here standalone.
- Lift "Start the Lab" out of step 1 into its own step 2 β€” mirrors the
  Intermediate / Beginner shape, so a player who clicks the Ports tab
  before reading further doesn't see a 502.
- Format Deadline + Community thread sections as Coming Soon callouts,
  matching Intermediate.
- Sync verify.sh OBJECTIVE block to the new outcome-based docs.

Addresses Katharina's review themes carried over from off-on-dev#43 (objective
shape, Concepts vs Learn overlap, verifier exercises objective).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request May 18, 2026
Wire the OpenTelemetry meter provider, register the OpenFeature
MetricsHook + TracesHook, author a ContextSpanHook that copies the
merged evaluation context onto Tempo spans, then diagnose and roll
back a misbehaving fractional rollout (vision_amplifier_v2) on the
Grafana LGTM dashboard β€” no redeploy.

Replaces the placeholder expert.md stub with the full level doc,
ships the Expert solution walkthrough, broken-state code (including
the dashboard JSON and k6 loadgen), verify.sh, and devcontainer.

Stacked on top of off-on-dev#43 (🟑 Intermediate). Review off-on-dev#42 then off-on-dev#43 first.
This is the last PR in the series, so it closes the tracking issue.

Closes off-on-dev#41

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
aepfli added a commit to aepfli/open-ecosystem-challenges that referenced this pull request May 18, 2026
Mirrors the Intermediate cleanup (8bcf885) on Expert, plus picks up the
targetingKey + PII discipline that was deferred from Intermediate.

- Rewrite Objective as 5 outcome-based bullets β€” drop the
  mechanism-heavy list, drop the parenthetical "verified: SpeciesInterceptor
  wires userId" note (now redundant: targetingKey lives at the
  implementation level here, not the objective level).
- Drop the "Concepts you'll touch" section. Its load-bearing content
  migrates inline to the per-step instructions: TracerProvider vs
  MeterProvider gloss into 4a, TracesHook/MetricsHook gloss into 4b,
  the ContextSpanHook authoring guide into a new 4c, and the
  fractional + targetingKey explanation into 4d.
- Add explicit step 4c "Author and register your own ContextSpanHook"
  β€” the ContextSpanHook was an objective bullet with no corresponding
  implementation step (analogous to the missing dose-passing step on
  Intermediate).
- Move the PII allowlist callout to step 4c β€” Expert is where it earns
  its place, since eval context is about to flow onto OTel spans that
  ship to SIEM-grade backends. The Intermediate cross-link goes away;
  the discipline lives here standalone.
- Lift "Start the Lab" out of step 1 into its own step 2 β€” mirrors the
  Intermediate / Beginner shape, so a player who clicks the Ports tab
  before reading further doesn't see a 502.
- Format Deadline + Community thread sections as Coming Soon callouts,
  matching Intermediate.
- Sync verify.sh OBJECTIVE block to the new outcome-based docs.

Addresses Katharina's review themes carried over from off-on-dev#43 (objective
shape, Concepts vs Learn overlap, verifier exercises objective).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon Schrottner <simon.schrottner@gmail.com>
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.

2 participants