While working on lesson 3 ("flip on g in the flags bar") it became clear that:
The starter-flags pre-population is systemic, not lesson-3-only. Every challenge lesson opened with requiredFlags already enabled, so any instruction reading "turn on X" was a no-op the moment the lesson loaded. Examples spotted: 40102 (g), 40103 (gi), every chapter that uses g, 40502 (gm), 41103 (s), 41207 (gm).
Hints were plain strings with no machine-readable handle on what substring or flag they were referring to, so the SPA couldn't offer hover-discoverability affordances (flash a substring in the test text, pulse a flag button) without re-parsing the prose.
This umbrella issue captures both fixes plus the full per-lesson audit. It supersedes #90, which was the lesson-3-specific symptom.
What landed
Phase 1 — Frontend systemic fix
Drop requiredFlags pre-population in reg-ex.component.ts (onLessonOpen). Every challenge lesson now opens with no flags enabled. The grader still consults RequiredFlags at submit, so correctness is unchanged; only the starting affordance changed.
Phase 2 — Backend hint data model
New records in RegexLessonPlan.cs: RegexLessonHint(Text, HighlightSpans?, HighlightFlags?) and HintHighlightSpan(Index, Length).
RegexLessonStrategyBase.BuildHints(Random) signature changed from IReadOnlyList<string> to IReadOnlyList<RegexLessonHint>.
New ergonomic helpers on the base: Hint(text, spans, flags), Spans(index, length), AllSpans(testText, needle).
BuiltAttempt.Hints (cross-language string contract) is preserved by mapping hints.Select(h => h.Text); the structured payload travels in RegexLessonPlan.Hints via the existing BrowserGradingState.TestCode JSON channel.
Phase 3 — Frontend wiring + hover affordances
Mirror types in regex-lesson-grader.service.ts: RegexLessonHint, HintHighlightSpan, plus hints? on RegexLessonPlan.
Lesson pane (regex-lesson-pane.component.*):
New structuredHints input + resolvedHints computed (falls back to plain strings for legacy lessons).
<li> per hint with (mouseenter) / (mouseleave) emitting hintHovered({hintIndex, spans, flags}) / hintHoverEnd.
buildHighlightedTextSegments rewritten as a breakpoint-merge sweep so live-match colours and hover-hint highlights compose cleanly into a single <span> list.
Flags bar binds [class.pulsing] against hoveredHintFlags().
With Phase 1 in place, every RequiredFlags lesson became actionable (no more pre-enabled flags). Every challenge lesson's BuildHints was migrated to the structured shape and enriched with HighlightSpans / HighlightFlags where the hint refers to specific substrings or flag keys. Conceptual hints (e.g., "a regex is just a sequence of characters") were left as plain Hint(text) calls with no metadata.
Per-lesson checklist (all complete with this issue):
Ch01 — Literals (Chapter01_Literals.cs): 40101, 40102 (the canary lesson — flag pulse + double-the highlight), 40103.
Ch02 — Special characters: 40201, 40202, 40203.
Ch03 — Character classes: 40301, 40302, 40303, 40304.
Ch04 — Quantifiers: 40401, 40402, 40403, 40404.
Ch05 — Anchors & boundaries: 40501, 40502 (pulse m), 40503.
No curriculum-pedagogy rule violations were found while migrating (no instruction asks for a token introduced after the lesson). No instruction text needed rewording — Phase 1 alone made every "turn on the X flag" instruction actionable.
Phase 5 — Tests + verification
dotnet test --filter FullyQualifiedName~Regex|FullyQualifiedName~Lesson: 1897 / 1897 passed (full backend suite green; the regex strategy curriculum smoke tests pass with the new hint shape and starter-flags semantics).
nx test feature-dev-tools-reg-ex: 104 / 104 passed including three new specs covering the hover-affordance plumbing (onHintHovered populates signals, hint-highlight overlay paints, hint span overlapping a live match keeps both classes on the same segment).
nx build spikersoft -c production: succeeds. The lazy regex feature chunk is ~115 KB, well under the inventory baseline (1.43 MB main / 302.58 KB gz).
Every challenge lesson opens with g (and any other required flag) off.
Submitting a challenge lesson still requires the correct flags (grader unchanged).
Hovering a hint with HighlightSpans flashes the matching substrings in the test text.
Hovering a hint with HighlightFlags pulses the matching flag-toggle button(s).
prefers-reduced-motion: reduce disables the animations but keeps a static visual cue.
All 57 regex lessons compile, ship, and pass curriculum smoke tests.
No bundle regression beyond the established baseline.
Notes for future work
The structured-hint shape is generic enough to add a third kind of metadata later (e.g., highlight a substring of the pattern bar, not the test text) without a wire-shape change. Just extend RegexLessonHint.
Tutorial-kind lessons still ship plain string hints via BuiltAttempt.Hints. The pane falls back to those gracefully — no migration needed for tutorials.
## Background
While working on lesson 3 ("flip on **g** in the flags bar") it became clear that:
1. The starter-flags pre-population is **systemic**, not lesson-3-only. Every challenge lesson opened with `requiredFlags` already enabled, so any instruction reading "turn on X" was a no-op the moment the lesson loaded. Examples spotted: 40102 (`g`), 40103 (`gi`), every chapter that uses `g`, 40502 (`gm`), 41103 (`s`), 41207 (`gm`).
2. Hints were plain strings with no machine-readable handle on what substring or flag they were referring to, so the SPA couldn't offer hover-discoverability affordances (flash a substring in the test text, pulse a flag button) without re-parsing the prose.
This umbrella issue captures both fixes plus the full per-lesson audit. It supersedes [#90](https://git.spikersoft.com/spikerj/spikersoft-issues/issues/90), which was the lesson-3-specific symptom.
## What landed
### Phase 1 — Frontend systemic fix
- Drop `requiredFlags` pre-population in `reg-ex.component.ts` (`onLessonOpen`). Every challenge lesson now opens with **no flags enabled**. The grader still consults `RequiredFlags` at submit, so correctness is unchanged; only the starting affordance changed.
### Phase 2 — Backend hint data model
- New records in `RegexLessonPlan.cs`: `RegexLessonHint(Text, HighlightSpans?, HighlightFlags?)` and `HintHighlightSpan(Index, Length)`.
- `RegexLessonStrategyBase.BuildHints(Random)` signature changed from `IReadOnlyList<string>` to `IReadOnlyList<RegexLessonHint>`.
- New ergonomic helpers on the base: `Hint(text, spans, flags)`, `Spans(index, length)`, `AllSpans(testText, needle)`.
- `BuiltAttempt.Hints` (cross-language string contract) is preserved by mapping `hints.Select(h => h.Text)`; the structured payload travels in `RegexLessonPlan.Hints` via the existing `BrowserGradingState.TestCode` JSON channel.
### Phase 3 — Frontend wiring + hover affordances
- Mirror types in `regex-lesson-grader.service.ts`: `RegexLessonHint`, `HintHighlightSpan`, plus `hints?` on `RegexLessonPlan`.
- Lesson pane (`regex-lesson-pane.component.*`):
- New `structuredHints` input + `resolvedHints` computed (falls back to plain strings for legacy lessons).
- `<li>` per hint with `(mouseenter)` / `(mouseleave)` emitting `hintHovered({hintIndex, spans, flags})` / `hintHoverEnd`.
- Subtle `.has-hover-affordance` cue (cursor + tinted background).
- Parent (`reg-ex.component.*`):
- `hoveredHintSpans` + `hoveredHintFlags` signals.
- `buildHighlightedTextSegments` rewritten as a breakpoint-merge sweep so live-match colours and hover-hint highlights compose cleanly into a single `<span>` list.
- Flags bar binds `[class.pulsing]` against `hoveredHintFlags()`.
- CSS animations in `reg-ex.component.scss`:
- `.flag-toggle.pulsing` — 1.2s scale + glow pulse.
- `.test-highlight-layer span.hint-highlight` — 1.2s background-color flash + outline.
- Both honour `prefers-reduced-motion` (animation off, static glow/outline kept).
### Phase 4 — Per-lesson audit (all 57 lessons across 12 chapter files)
With Phase 1 in place, every `RequiredFlags` lesson became actionable (no more pre-enabled flags). Every challenge lesson's `BuildHints` was migrated to the structured shape and enriched with `HighlightSpans` / `HighlightFlags` where the hint refers to specific substrings or flag keys. Conceptual hints (e.g., "a regex is just a sequence of characters") were left as plain `Hint(text)` calls with no metadata.
Per-lesson checklist (all complete with this issue):
- [x] **Ch01 — Literals** (`Chapter01_Literals.cs`): 40101, 40102 (the canary lesson — flag pulse + double-`the` highlight), 40103.
- [x] **Ch02 — Special characters**: 40201, 40202, 40203.
- [x] **Ch03 — Character classes**: 40301, 40302, 40303, 40304.
- [x] **Ch04 — Quantifiers**: 40401, 40402, 40403, 40404.
- [x] **Ch05 — Anchors & boundaries**: 40501, 40502 (pulse `m`), 40503.
- [x] **Ch06 — Alternation**: 40601, 40602.
- [x] **Ch07 — Capturing groups**: 40701, 40702, 40703, 40704.
- [x] **Ch08 — Backreferences**: 40801, 40802, 40803.
- [x] **Ch09 — Replace & substitution**: 40901, 40902, 40903, 40904.
- [x] **Ch10 — Lookarounds**: 41001, 41002, 41003, 41004.
- [x] **Ch11 — Named groups, Unicode, misc**: 41101, 41102, 41103 (pulse `s`), 41104.
- [x] **Ch12 — Real-world recipes**: 41201, 41202, 41203, 41204, 41205, 41206, 41207.
No curriculum-pedagogy rule violations were found while migrating (no instruction asks for a token introduced after the lesson). No instruction text needed rewording — Phase 1 alone made every "turn on the X flag" instruction actionable.
### Phase 5 — Tests + verification
- `dotnet test --filter FullyQualifiedName~Regex|FullyQualifiedName~Lesson`: **1897 / 1897 passed** (full backend suite green; the regex strategy curriculum smoke tests pass with the new hint shape and starter-flags semantics).
- `nx test feature-dev-tools-reg-ex`: **104 / 104 passed** including three new specs covering the hover-affordance plumbing (`onHintHovered` populates signals, `hint-highlight` overlay paints, hint span overlapping a live match keeps both classes on the same segment).
- `nx build spikersoft -c production`: succeeds. The lazy regex feature chunk is ~115 KB, well under the inventory baseline (1.43 MB main / 302.58 KB gz).
### Phase 6 — Gitea housekeeping
- This umbrella issue.
- [#90](https://git.spikersoft.com/spikerj/spikersoft-issues/issues/90) closed with a superseded-by comment.
## Acceptance criteria
- [x] Every challenge lesson opens with `g` (and any other required flag) off.
- [x] Submitting a challenge lesson still requires the correct flags (grader unchanged).
- [x] Hovering a hint with `HighlightSpans` flashes the matching substrings in the test text.
- [x] Hovering a hint with `HighlightFlags` pulses the matching flag-toggle button(s).
- [x] `prefers-reduced-motion: reduce` disables the animations but keeps a static visual cue.
- [x] All 57 regex lessons compile, ship, and pass curriculum smoke tests.
- [x] No bundle regression beyond the established baseline.
## Notes for future work
- The structured-hint shape is generic enough to add a third kind of metadata later (e.g., highlight a substring of the **pattern** bar, not the test text) without a wire-shape change. Just extend `RegexLessonHint`.
- Tutorial-kind lessons still ship plain string hints via `BuiltAttempt.Hints`. The pane falls back to those gracefully — no migration needed for tutorials.
Verified all phases are present in current master (source-of-truth check):
Phase 1 (starter flags) — reg-ex.component.tsonLessonOpen now does this.flags.set("") with an inline comment pointing back to this umbrella issue; required flags are no longer pre-enabled, and the grader still consults them at submit.
Phase 2 (backend data model) — RegexLessonPlan.cs defines RegexLessonHint(Text, HighlightSpans?, HighlightFlags?) and HintHighlightSpan(Index, Length); RegexLessonStrategyBase.BuildHints returns IReadOnlyList<RegexLessonHint> with the Hint(...) / Spans(...) / AllSpans(...) helpers.
Phase 3 (frontend wiring + hover affordances) — regex-lesson-pane.component.ts exposes structuredHints, resolvedHints, hintHovered, hintHoverEnd (with the legacy plain-string fallback); regex-lesson-grader.service.ts mirrors the hint types; reg-ex.component.scss ships .flag-toggle.pulsing + span.hint-highlight animations, both guarded by @media (prefers-reduced-motion: reduce).
Phase 4 (per-lesson audit) — all 12 Chapter01..Chapter12 files are present and use the structured hint shape; e.g. the canary lesson 40102 in Chapter01_Literals.cs uses Hint(..., spans: AllSpans("the cat sat on the mat", "the"), flags: new[] { "g" }).
All acceptance criteria in the description are satisfied by the merged code. Closing as completed; #90 was already superseded by this ticket.
Verified all phases are present in current `master` (source-of-truth check):
- **Phase 1 (starter flags)** — `reg-ex.component.ts` `onLessonOpen` now does `this.flags.set("")` with an inline comment pointing back to this umbrella issue; required flags are no longer pre-enabled, and the grader still consults them at submit.
- **Phase 2 (backend data model)** — `RegexLessonPlan.cs` defines `RegexLessonHint(Text, HighlightSpans?, HighlightFlags?)` and `HintHighlightSpan(Index, Length)`; `RegexLessonStrategyBase.BuildHints` returns `IReadOnlyList<RegexLessonHint>` with the `Hint(...)` / `Spans(...)` / `AllSpans(...)` helpers.
- **Phase 3 (frontend wiring + hover affordances)** — `regex-lesson-pane.component.ts` exposes `structuredHints`, `resolvedHints`, `hintHovered`, `hintHoverEnd` (with the legacy plain-string fallback); `regex-lesson-grader.service.ts` mirrors the hint types; `reg-ex.component.scss` ships `.flag-toggle.pulsing` + `span.hint-highlight` animations, both guarded by `@media (prefers-reduced-motion: reduce)`.
- **Phase 4 (per-lesson audit)** — all 12 `Chapter01..Chapter12` files are present and use the structured hint shape; e.g. the canary lesson 40102 in `Chapter01_Literals.cs` uses `Hint(..., spans: AllSpans("the cat sat on the mat", "the"), flags: new[] { "g" })`.
All acceptance criteria in the description are satisfied by the merged code. Closing as completed; #90 was already superseded by this ticket.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Background
While working on lesson 3 ("flip on g in the flags bar") it became clear that:
requiredFlagsalready enabled, so any instruction reading "turn on X" was a no-op the moment the lesson loaded. Examples spotted: 40102 (g), 40103 (gi), every chapter that usesg, 40502 (gm), 41103 (s), 41207 (gm).This umbrella issue captures both fixes plus the full per-lesson audit. It supersedes #90, which was the lesson-3-specific symptom.
What landed
Phase 1 — Frontend systemic fix
requiredFlagspre-population inreg-ex.component.ts(onLessonOpen). Every challenge lesson now opens with no flags enabled. The grader still consultsRequiredFlagsat submit, so correctness is unchanged; only the starting affordance changed.Phase 2 — Backend hint data model
RegexLessonPlan.cs:RegexLessonHint(Text, HighlightSpans?, HighlightFlags?)andHintHighlightSpan(Index, Length).RegexLessonStrategyBase.BuildHints(Random)signature changed fromIReadOnlyList<string>toIReadOnlyList<RegexLessonHint>.Hint(text, spans, flags),Spans(index, length),AllSpans(testText, needle).BuiltAttempt.Hints(cross-language string contract) is preserved by mappinghints.Select(h => h.Text); the structured payload travels inRegexLessonPlan.Hintsvia the existingBrowserGradingState.TestCodeJSON channel.Phase 3 — Frontend wiring + hover affordances
regex-lesson-grader.service.ts:RegexLessonHint,HintHighlightSpan, plushints?onRegexLessonPlan.regex-lesson-pane.component.*):structuredHintsinput +resolvedHintscomputed (falls back to plain strings for legacy lessons).<li>per hint with(mouseenter)/(mouseleave)emittinghintHovered({hintIndex, spans, flags})/hintHoverEnd..has-hover-affordancecue (cursor + tinted background).reg-ex.component.*):hoveredHintSpans+hoveredHintFlagssignals.buildHighlightedTextSegmentsrewritten as a breakpoint-merge sweep so live-match colours and hover-hint highlights compose cleanly into a single<span>list.[class.pulsing]againsthoveredHintFlags().reg-ex.component.scss:.flag-toggle.pulsing— 1.2s scale + glow pulse..test-highlight-layer span.hint-highlight— 1.2s background-color flash + outline.prefers-reduced-motion(animation off, static glow/outline kept).Phase 4 — Per-lesson audit (all 57 lessons across 12 chapter files)
With Phase 1 in place, every
RequiredFlagslesson became actionable (no more pre-enabled flags). Every challenge lesson'sBuildHintswas migrated to the structured shape and enriched withHighlightSpans/HighlightFlagswhere the hint refers to specific substrings or flag keys. Conceptual hints (e.g., "a regex is just a sequence of characters") were left as plainHint(text)calls with no metadata.Per-lesson checklist (all complete with this issue):
Chapter01_Literals.cs): 40101, 40102 (the canary lesson — flag pulse + double-thehighlight), 40103.m), 40503.s), 41104.No curriculum-pedagogy rule violations were found while migrating (no instruction asks for a token introduced after the lesson). No instruction text needed rewording — Phase 1 alone made every "turn on the X flag" instruction actionable.
Phase 5 — Tests + verification
dotnet test --filter FullyQualifiedName~Regex|FullyQualifiedName~Lesson: 1897 / 1897 passed (full backend suite green; the regex strategy curriculum smoke tests pass with the new hint shape and starter-flags semantics).nx test feature-dev-tools-reg-ex: 104 / 104 passed including three new specs covering the hover-affordance plumbing (onHintHoveredpopulates signals,hint-highlightoverlay paints, hint span overlapping a live match keeps both classes on the same segment).nx build spikersoft -c production: succeeds. The lazy regex feature chunk is ~115 KB, well under the inventory baseline (1.43 MB main / 302.58 KB gz).Phase 6 — Gitea housekeeping
Acceptance criteria
g(and any other required flag) off.HighlightSpansflashes the matching substrings in the test text.HighlightFlagspulses the matching flag-toggle button(s).prefers-reduced-motion: reducedisables the animations but keeps a static visual cue.Notes for future work
RegexLessonHint.BuiltAttempt.Hints. The pane falls back to those gracefully — no migration needed for tutorials.Verified all phases are present in current
master(source-of-truth check):reg-ex.component.tsonLessonOpennow doesthis.flags.set("")with an inline comment pointing back to this umbrella issue; required flags are no longer pre-enabled, and the grader still consults them at submit.RegexLessonPlan.csdefinesRegexLessonHint(Text, HighlightSpans?, HighlightFlags?)andHintHighlightSpan(Index, Length);RegexLessonStrategyBase.BuildHintsreturnsIReadOnlyList<RegexLessonHint>with theHint(...)/Spans(...)/AllSpans(...)helpers.regex-lesson-pane.component.tsexposesstructuredHints,resolvedHints,hintHovered,hintHoverEnd(with the legacy plain-string fallback);regex-lesson-grader.service.tsmirrors the hint types;reg-ex.component.scssships.flag-toggle.pulsing+span.hint-highlightanimations, both guarded by@media (prefers-reduced-motion: reduce).Chapter01..Chapter12files are present and use the structured hint shape; e.g. the canary lesson 40102 inChapter01_Literals.csusesHint(..., spans: AllSpans("the cat sat on the mat", "the"), flags: new[] { "g" }).All acceptance criteria in the description are satisfied by the merged code. Closing as completed; #90 was already superseded by this ticket.