feat(demo): chapter-1 vertical + bridge swap (Pillar-1 slice 1.2b)#150
Conversation
Pillar-1 slice 1.2b of the pre-v1 demo evolution increment.
- Wires `@vitejs/plugin-vue` (build + vitest test runtime).
- Swaps `app/main.ts` from the Wave-0 `await import('../main.js')` bridge
to `createApp(App).use(pinia).use(router).mount('#app')`. STO-3
legacy-key purge stays as the first action and now wipes the
`agentonomous/*` namespace too (pre-v1 clean break per design).
- Restructures `index.html` to a `<div id="app">` mount target — the
legacy DOM scaffold (#bars, #buttons, #seed, #pet, #decision-trace,
#species-config) is gone; SFCs build their own markup.
- Deletes legacy `src/{ui,traceView,seed,main}.ts`. `cognitionSwitcher.ts`,
`lossSparkline.ts`, `predictionStrip.ts`, `speciesConfig.ts` stay
(Pillar 2 slice 2.5 + Pillar 4 slice 4.3 own their deletion).
- Ports the legacy `mountHud` / `mountSpeedPicker` / `mountResetButton` /
`mountExportImport` / `mountTraceView` into Vue SFCs:
`<HudPanel>`, `<SpeedPicker>`, `<ResetButton>`, `<ExportImportPanel>`,
`<TracePanel>`. Reuses the `INTERACTION_BUTTONS` / `STAGE_LABELS` /
`NEEDS` data tables verbatim.
- Adds `<TourOverlay>` + `<StepHighlight>` against a `useSelectorRegistry`
view-store stub (full registry lands in slice 1.3).
- Adds `useTourProgress` view store with cursor / completedAt / skipped
+ persistence under `demo.v2.tour.progress`. Reads
`useAgentSession.sessionSnapshot` projection + the active route.
- Authors chapter-1 (autonomy) step content in
`demo-domain/walkthrough/chapters/1.ts`. Predicate combines
`tickAtLeast(3)` with `eventEmittedSince(AGENT_TICKED, 0)`.
- Settles OQ-P1: tour copy tone is **friendly-informal** (recorded in
the slice plan's Done log + applied to the chapter-1 hint).
- Extends `useAgentSession` with `tickIndex` / `recentEvents` /
`lastTrace` / `lastTickNumber` / `sessionSnapshot` projections so
the view layer never re-subscribes to AGENT_TICKED. Implements the
snapshot-restore branch of `replayFromSnapshot(snapshot)` —
`<ExportImportPanel>` calls it directly.
- Updates `eslint.config.js` ignores (drops the four deleted files)
and relaxes `no-restricted-imports` for `components/views/stores/view`
to permit `import type` from `agentonomous` and `demo-domain/**`
(runtime imports stay forbidden per design's DDD layering).
Storage-key clean break (per pre-v1 policy, not migrated): legacy
`agentonomous/seed`, `agentonomous/speed`, `agentonomous/trace-visible`,
`agentonomous/species-config`, `whiskers`, `whiskers:speed`. The new
shell uses `demo.v2.session.speed`, `demo.v2.trace.visible`, and
`demo.v2.tour.progress` exclusively.
Tracks: #132
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pillar-1 plan tracker: row 1.2b → ✅ shipped, linked to PR #150. Done log captures the OQ-P1 decision (friendly-informal tour copy) plus the four non-obvious mechanics that future-you / Codex will want to find quickly: - `@vitejs/plugin-vue@^6` wired with `isProduction: false` for vitest so template directives bind under @vue/test-utils; - `useAgentSession` projections (`tickIndex`, `recentEvents`, `lastTrace`, `lastTickNumber`, `sessionSnapshot`) keep view-layer SFCs subscription- free + the snapshot-restore branch of `replayFromSnapshot` actually restores now; - demo `no-restricted-imports` was relaxed to permit `import type` from `agentonomous` + `demo-domain/**` (runtime stays forbidden); - legacy `agentonomous/*` keys are wiped at first mount via the existing STO-3 purge; new shell uses the `demo.v2.*` namespace exclusively. Tracks: #132 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@codex review |
Coverage report
Floors live in |
size-limit report 📦
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aaea2bb3af
ℹ️ 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".
| onMounted(() => { | ||
| const seed = readPersistedSeed() ?? generateSeed(); | ||
| session.init({ seed }); | ||
| raf = globalThis.requestAnimationFrame((t) => { |
There was a problem hiding this comment.
Initialize session before mounting speed controls
Move session.init(...) earlier in the render lifecycle (or re-apply the saved speed after init), because Vue runs child onMounted hooks before the parent. SpeedPicker reads demo.v2.session.speed and applies it in its own onMounted, but this parent hook then calls session.init, which resets speedMultiplier to 1 and running to true; as a result, persisted speed (including persisted pause) is silently lost on every page load.
Useful? React with 👍 / 👎.
Vue runs child onMounted before parent. SpeedPicker.onMounted reads the persisted demo.v2.session.speed and applied it via session.pause()/setSpeed, but PlayView's onMounted then called session.init(...) — which resets speedMultiplier to 1 and running to true — silently discarding the saved pause/speed on every page load. Move session.init out of onMounted into the top-level <script setup> so it runs before any child component instantiates; the rAF loop stays in onMounted because it doesn't want to fire during SSR-style synchronous setup. Adds test/views/PlayView.test.ts covering pause / numeric / no-persisted cases. Codex P1 review on aaea2bb. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1342dee19a
ℹ️ 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 (event.type === AGENT_TICKED) { | ||
| tickIndex.value += 1; | ||
| const ticked = event as AgentTickedEvent; |
There was a problem hiding this comment.
Exclude paused ticks from tour progression counter
tickIndex is incremented for every AGENT_TICKED event, but the play loop still calls session.tick() while paused and Agent.tick() emits AGENT_TICKED even at timeScale=0. That means chapter-1’s tickAtLeast(3) predicate can be satisfied while the simulation is paused, so the tour can auto-complete without real autonomous progression. Please gate this counter on non-paused/positive virtual-dt ticks (or derive from an already gated signal).
Useful? React with 👍 / 👎.
| `Reset ${petName.value}? Lifetime stats and current state will be lost.`, | ||
| ); | ||
| if (ok !== true) return; | ||
| void session.replayFromSnapshot(null); |
There was a problem hiding this comment.
Clear HUD lifetime counters when reset is confirmed
This reset path only rebuilds the agent session; it does not clear the HUD’s in-component lifetime counters, which are only reset in HudPanel.newPet(). After using this button, the next death summary can include stats from the previous pet, contradicting the confirmation text that “lifetime stats … will be lost.” Reset should also clear those counters (or route through a shared reset action that does both).
Useful? React with 👍 / 👎.
…on reset Two Codex P2 findings on 1342dee: 1. useAgentSession: Agent.tick still emits AGENT_TICKED at timeScale=0 so trace panels can keep observing paused frames, but `tickIndex` was incremented on every emission — chapter-1's `tickAtLeast(N)` predicate could therefore satisfy while paused, silently auto-completing the tour without real progression. Gate the increment on `event.virtualDtSeconds > 0` (the agent's already- computed "did virtual time advance this tick" signal). Trace + tickNumber projections still update so TracePanel stays live. step() — which temporarily unpauses for one virtual tick — keeps counting, as it should. 2. HudPanel: ResetButton.reset → session.replayFromSnapshot(null) rebuilds the agent but did not clear the HUD's in-component lifetime counters (only HudPanel.newPet() did). After clicking Reset, the next death summary leaked counters from the previous pet, contradicting the confirmation prompt's "lifetime stats … will be lost." Add a watch on `session.agent` that clears counters + lifeSummary whenever the ref swaps, so any rebuild path (ResetButton, newPet, future scenario switches) routes through one place. newPet's manual clear becomes redundant and is removed. Adds regression coverage: - useAgentSession: tickIndex frozen across paused tick(0.1) calls, advances by 1 on step(). - HudPanel: counters + lifeSummary reset after replayFromSnapshot(null). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a9030a6d8
ℹ️ 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".
| agent.value = fresh; | ||
| setLearningAgent(fresh); |
There was a problem hiding this comment.
Defer session swap until snapshot restore succeeds
replayFromSnapshot replaces agent.value and rebinds listeners before awaiting fresh.restore(...). When an imported snapshot is syntactically valid JSON but semantically invalid, restore rejects and <ExportImportPanel> reports an import failure, yet the previous in-memory pet has already been discarded and replaced by a fresh one. This makes a failed import destructive; keep the current agent until restore succeeds (or rollback on failure).
Useful? React with 👍 / 👎.
| onMounted(() => { | ||
| const saved = readSaved(); | ||
| const valid = saved !== null && CHOICES.some((c) => c.mult === saved); | ||
| const initial: number | 'pause' = valid ? (saved as number | 'pause') : 1; | ||
| active.value = initial; |
There was a problem hiding this comment.
Resync speed picker after replay resets speed state
The speed picker's active state is initialized on mount and updated on button clicks only, but session replays (Reset and import) force the store back to speedMultiplier = 1/running = true without remounting this component. After replay, the UI can still show "pause" or "4×" while the simulation is actually running at 1×, which is misleading and can cause incorrect follow-up actions. Add a watcher on session speed/running (or equivalent sync hook) to keep active accurate.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5a9030a6d8
ℹ️ 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".
| speedMultiplier.value = 1; | ||
| running.value = true; |
There was a problem hiding this comment.
Preserve speed state when replaying/resetting the session
replayFromSnapshot() now unconditionally sets speedMultiplier to 1 and running to true, so Reset/New-pet/import flows silently discard the user’s current speed (including pause) and can leave the speed UI out of sync with the actual simulation rate until remount. This is a behavioral regression from the previous reset/import path, where speed preference was preserved across resets and imports.
Useful? React with 👍 / 👎.
| `Reset ${petName.value}? Lifetime stats and current state will be lost.`, | ||
| ); | ||
| if (ok !== true) return; | ||
| void session.replayFromSnapshot(null); |
There was a problem hiding this comment.
Clear persisted tfjs network on Reset
The reset button now only calls session.replayFromSnapshot(null) and no longer removes agentonomous/<agentId>/tfjs-network. Because learning-mode hydration reads that key (loadPersistedSnapshot in learning.ts), a user who trained the model and then presses Reset can still get the previously trained weights on the next learning-mode construct, which contradicts reset semantics of starting fresh.
Useful? React with 👍 / 👎.
…ve speed + clear tfjs network Four Codex review findings on 5a9030a, all rooted in useAgentSession.replayFromSnapshot: P1 #3144119465 — defer agent swap until restore succeeds. The previous shape replaced agent.value + rebound listeners BEFORE awaiting fresh.restore(snapshot). A semantically broken (but JSON-valid) import made restore reject AFTER the live pet had already been thrown out, so ExportImportPanel's "import failed" alert silently destroyed the user's session. Now the restore is awaited on the fresh agent first; on rejection the fresh instance is dropped and the live agent stays put, matching the legacy mountExportImport semantics. P1 #3144120027 — preserve speedMultiplier + running across replay. The previous code unconditionally reset both to 1/true, so Reset / New-pet / import flows clobbered the user's pause or 4× choice. They reflect UI state, not snapshot contents — keep them, and apply them to the fresh agent's setTimeScale right after the swap so the rebuilt agent runs at the same scale the picker is showing. P2 #3144119466 — speed picker resync after replay. With P1 #3144120027 fixed, the store no longer drifts during replay, so SpeedPicker's mount-time-initialized active ref stays correct without an explicit sync hook. The defense-in-depth shape (storeToRefs + computed/watch on running + speedMultiplier) was tried but trips a duplicate-Vue duplication issue in the test runner — root vite.config.ts has no `dedupe: ['vue', 'pinia']` for the test block, so the picker's in-component reactive scope and the test's session mutations live in different Vue copies; the watch fires (setupState.active mutates) but the renderer never repaints. Out of scope for this PR — left a comment in SpeedPicker.vue documenting the intended switch once the dedupe config lands. P2 #3144120028 — clear persisted tfjs network on Reset. Reset must mean "fresh start": move the agentonomous/<agentId>/tfjs-network localStorage clear into replayFromSnapshot's null/reset branch (NOT the import branch — imported state is intentionally inheriting). Same key the cognition switcher's Train and Untrain paths already use. Adds regression coverage in useAgentSession.test.ts: - speedMultiplier preserved across replayFromSnapshot(null) - running=false preserved across replayFromSnapshot(null) - tfjs-network localStorage key cleared by replayFromSnapshot(null) - replayFromSnapshot(snapshot) leaves the live agent untouched when restore rejects (vi.spyOn on Agent.prototype.restore) And a SpeedPicker test asserting the store contract (preserve speed) holds end-to-end through a click → replay sequence. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 828f23dfee
ℹ️ 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".
| const lastStep = ref<WalkthroughStepId>( | ||
| (persisted?.lastStep as WalkthroughStepId | undefined) ?? graph.firstStepId, | ||
| ); |
There was a problem hiding this comment.
Fallback to first step when persisted cursor is unknown
lastStep is restored from localStorage with a blind cast, so if a previously persisted step id is no longer present in graph.stepsById (for example after a step-id rename between releases), currentStep becomes null while completedAt remains null. In that state the overlay never renders and IntroView.startTour() won't call restart(), so users cannot re-enter the guided tour without manually clearing storage. Validate persisted.lastStep against the graph and default to firstStepId when missing.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 828f23dfee
ℹ️ 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".
| const lastStep = ref<WalkthroughStepId>( | ||
| (persisted?.lastStep as WalkthroughStepId | undefined) ?? graph.firstStepId, | ||
| ); |
There was a problem hiding this comment.
Fall back when persisted step id is unknown
Validate persisted.lastStep against graph.stepsById before restoring it. As written, any stale/corrupted value in demo.v2.tour.progress (for example after step-id changes between releases) leaves lastStep pointing to a missing node, so currentStep becomes null while completedAt is still null; then next()/skip() no-op and the guided flow can appear permanently stuck until storage is manually cleared.
Useful? React with 👍 / 👎.
Codex P2 #3144164103 / #3144166101 on 828f23d — useTourProgress was restoring `lastStep` from `demo.v2.tour.progress` with a blind cast. After a step-id rename between releases (or any other corrupted payload), the cursor resolved to `currentStep === null` while `completedAt` stayed null; the overlay then never rendered and `next()` / `skip()` no-op'd, leaving users with no in-app way to re-enter the guided tour short of clearing localStorage by hand. Validate `persisted.lastStep` against `graph.stepsById.has(...)` and fall back to `graph.firstStepId` when missing. Adds a regression test covering the stale-id payload path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
…3) (#153) ## 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 #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 - [x] `npm run verify` green (645 tests). - [x] `cd examples/product-demo && npm run build` green. - [x] 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](https://claude.com/claude-code) --- _Generated by [Claude Code](https://claude.ai/code/session_01TPggmKp12XqQdNjjMKVxd7)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
## Summary Resolves all 11 findings from the 2026-04-27 docs-review run (`d9b4b85`) tracked in #157: 5 MAJOR + 5 MINOR + 1 NIT. | ID | File | Severity | Fix | |----|------|----------|-----| | `d9b4b85.1` | `CLAUDE.md:53` | MAJOR | Add `lint:demo` + `docs` to `npm run verify` description | | `d9b4b85.2` | `CONTRIBUTING.md:144` | MAJOR | Same `npm run verify` alignment | | `d9b4b85.3` | `docs/PRODUCT_VISION.md:419` | MAJOR | Remove leaked `/root/.claude/plans/...` path | | `d9b4b85.4` | `examples/product-demo/README.md:109` | MAJOR | `src/main.ts` → `src/app/main.ts` (moved in #150) | | `d9b4b85.5` | `PUBLISHING.md:36-38` | MAJOR | Replace stale 5-job CI list with `CI gate (required check)` aggregator + current leaf-job reference | | `d9b4b85.6` | `docs/PRODUCT_VISION.md:3-4,~413,~415,~469` | MINOR | Remove dead `docs/specs/overview.md` + `docs/specs/roadmap.md` references (header, relationship section, review steps) | | `d9b4b85.7` | `docs/PRODUCT_VISION.md:417` | MINOR | Remove dead `docs/plans/review-remediation.md` link | | `d9b4b85.8` | `CONTRIBUTING.md:143` | MINOR | `R-XX` → `#NNN` (no R-XX scheme in this repo) | | `d9b4b85.9` | `CLAUDE.md:44` | MINOR | Drop hardcoded `D:\Projects\agent-library` path | | `d9b4b85.10` | `docs/plans/2026-04-26-pre-v1-demo-guided-walkthrough.md:20` | MINOR | Mark rename preflight as resolved (archived via #134) | | `d9b4b85.11` | `.claude/memory/project_pending_major_changesets.md:8` | NIT | Replace stale 4-changeset count with pointer to `.changeset/*.md` | ## Test plan - [x] `npm run verify` (format:check + lint + lint:demo + typecheck + test + build + docs) green - [x] No code changes — docs-only PR; behavior unchanged - [ ] Codex review on the PR is acknowledged or rebutted ## Notes - No changeset (docs-only). - Issue #157 uses the `docs-review` label and `<!-- d:... -->` markers, which the `review-fix-shipped` Action does not handle (it only matches `<!-- f:... -->` from the code-review bot). The owner ticks the boxes manually per `docs/docs-review-bot/README.md`. PR body therefore lists each finding ID for manual reconciliation rather than the `Refs # finding:` magic line. - Bundled all 11 findings into one PR per the "one PR per session" rule and the doc-only nature of the changes (each fix is a one-liner with no test surface). Refs #157 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Luis Mendez <hallo@luis-mendez.de> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
examples/product-demo/src/app/main.tsfor a real Vue mount (createApp(App).use(pinia).use(router).mount('#app')) and deletes the four legacy DOM-mount files (src/{ui,traceView,seed,main}.ts).index.htmlis restructured to a<div id="app">mount target.<HudPanel>,<SpeedPicker>,<ResetButton>,<ExportImportPanel>,<TracePanel>. Adds<TourOverlay>+<StepHighlight>against auseSelectorRegistryview-store stub (full registry lands in slice 1.3).useTourProgressview store + chapter-1 (autonomy) step content. Predicate combinestickAtLeast(3)witheventEmittedSince(AGENT_TICKED, 0). Tour copy tone (OQ-P1) is settled to friendly-informal.useAgentSessionwithtickIndex/recentEvents/lastTrace/lastTickNumber/sessionSnapshotprojections. Implements the snapshot-restore branch ofreplayFromSnapshot(snapshot)for<ExportImportPanel>.@vitejs/plugin-vue@^6for the demo build + the root vitest test runtime (Vue 3.5 + Vite 8). Component tests run under// @vitest-environment jsdomper file.agentonomous/*andwhiskers*keys are NOT migrated. Wiped at first mount via the existing STO-3 purge (extended to cover theagentonomous/namespace). New shell usesdemo.v2.session.speed,demo.v2.trace.visible,demo.v2.tour.progressexclusively.Tracks: #132
Test plan
npm run verify(format:check + lint + lint:demo + typecheck + 611 tests + lib build + typedoc) green.examples/product-demoVite production build green.🤖 Generated with Claude Code