Skip to content

feat(demo): chapters 2-5 + typed selector registry (Pillar-1 slice 1.3)#153

Merged
Luis85 merged 12 commits into
developfrom
claude/plan-pre-v1-increment-dIGEH
Apr 27, 2026
Merged

feat(demo): chapters 2-5 + typed selector registry (Pillar-1 slice 1.3)#153
Luis85 merged 12 commits into
developfrom
claude/plan-pre-v1-increment-dIGEH

Conversation

@Luis85
Copy link
Copy Markdown
Owner

@Luis85 Luis85 commented Apr 26, 2026

Summary

  • Pillar-1 slice 1.3 of the pre-v1 demo evolution increment.
  • Wires chapters 2-5 end-to-end on top of the chapter-1 vertical landed in feat(demo): chapter-1 vertical + bridge swap (Pillar-1 slice 1.2b) #150: <TracePanel>, cognition picker in <HudPanel>, JSON-preview placeholder, and <ExportImportPanel> all emit the synthetic UI events that drive their chapter predicates. The composed graph (petCareWalkthroughGraph) now runs all five chapters in sequence; defineWalkthroughGraph(...) validation catches typos in nextOnComplete chains at module-load time.
  • Closes the selector-handle union (spec P1-FR-4): RegisteredHandle in examples/product-demo/src/stores/view/selectorHandles.ts is now the single source of truth. useSelectorRegistry is generic over it and the new useRegisterSelector(handle) composable wraps the data-attribute lookup pattern. A renamed literal in selectorHandles.ts becomes a tsc error at every chapter + component referencing it (manually verified by spot-renaming 'hud.needs' → typecheck flagged 10 sites; reverted).
  • Adds /tour/:step routing (P1-FR-6): a slim TourView.vue wraps PlayView and reconciles the URL with useTourProgress.lastStep via new currentStepRoutePath / syncRoute(router) / resumeFromRoute(stepId) actions. resumeFromRoute is forward-only — a hard reload at /tour/<earlier-step> does not rewind past the persisted cursor.
  • New predicate primitives (P1-FR-3 follow-on): eventEmittedSinceStep(type) and ticksSinceStepAtLeast(n) read a new stepBaselineTick field on TourCtx populated by useTourProgress. The baseline rebases to 0 when session.tickIndex resets, so chapter-5 import reliably fires on the post-rebuild event buffer (export → import → snapshot rebuild → predicate fires).
  • Reset hygiene (P1-FR-7): useAgentSession.replayFromSnapshot(null) now provably leaves useTourProgress.lastStep / completedAt / skipped untouched. Covered by a new test at test/stores/view/useTourProgress.test.ts.
  • <TourOverlay> surfaces both Skip and Restart buttons (P1-FR-5) and re-evaluates predicates on recentEvents.length changes in addition to tickIndex, so UI events advance the tour without per-component imperative tour.next() calls.

Chapter-4 placeholder

Pillar-4 owns the proper preview/commit dual-action flow against useConfigDraft + the editor view. Until that ships, slice 1.3 provides a single placeholder "🛠️ Preview JSON" button in <HudPanel> that emits ConfigPreviewOpened so the walkthrough can advance. When Pillar-4 slice 4.3 lands, this chapter's step content stays valid: the real editor will emit the same event, the placeholder button is removed, and the predicate keeps working without modification.

Verification

  • npm run verify (format:check + lint + lint:demo + typecheck + 645 tests + lib build + typedoc) green.
  • cd examples/product-demo && npm run build (Vite production) green.
  • Compile-time enforcement spot check passed (rename → tsc errors at every consumer; reverted).

Out of scope

  • Playwright tour-happy-path.spec.ts — slice 1.4.
  • Real cognitionSwitcher.ts port with loss sparkline + prediction strip — Pillar-2 slice 2.5; this slice ships a minimal cognition <select> placeholder that calls useAgentSession.setCognitionMode(...) (probes peer + swaps reasoner).
  • Real JSON preview/commit editor — Pillar-4 slice 4.3.

Tracks: #132

Test plan

  • npm run verify green (645 tests).
  • cd examples/product-demo && npm run build green.
  • Compile-time enforcement spot check (rename a RegisteredHandle literal → tsc errors at every consumer; revert).
  • Manual: load the demo, walk through chapters 1-5 end-to-end. Each chapter advances when its predicate fires; URL tracks the cursor. Reload mid-tour at /tour/<step> → cursor resumes. Reset preserves cursor; Skip advances + records; Restart returns to chapter-1 step-1.
  • Manual chapter-3 fallback: with mistreevous / js-son / tfjs unavailable, the cognition <select> renders those modes disabled with an install hint and the chapter still advances when an available alternative is picked.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 2 commits April 26, 2026 22:22
Composes the full pre-v1 walkthrough graph: chapter-1 (autonomy) now
threads into chapter-2 (trace visibility), chapter-3 (cognition swap +
observe), chapter-4 (JSON-preview placeholder), and chapter-5
(deterministic replay export → import). Each chapter ships as a
standalone step factory under `demo-domain/walkthrough/chapters/`,
composed in `petCareGraph.ts` via `defineWalkthroughGraph(...)` whose
existing validation catches typos in `nextOnComplete` chains.

Closes the selector-handle union (spec P1-FR-4): `RegisteredHandle`
in `stores/view/selectorHandles.ts` is now the single source of truth;
`useSelectorRegistry` is generic over it and `useRegisterSelector(...)`
is the composable that components call to bind the handle. A renamed
literal in `selectorHandles.ts` becomes a `tsc` error at every chapter
+ component referencing it (manually verified).

Adds `/tour/:step` routing (P1-FR-6): a slim `TourView.vue` wraps
`PlayView` and reconciles the URL with `useTourProgress.lastStep`
via new `currentStepRoutePath` / `syncRoute(router)` /
`resumeFromRoute(stepId)` actions. `resumeFromRoute` is forward-only
so a hard reload at `/tour/<earlier-step>` doesn't rewind past the
persisted cursor.

Predicate primitives gain `eventEmittedSinceStep(type)` and
`ticksSinceStepAtLeast(n)`, both reading a new `stepBaselineTick`
field on `TourCtx` populated by `useTourProgress`. Baseline rebases
to 0 when `session.tickIndex` resets so chapter-5 import reliably
fires on the post-rebuild event buffer.

`useAgentSession` gains `setCognitionMode(modeId)` (probes peer dep,
constructs reasoner, calls `agent.setReasoner`, records
`CognitionModeChanged` UI event) plus `recordUiEvent(type)` for
synthetic UI signals consumed by chapters 2/4/5 (`TracePanelOpened`,
`ConfigPreviewOpened`, `SnapshotExported`, `SnapshotImported`).

`<TourOverlay>` surfaces both Skip and Restart controls and now
re-evaluates predicates on every `recentEvents` change (not just
`tickIndex`), so UI events advance the tour without per-component
imperative `tour.next()` calls. Reset (`replayFromSnapshot(null)`)
preserves cursor / completedAt / skipped (P1-FR-7); covered by a new
hygiene test.

Chapter-4 ships as a placeholder until Pillar-4 lands the proper
preview/commit editor — a "Preview JSON" button in `<HudPanel>`
emits `ConfigPreviewOpened` and the predicate keeps working when
Pillar-4 swaps in the real editor.

Tracks: #132

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Slice 1.3 row in the guided-walkthrough plan flips to ✅ shipped with
the PR link, and the planning doc's Tracker table for the "Guided
walkthrough" pillar now lists every shipped slice.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a3c435b644

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +285 to +288
const reasoner = await mode.construct();
agent.value.setReasoner(reasoner);
cognitionModeId.value = modeId;
recordUiEvent('CognitionModeChanged');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reset cognition mode when rebuilding the agent

setCognitionMode updates cognitionModeId, but neither init() nor replayFromSnapshot() resets it when they construct a fresh agent (which starts on the default heuristic reasoner). After a user switches modes and then resets/imports/new-pet, the UI and tour predicates read a stale mode id (not(cognitionModeIs('heuristic')) becomes true immediately), so chapter-3 can auto-advance without an actual cognition switch and the HUD reports the wrong active mode.

Useful? React with 👍 / 👎.

Comment on lines +117 to +119
(next, prev) => {
if (next < prev) baselineTickIndex.value = next;
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Persist baseline rebase after tick-index resets

When session.tickIndex drops (reset/replay), the watcher rebases baselineTickIndex in memory but never calls persist(). If the page reloads before another action that persists progress, storage still contains the old baseline, so eventEmittedSinceStep/ticksSinceStepAtLeast evaluate against stale pre-reset ticks and can incorrectly block progression until the tick counter catches up.

Useful? React with 👍 / 👎.

Comment on lines +18 to +19
watch([() => session.tickIndex, () => session.recentEvents.length], () => {
tour.next();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Re-evaluate on event writes, not recentEvents.length

The overlay re-checks predicates by watching session.recentEvents.length, but the event buffer is capped at 50 and recordUiEvent trims immediately after push, so once full the length often stays unchanged. In that state, UI events like TracePanelOpened/SnapshotExported do not trigger tour.next() unless a tick also changes, which breaks event-driven progression while paused and makes step advancement depend on unrelated ticking.

Useful? React with 👍 / 👎.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 26, 2026

Coverage report

Metric This PR vs base Floor Status
statements 87.12% ⬆️ +0.45pp 74% ⚠️ 13.1pp above floor — consider re-baselining
branches 77.25% ⬆️ +0.20pp 64% ⚠️ 13.3pp above floor — consider re-baselining
functions 91.05% ⬆️ +0.64pp 83% ⚠️ 8.0pp above floor — consider re-baselining
lines 89.53% ⬆️ +0.64pp 75% ⚠️ 14.5pp above floor — consider re-baselining

Floors live in scripts/coverageThresholds.mjs (drift envelope 5pp). Re-baseline by editing that file when ⚠️ appears above; cite the new measured value + commit SHA.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 26, 2026

size-limit report 📦

Path Size
dist/index.js (gzip) 37.86 KB (0%)
dist/integrations/excalibur/index.js (gzip) 1.4 KB (0%)
dist/cognition/adapters/mistreevous/index.js (gzip) 1.14 KB (0%)
dist/cognition/adapters/js-son/index.js (gzip) 1.36 KB (0%)
dist/cognition/adapters/tfjs/index.js (gzip) 8.74 KB (0%)

claude and others added 2 commits April 26, 2026 22:31
Three issues raised by Codex on PR #153:

1. (P1) **Reset cognitionModeId on agent rebuild.** `init()` and
   `replayFromSnapshot()` build a fresh `Agent` on the default
   heuristic reasoner but kept the previous `cognitionModeId`. After
   a mode swap + reset/import, chapter-3's
   `not(cognitionModeIs('heuristic'))` predicate would auto-fire and
   the HUD readout reported the wrong active mode. Both paths now
   reset `cognitionModeId.value = 'heuristic'` alongside the other
   per-rebuild resets.

2. (P2) **Persist baselineTickIndex after the rebase.** The watcher
   that detects `session.tickIndex` falling (snapshot replay) updated
   the baseline in memory but never called `persist()`. A reload
   between the rebase and the next explicit cursor move would restore
   the pre-reset baseline from localStorage and break
   `eventEmittedSinceStep` / `ticksSinceStepAtLeast`. Watcher now
   persists immediately after the rebase.

3. (P2) **Re-evaluate predicates on event writes, not buffer
   length.** `recentEvents` is capped at 50 and trimmed on every
   overflow push, so `recentEvents.length` saturates and
   `<TourOverlay>`'s length watcher silently misses UI events once
   the buffer is full — `TracePanelOpened` / `SnapshotExported`
   would fail to advance the tour while paused. Added a monotonic
   `recentEventsVersion` ref bumped on every push (both internal
   AGENT_TICKED listener and `recordUiEvent`); the overlay now
   watches that counter alongside `tickIndex`.

Tests cover all three: cognition reset on init + replayFromSnapshot,
recentEventsVersion bumping past the 50-event cap, and persisted
baselineTickIndex after replay.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a5ffd36db

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// fired before the user reached the step. Persisted alongside the
// cursor so a reload mid-step doesn't reset the baseline (which
// would make e.g. "wait 3 ticks" succeed instantly on resume).
const baselineTickIndex = ref<number>(persisted?.baselineTickIndex ?? 0);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Rebase step baseline when restoring persisted progress

baselineTickIndex is restored directly from local storage, but PlayView always calls session.init(...) on load, which resets session.tickIndex to 0. When a user reloads on /tour/<step> in chapters 2–5, eventEmittedSinceStep/ticksSinceStepAtLeast compare against a stale pre-reload baseline and can reject valid post-reload actions until the tick counter catches up to the old value, effectively stalling progression after resume. Rebase/clamp the restored baseline to the current session tick on startup.

Useful? React with 👍 / 👎.

Comment on lines +301 to +303
const reasoner = await mode.construct();
agent.value.setReasoner(reasoner);
cognitionModeId.value = modeId;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Guard async cognition switches against stale completions

setCognitionMode awaits probe() and construct() and then unconditionally applies the result to agent.value. If the agent is rebuilt (init/replayFromSnapshot) or the user triggers another mode change while the first request is in flight, the older request can finish later and overwrite the newer state, producing the wrong active reasoner/mode and emitting a misleading CognitionModeChanged event. Capture/validate the target agent (or a request token) before applying the result.

Useful? React with 👍 / 👎.

…le completions

Two follow-up issues raised by Codex on PR #153:

1. (P1) **Rebase step baseline when restoring persisted progress**
   (`useTourProgress.ts`). On a hard reload at `/tour/<step>`,
   `PlayView` calls `session.init(...)` which resets
   `session.tickIndex` to 0, but the persisted `baselineTickIndex`
   still carries the pre-reload value. Predicates
   (`eventEmittedSinceStep`, `ticksSinceStepAtLeast`) would reject
   valid post-reload events until the tick counter caught up.
   Clamp the restored baseline to `min(persisted, session.tickIndex)`
   on store construction.

2. (P2) **Guard async cognition swaps against stale completions**
   (`useAgentSession.ts`). `setCognitionMode` awaits `probe()` and
   `construct()` and unconditionally applied the result. A parallel
   `init()` / `replayFromSnapshot()` / second `setCognitionMode()`
   could land while those promises were in flight, causing the older
   request's `setReasoner` to overwrite the newer state and emit a
   misleading `CognitionModeChanged`. Added a monotonic
   `cognitionToken` bumped on every agent rebuild + at the start of
   each swap; both await points now drop their result if either the
   token has moved or `agent.value` no longer matches the captured
   `targetAgent`.

Tests cover both: a localStorage-seeded baseline of 15 clamps to 0
when the fresh session starts at tick 0, and a `setCognitionMode`
race that calls `init()` mid-flight does not invoke `setReasoner` on
the discarded agent or emit a stray `CognitionModeChanged`.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

tour.restart();
tour.skip();

P1 Badge Complete intro "Skip" flow instead of skipping one step

This CTA no longer does what its label promises after the tour expanded beyond one step: skipTour() calls restart() and then a single skip(), which now only advances from chapter 1 to chapter 2. Because completedAt stays null, TourOverlay still renders on /play, so users who click “Skip to free play” still get guided steps. The skip action here should mark the whole tour complete (or iterate until completion) before routing to /play.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

title: observeCopy.title,
hint: observeCopy.hint,
highlight: COGNITION_INDICATOR_HANDLE,
completionPredicate: eventEmittedSinceStep('AgentTicked'),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gate chapter-3 observe on elapsed ticks, not tick events alone

Using only eventEmittedSinceStep('AgentTicked') lets this step complete while simulation time is paused, because useAgentSession still records AgentTicked events at timeScale === 0 even though tickIndex does not advance. In that paused scenario, users can satisfy this step without observing a real post-switch decision tick, which breaks the chapter’s intended behavior; this predicate should also require positive tick progression (e.g., ticksSinceStepAtLeast(1)).

Useful? React with 👍 / 👎.

Two follow-up issues raised by Codex on PR #153:

1. (P1) **"Skip to free play" must end the entire tour, not just
   chapter 1.** `IntroView.skipTour()` was written when chapter 1 was
   the only chapter, so a single `skip()` set `completedAt`. With
   chapters 1-5 wired, that single `skip()` only advanced chapter 1
   → chapter 2 and left `completedAt === null`, so `<TourOverlay>`
   still rendered on `/play`. Added a `complete()` action on
   `useTourProgress` that walks every remaining step into `skipped`
   and sets `completedAt` in one persisted shot; `skipTour()` now
   calls `restart() + complete()`. The action is bounded by the
   graph step count so a future cyclic-graph mistake short-circuits.

2. (P2) **Chapter-3 observe must require virtual-time progression,
   not just an `AgentTicked` event.** `useAgentSession` records
   `AgentTicked` events at `timeScale === 0` so the trace panel
   keeps refreshing on paused frames, but `tickIndex` does not
   advance. The previous predicate
   (`eventEmittedSinceStep('AgentTicked')` only) auto-completed the
   chapter while paused, never showing the user a real post-switch
   decision tick. Combined with `ticksSinceStepAtLeast(1)` so the
   chapter only fires after virtual time has actually advanced.

Tests cover both: a `complete()` test asserts every authored step
ends up in `skipped` and `completedAt` is persisted; a chapter-3
test triple covers paused-tick rejection, virtual-time-advance
fire, and AgentTicked-required behaviour.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8bba87add0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (next === null) return;
const here = router.currentRoute.value.fullPath;
if (here === next) return;
if (!here.startsWith('/tour/')) return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Sync /tour root to a concrete step route

The route is declared as '/tour/:step?', but syncRoute only runs when fullPath starts with '/tour/', so '/tour' is treated like a non-tour route. In that case (e.g., bookmarked/manual '/tour' entry), the tour cursor can advance while the URL never updates to '/tour/<step>', which breaks the step-specific resume/share behavior this feature adds.

Useful? React with 👍 / 👎.

Codex P2 follow-up on PR #153. The tour route is declared
`/tour/:step?`, so the bare `/tour` (bookmarked / hand-typed) is also
a tour entry. `syncRoute` was checking `here.startsWith('/tour/')`
which excluded the bare `/tour`, so the cursor could advance while
the URL never upgraded to `/tour/<step>` — breaking step-specific
resume + share.

Also accept `here === '/tour'`. Bare `/tour` now gets pushed to the
concrete step path on first sync; deep-link share + reload-resume
work from the bare entry too.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b836a8dd5e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +33 to +37
watch(
() => tour.lastStep,
() => {
void tour.syncRoute(router);
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle /tour/:step param updates after mount

This view only reacts to tour.lastStep, so if the user navigates between tour URLs while TourView stays mounted (e.g., browser back/forward from /tour/chapter-3... to /tour/chapter-2...), resumeFromRoute is never re-run and the store cursor remains on the old step. That leaves the URL and active walkthrough step out of sync until some later cursor change, breaking the route-resume contract for in-session navigation.

Useful? React with 👍 / 👎.

Codex P2 follow-up on PR #153. `<TourView>` only ran the URL → cursor
reconciliation on mount, so browser back/forward between
`/tour/<step-a>` and `/tour/<step-b>` (with the view staying mounted)
left the active walkthrough step out of sync with the URL.

Extracted the mount-time block into `reconcileFromRoute()` and added a
`watch(() => route.params['step'], reconcileFromRoute)` so any
in-session URL change re-runs `resumeFromRoute(stepId)` (forward-only)
followed by `syncRoute(router)` to snap the URL back to the cursor
when the URL is upstream of the persisted progress.

Coverage notes: the deep-link mount-time path is verified by two
tests (downstream URL fast-forwards the cursor; upstream URL leaves
the persisted cursor put). The browser-back/forward path that
exercises the new watcher relies on vue-router reactivity through
`<router-view>`; under VTU + jsdom this only flushes reliably with
`<router-view>` mounted as the test root, but even then the watcher
chain (route param → resume → syncRoute → router.push) doesn't
settle inside two `await flushPromises()` ticks. Slice 1.4's
Playwright `tour-happy-path.spec.ts` will exercise the
back/forward path in a real browser.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
@Luis85
Copy link
Copy Markdown
Owner Author

Luis85 commented Apr 26, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 91e6833708

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// The fresh agent boots on the default heuristic reasoner; sync
// the readout (and chapter-3 predicate) so a previously-selected
// mode doesn't ghost across a reset / import.
cognitionModeId.value = 'heuristic';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve cognition mode across snapshot imports

When a user reaches chapter 3 and switches to a non-heuristic mode, importing an exported snapshot via replayFromSnapshot(snapshot) rebuilds a fresh default agent and then unconditionally forces cognitionModeId back to 'heuristic'. That means the run after import no longer uses the same decision policy as the exported run, so replayed behavior can diverge even with the same seed/state, undermining the deterministic replay flow in chapter 5. Reapply the active cognition mode (or persist/restore it) on snapshot imports instead of always resetting to heuristic.

Useful? React with 👍 / 👎.

Codex P1 follow-up on PR #153. `replayFromSnapshot(snapshot)`
unconditionally reset `cognitionModeId` to `'heuristic'` after
rebuilding the agent, so a chapter-5 import overwrote the user's
selected reasoner — the replayed run no longer used the same
decision policy as the exported run, undermining deterministic
replay.

Capture `cognitionModeId.value` BEFORE the rebuild. The reset path
(`snapshot === null`) still drops it to `'heuristic'`. The import
path (`snapshot !== null`) re-applies the captured mode by awaiting
`setCognitionMode(previousMode)` after the agent swap so the fresh
agent runs the same reasoner the export was made under. If the peer
dep is no longer available (uninstalled between export and import),
the inner `setCognitionMode` throws and we swallow it: the import
itself succeeds, `cognitionModeId` reflects the agent's actual
reasoner (`'heuristic'`), and the user can retry the swap manually
via the HUD picker.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 096e6dfe99

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

title: traceOpenCopy.title,
hint: traceOpenCopy.hint,
highlight: TRACE_PANEL_HANDLE,
completionPredicate: eventEmittedSinceStep('TracePanelOpened'),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Accept already-visible trace panel for trace-open step

The trace-open step only checks eventEmittedSinceStep('TracePanelOpened'), but TracePanel restores visibility from demo.v2.trace.visible on mount and only emits TracePanelOpened on a hidden→visible toggle. In the common returning-user case where the panel is already open from a previous session, chapter 2 appears stuck until the user closes and re-opens the panel, which breaks the intended “open the trace panel” progression flow. Consider treating restored-visible state as satisfied (or emitting the event on mount when restored visible) so chapter 2 can advance without a forced extra toggle.

Useful? React with 👍 / 👎.

Codex P2 follow-up on PR #153. `<TracePanel>` only emitted
`TracePanelOpened` on a hidden→visible toggle, but
`demo.v2.trace.visible` may persist `true` from a previous session.
For returning users with the panel already open, chapter-2's
`trace-open` predicate would stall indefinitely until they toggled
the panel off and back on.

Emit `TracePanelOpened` once in `onMounted` when `visible.value` is
true (restored), so the predicate sees the signal as soon as the
component mounts. Hidden cold-start mounts stay quiet.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 862f6cba73

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

title: traceOpenCopy.title,
hint: traceOpenCopy.hint,
highlight: TRACE_PANEL_HANDLE,
completionPredicate: eventEmittedSinceStep('TracePanelOpened'),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Treat already-open trace panel as chapter-2 completion

Chapter-2 trace-open still blocks returning users whose trace panel is already visible, because this predicate only accepts TracePanelOpened events emitted at or after the step baseline tick. Fresh evidence: this patch now emits TracePanelOpened on TracePanel mount, but that mount event fires at tick 0 before chapter-2 starts, so eventEmittedSinceStep('TracePanelOpened') filters it out once the baseline advances in chapter-1 and the user must still close/re-open the panel to proceed.

Useful? React with 👍 / 👎.

Codex P2 follow-up on PR #153. The previous patch emitted
`TracePanelOpened` on `<TracePanel>` mount when the panel was
restored visible, so a returning user's preference would surface as
a UI event. But chapter-2's predicate was step-scoped
(`eventEmittedSinceStep('TracePanelOpened')`), and the mount event
fires at tick 0 — before chapter-2 starts — so the step baseline
would advance past it and the predicate would still filter the
event out. The returning user was still forced to close + reopen
the panel.

Switch the trace-open predicate to session-scoped
(`eventEmittedSince('TracePanelOpened', 0)`) so any
`TracePanelOpened` since session init counts. Cold-start users who
have never opened the panel still need to toggle (no event in
buffer); returning users with the panel restored visible advance
without the forced extra toggle.

Chapter-2 step-2 (`trace-observe`) stays step-scoped because the
dwell-tick semantics are about elapsed time after the user reached
THIS step, not session totals.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2106129ab5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

title: traceOpenCopy.title,
hint: traceOpenCopy.hint,
highlight: TRACE_PANEL_HANDLE,
completionPredicate: eventEmittedSince('TracePanelOpened', 0),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require trace-open action to occur in chapter 2

Using eventEmittedSince('TracePanelOpened', 0) lets chapter-2 step trace-open pass from any historical open in the current session, even if the panel is currently hidden. A user who opened then closed the trace panel before reaching chapter 2 will auto-advance without actually reopening it, and trace-observe can then complete while the panel stays closed, which breaks the intended walkthrough behavior for this chapter.

Useful? React with 👍 / 👎.

Comment on lines 227 to 231
completedAt.value = null;
skipped.value = [];
lastStep.value = graph.firstStepId;
baselineTickIndex.value = session.tickIndex;
clearPersisted();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reset session evidence when restarting the tour

restart() only rewinds tour cursor state, but it keeps the existing session tick/event history intact. Since chapter-1 completion still depends on session-lifetime signals (tickAtLeast and eventEmittedSince(..., 0)), restarting after the app has already ticked will immediately re-satisfy chapter 1 on the next overlay evaluation, so the user is pushed back to chapter 2 almost instantly instead of actually replaying from chapter 1.

Useful? React with 👍 / 👎.

Two Codex P2 follow-ups on PR #153:

1. **Chapter-2 trace-open requires panel currently visible.** The
   previous fix used `eventEmittedSince('TracePanelOpened', 0)` to
   handle returning users with restored-visible panels, but a user
   who opened-then-closed the panel before reaching chapter-2 would
   still auto-advance from the historical open event. Added a new
   `flagOpen(openType, closeType)` predicate that scans recentEvents
   in reverse to find the latest matching event of either type — true
   iff the most recent is `openType`. Wired `<TracePanel>` to emit
   both `TracePanelOpened` (hidden→visible, mount-when-restored-visible)
   AND `TracePanelClosed` (visible→hidden), so the predicate models
   "panel currently visible" through the shared event stream.

2. **Chapter-1 step-scoped so restart() honestly replays.** Chapter-1
   used session-lifetime predicates (`tickAtLeast(3)`,
   `eventEmittedSince(AGENT_TICKED, 0)`). After a long session the
   buffer is full of historical AgentTicked events at high tickIndex,
   so `tour.restart()` would auto-satisfy the chapter immediately and
   push the user to chapter-2 without an actual replay-from-the-start
   experience. Switched both predicates to step-scoped variants
   (`ticksSinceStepAtLeast(3)`, `eventEmittedSinceStep(AGENT_TICKED)`)
   so the step waits for fresh evidence after restart's baseline rebase.

Tests cover both: chapter-2 has open / close / re-open scenarios
hitting `flagOpen`; chapter-1 has a long-session restart scenario
that asserts the predicate stays false until fresh ticks land.

Tracks: #132

https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7
@Luis85 Luis85 merged commit ece9198 into develop Apr 27, 2026
25 checks passed
@Luis85 Luis85 deleted the claude/plan-pre-v1-increment-dIGEH branch April 27, 2026 07:28
@Luis85 Luis85 added the roadmap:v1-demo Pre-v1 product-demo evolution: walkthrough, cognition diff, fingerprint, editor, second scenario label May 5, 2026
@Luis85 Luis85 mentioned this pull request May 11, 2026
15 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

roadmap:v1-demo Pre-v1 product-demo evolution: walkthrough, cognition diff, fingerprint, editor, second scenario

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants