Skip to content

feat(mascot): load Human mascots from GitHub manifest#4312

Merged
senamakel merged 21 commits into
tinyhumansai:mainfrom
senamakel:feat/github-mascot-manifest
Jun 30, 2026
Merged

feat(mascot): load Human mascots from GitHub manifest#4312
senamakel merged 21 commits into
tinyhumansai:mainfrom
senamakel:feat/github-mascot-manifest

Conversation

@senamakel

@senamakel senamakel commented Jun 29, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds a GitHub-backed mascot manifest service and typed manifest/state-engine helpers.
  • Adds ManifestRiveMascot so the Human stage can render manifest-provided Rive characters, poses, channels, idle cycles, and visemes.
  • Repoints the Settings character picker at manifest entries and persists selectedMascotId across reloads.
  • Updates voice/viseme timing to accept backend startSeconds/endSeconds alignment fields.
  • Adds focused unit coverage for manifest loading, state-engine matching, settings selection, Human page rendering, TTS timing, and lipsync behavior.

Problem

  • Human mascots were effectively tied to local/static assumptions, which made adding or changing Rive characters require app changes.
  • Rive state-machine inputs and viseme timelines were brittle when manifest casing or backend timing field names differed from frontend assumptions.
  • The selected mascot could be lost across reloads because Redux persistence did not include the new mascot selection field.

Solution

  • Introduce a manifest service under the Human mascot domain with config-driven manifest URL selection and validation.
  • Render manifest-driven Rive mascots through a dedicated component that resolves poses, channels, idle cycles, and visemes from manifest state-engine metadata.
  • Normalize Rive enum/state matching case-insensitively and drive lipsync from the actual viseme timeline.
  • Persist selectedMascotId in the mascot slice and update Settings/Human page tests around the manifest-backed selection flow.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — changed lines (Vitest + cargo-llvm-cov merged via diff-cover) meet the gate enforced by .github/workflows/pr-ci.yml. Run pnpm test:coverage and pnpm test:rust locally; PRs below 80% on changed lines will not merge.
  • N/A: Coverage matrix has no feature row for the internal mascot manifest renderer/config seam.
  • N/A: No affected feature IDs from the coverage matrix.
  • New external network dependency introduced and disclosed: the mascot library fetches the public GitHub raw manifest (raw.githubusercontent.com) plus manifest-declared mascot asset hosts; tests mock the request per Testing Strategy.
  • N/A: Does not touch release-cut manual smoke surfaces.
  • N/A: No linked issue for this branch.

Impact

  • Runtime/platform impact: desktop Human page and Settings mascot picker can use manifest-provided mascot entries.
  • Compatibility: legacy bundled mascot behavior is preserved through fallbacks while manifest loading is unavailable or incomplete.
  • Security/privacy: no secrets or PII are logged; manifest URL is public/configured and tests mock network responses.

Related

  • Closes: N/A
  • Follow-up PR(s)/TODOs: N/A

AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: feat/github-mascot-manifest
  • Commit SHA: c896d04

Validation Run

  • pnpm --filter openhuman-app format:check (via pre-push pnpm format:check)
  • pnpm typecheck (via pre-push)
  • Focused tests: pnpm debug unit src/features/human/Mascot/manifest/manifestService.test.ts src/features/human/Mascot/manifest/stateEngine.test.ts src/features/human/Mascot/manifest/useMascotManifest.test.tsx src/features/human/Mascot/ManifestRiveMascot.test.tsx src/features/human/HumanPage.test.tsx src/features/human/useHumanMascot.test.ts src/features/human/useHumanMascot.lipsync.test.ts src/features/human/voice/ttsClient.test.ts src/components/settings/panels/__tests__/MascotPanel.test.tsx (9 files, 178 tests) and cargo test --manifest-path Cargo.toml voice::reply_speech --lib (8 tests)
  • Rust fmt/check (if changed): cargo fmt --manifest-path ../Cargo.toml --all --check via pre-push
  • Tauri fmt/check (if changed): cargo check --manifest-path app/src-tauri/Cargo.toml via pre-push
  • E2E build: pnpm --filter openhuman-app test:e2e:web:build
  • Focused E2E: bash app/scripts/e2e-web-session.sh test/playwright/specs/settings-feature-preferences.spec.ts --grep "persists manifest mascot selection"
  • Review fix checks: pnpm debug unit src/features/human/Mascot/manifest/stateEngine.test.ts src/features/human/useHumanMascot.lipsync.test.ts (2 files, 21 tests) and pnpm --filter openhuman-app exec eslint src/features/human/Mascot/ManifestRiveMascot.tsx
  • Final review fix checks: pnpm debug unit src/features/human/Mascot/manifest/stateEngine.test.ts src/components/skills/__tests__/MeetingBotsCard.test.tsx (2 files, 48 tests)
  • Final follow-up review checks: pnpm debug unit src/features/human/useHumanMascot.lipsync.test.ts (1 file, 9 tests), cargo test --manifest-path Cargo.toml persona_pack_reports_github_mascot_manifest_destination --lib, and cargo test --manifest-path Cargo.toml github_repo_memory_source_reports_github_destination --lib
  • Edge-case review follow-up checks: pnpm debug unit src/features/human/Mascot/manifest/stateEngine.test.ts src/features/human/Mascot/manifest/useMascotManifest.test.tsx src/features/human/useHumanMascot.lipsync.test.ts (3 files, 27 tests) and cargo test --manifest-path Cargo.toml persona_pack_reports_github_mascot_manifest_destination --lib
  • Custom GIF preservation review check: pnpm debug unit src/features/human/Mascot/manifest/useMascotManifest.test.tsx src/features/human/Mascot/manifest/stateEngine.test.ts src/features/human/useHumanMascot.lipsync.test.ts (3 files, 28 tests)
  • CI failure follow-up check: pnpm debug unit src/features/human/Mascot/ManifestRiveMascot.test.tsx src/features/human/Mascot/manifest/useMascotManifest.test.tsx src/features/human/Mascot/manifest/stateEngine.test.ts src/features/human/useHumanMascot.lipsync.test.ts (4 files, 33 tests)
  • Local default preservation review check: pnpm debug unit src/features/human/Mascot/manifest/useMascotManifest.test.tsx src/components/settings/panels/__tests__/MascotPanel.test.tsx src/features/human/Mascot/ManifestRiveMascot.test.tsx src/features/human/Mascot/manifest/stateEngine.test.ts src/features/human/useHumanMascot.lipsync.test.ts (5 files, 57 tests)
  • Final pre-push checks: pnpm --filter openhuman-app format:check, pnpm lint, pnpm typecheck, pnpm rust:check, and pnpm --filter openhuman-app lint:commands-tokens via git push origin feat/github-mascot-manifest

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: Human mascot selection and rendering can come from the GitHub mascot manifest instead of only local/static mascot assumptions.
  • User-visible effect: Settings can present manifest-backed characters, and the Human page keeps the selected mascot across reloads.

Parity Contract

  • Legacy behavior preserved: fallback selection/render paths remain when manifest data is unavailable.
  • Guard/fallback/dispatch parity checks: manifest tests cover happy path, unavailable manifest fallback, case-insensitive state matching, and voice timing field aliases.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A
  • Canonical PR: This PR
  • Resolution (closed/superseded/updated): N/A

Summary by CodeRabbit

  • New Features
    • Updated the mascot picker and human stage preview to use the published mascot manifest, including draft badges, consistent pose/color/viseme rendering, and idle pose/flourish cycling.
    • Selecting “local default” or a new character now updates the preview/selection state cleanly, including custom GIF handling.
  • Bug Fixes
    • Improved TTS-driven lipsync timing by normalizing viseme timelines and making playback/metadata timing more reliable.
    • Enhanced reply-speech timing parsing to correctly handle millisecond and second-based frame values.
  • Documentation
    • Added localized UI text for the “Draft” mascot label.
  • Chores
    • Persisted the selected mascot ID across reloads.
  • Tests
    • Expanded unit/integration/E2E coverage for manifest selection/preview and lipsync timing.

senamakel added 11 commits June 29, 2026 14:14
Fetch the published tinyhumansai/mascots dist/mascots.json directly over
HTTPS with in-memory + localStorage caching and a sha256-keyed .riv binary
cache (reusing rivCache). Adds typed manifest model, validation that drops
malformed/runtime-less entries, and default/find selectors.
Constrain face->pose, viseme normalisation, idle flourish picks and channel
defaults to a specific mascot's stateEngine vocabulary, degrading cleanly to
idle/thinking/sil when an asset lacks a given value.
Loads a manifest mascot's .riv buffer (sha-cached), drives pose/viseme/colors
constrained to its stateEngine, runs the per-mascot idle pose cycle, and
auto-cycles channels (e.g. Toshi's eyes) when alive. Falls back to the bundled
default while loading/on failure so the stage never blanks.
Refactor HumanPage to utilize the useMascotManifest hook, allowing for dynamic resolution of the active mascot based on the GitHub manifest. This change replaces the previous selectedMascotId logic with a fallback to ManifestRiveMascot, ensuring a seamless user experience while loading or in case of errors. Update tests to mock the mascot manifest appropriately.
useMascotManifest loads the manifest and resolves the active mascot from the
selectedMascotId preference (falling back to the default ready mascot).
HumanPage now renders ManifestRiveMascot instead of the backend-sourced
BackendRiveMascot.
MascotPanel now lists mascots from the published manifest (via useMascotManifest)
with per-mascot pose/viseme counts and a draft badge, and previews the active
mascot with ManifestRiveMascot. Drops the backend /mascots library calls. Adds
the settings.mascot.characterDraft i18n key across all locales. Voice + color
sections are unchanged.
The cloud TTS backend ships per-frame timing as seconds (startSeconds/
endSeconds), but parse_cue/parse_alignment only read *_ms — so timing
deserialized as missing and every frame collapsed to start=0/end=80, freezing
the mascot mouth on the first viseme. Add a read_ms helper that falls back to
the seconds keys (×1000) and wire it into both parsers. Adds a unit test for
the seconds shape including a pause gap.
- Suppress the text-delta pseudo-lipsync while "Speak replies" is on so the
  mouth only moves with the synthesized audio (it was flapping ahead of, and
  faster than, the voice during streaming).
- Replace the brittle rescale with normalizeVisemeTimeline: keep a real
  per-frame timeline (preserving gaps as pauses), and only even-distribute the
  viseme sequence across the measured audio when timestamps are degenerate.
- Prefer the char alignment (which carries real timing incl. pauses) when the
  viseme starts are unusable (hasUsableStarts).
- Resolve audio duration without an extra microtask when already known.
- Match resolved pose/viseme codes against the asset's actual enum option list
  case-insensitively (Rive enums are case-sensitive and silently ignore an
  unknown value, which froze the mouth/pose).
- Gate the enum-driving effects on a stable content key instead of the
  per-render `values` array identity, which caused an infinite render loop
  ("Maximum update depth exceeded").
The mascot redux-persist whitelist omitted selectedMascotId, so the chosen
GitHub-manifest mascot reset to the default on every reload. Add it to the
whitelist (the slice's REHYDRATE guard re-validates it on restore).
@senamakel senamakel requested a review from a team June 29, 2026 23:26
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds manifest-based mascot selection and rendering for settings and human pages, persists the selected mascot id, updates draft translations and privacy metadata, and expands TTS viseme timing normalization and seconds-based parsing. It also adds meeting-bot mascot-id fallback routing.

Changes

Mascot Manifest System

Layer / File(s) Summary
Manifest contracts and service
app/src/features/human/Mascot/manifest/types.ts, app/src/features/human/Mascot/manifest/manifestService.ts, app/src/features/human/Mascot/manifest/manifestService.test.ts, app/src/features/human/Mascot/manifest/useMascotManifest.test.tsx
Defines manifest document, entry, file, channel, and state-engine types; implements manifest parsing, fetch/memoization, snapshot fallback, mascot lookup, default selection, and runtime .riv loading; covers validation and fetch fallback behavior in tests.
State engine helpers
app/src/features/human/Mascot/manifest/stateEngine.ts, app/src/features/human/Mascot/manifest/stateEngine.test.ts
Adds helpers to resolve face-to-pose, viseme codes, idle flourishes, channel defaults, and available poses against a mascot state engine, with unit tests for each helper.
Manifest Rive renderer
app/src/features/human/Mascot/ManifestRiveMascot.tsx, app/src/features/human/Mascot/ManifestRiveMascot.test.tsx, app/src/features/human/Mascot/index.ts
Implements manifest-buffer loading, fallback mascot rendering, pose/viseme/color binding, idle pose rotation, and enum channel auto-cycling; re-exports the renderer and manifest types/functions from the mascot barrel; tests cover loading, mapping, fallback, and cycling behavior.
Mascot settings and human page wiring
app/src/components/settings/panels/MascotPanel.tsx, app/src/components/settings/panels/__tests__/MascotPanel.test.tsx, app/src/features/human/HumanPage.tsx, app/src/features/human/HumanPage.test.tsx
Switches the mascot settings panel from backend list/detail fetching to useMascotManifest, renders manifest entries and draft badges, and previews the active entry with ManifestRiveMascot; HumanPage now renders the manifest-driven mascot stage. Tests and mocks were updated around the new manifest flow.
Persistence, config, and catalog updates
app/src/store/index.ts, app/src/store/mascotSlice.ts, app/src/utils/config.ts, app/src/test/setup.ts, app/src/lib/i18n/*.ts, src/openhuman/about_app/catalog_data.rs, src/openhuman/about_app/catalog_tests.rs
Persists selectedMascotId, adds MASCOT_MANIFEST_URL, adds settings.mascot.characterDraft translations across locales, and annotates the persona pack capability with GitHub manifest privacy metadata and tests.

TTS Lipsync and timing

Layer / File(s) Summary
Viseme helpers and backend seconds parsing
app/src/features/human/voice/ttsClient.ts, app/src/features/human/voice/ttsClient.test.ts, src/openhuman/voice/reply_speech.rs
Adds viseme start usability checks and timeline normalization on the client, and updates Rust cue/alignment parsing to accept seconds-based timing keys, with tests for both.
Human lipsync playback
app/src/features/human/useHumanMascot.ts, app/src/features/human/useHumanMascot.test.ts, app/src/features/human/useHumanMascot.lipsync.test.ts
Updates TTS playback to prefer usable backend starts, normalize viseme timelines, track wall-clock playback anchors, suppress streaming text pseudo-lipsync while audio is active, and add deterministic tests for rescaling, delayed metadata, and frozen audio clocks.

Meeting Bot Mascot Routing

Layer / File(s) Summary
Meeting bot mascot id resolution
app/src/components/skills/MeetingBotsCard.tsx, app/src/components/skills/__tests__/MeetingBotsCard.test.tsx
Adds a mascot-id allowlist for meeting bots, falls back to mascot color when the selected mascot is not compatible, and tests the fallback for a manifest-only mascot id.

Possibly related PRs

  • tinyhumansai/openhuman#3363: Both PRs touch the meeting-bot mascot selection path and change how mascotId is derived before backend submission.

Suggested labels

feature

Suggested reviewers

  • sanil-23
  • oxoxDev

Poem

🐇 I hopped through manifests, crisp and bright,
Draft badges twinkled in settings light.
Visemes glided on a steadier track,
While mascot stars and timing snapped right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: switching Human mascots to a GitHub-hosted manifest.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. labels Jun 29, 2026

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08c326fd34

ℹ️ 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 thread app/src/features/human/Mascot/manifest/manifestService.ts
Comment thread app/src/store/index.ts

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 7

🧹 Nitpick comments (1)
app/src/features/human/Mascot/manifest/manifestService.ts (1)

27-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Move the manifest snapshot behind a store slice instead of raw localStorage.

This adds a second persistence path beside mascotSlice, so manifest data and selectedMascotId now follow different invalidation/versioning rules. As per coding guidelines, "Prefer Redux Toolkit state slices over ad-hoc localStorage; frontend state should live in the established store/ slices."

Also applies to: 97-114

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/features/human/Mascot/manifest/manifestService.ts` around lines 27 -
28, The manifest snapshot is still being persisted directly through
`SNAPSHOT_KEY` in `manifestService`, which bypasses the Redux store and creates
a separate persistence/versioning path from `mascotSlice`. Move this snapshot
state into an existing or new store slice under `store/` and update the relevant
manifest load/save flow in `manifestService` to read and write through Redux
Toolkit state instead of raw `localStorage`, keeping `selectedMascotId` and
manifest data on the same persistence path.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/features/human/Mascot/manifest/manifestService.ts`:
- Around line 48-69: `isManifestEntry()` is too permissive for nested
`stateEngine` data, so remote entries with invalid `visemeCodes`,
`idlePoseCycle`, or missing/ill-typed `channels` can still be cast to
`MascotManifestEntry`. Tighten the validation in `manifestService.ts` by
checking each `stateEngine` collection element and the `channels` structure for
the expected string keys/values before returning true, so only fully valid
manifest entries pass `parseManifest()`.
- Around line 122-145: The stalled manifest request in fetchMascotManifest
prevents the snapshot fallback from ever running because the retry/offline logic
only happens inside the catch path. Add an abort/timeout around the fetch call
for MASCOT_MANIFEST_URL so a hung request rejects and can reach readSnapshot(),
while keeping the existing inflight, parseManifest, and writeSnapshot flow
unchanged.

In `@app/src/features/human/Mascot/manifest/useMascotManifest.ts`:
- Around line 28-31: The useMascotManifest effect contains a redundant
synchronous state update because loading already defaults to true, so remove the
setLoading(true) call from the useEffect while keeping the rest of the async
cancellation logic intact. Update the effect in useMascotManifest so it only
handles the async manifest fetch and cancellation, and rely on the existing
initial loading state instead of setting it again inside the effect.

In `@app/src/features/human/Mascot/ManifestRiveMascot.tsx`:
- Around line 256-281: The loader state in ManifestRiveMascot is being preserved
across entry changes because the component relies on callers remounting it with
a key, which can leave stale buffer/failed state attached to a new entry. Reset
the internal state inside ManifestRiveMascot when entry changes by clearing
buffer and failed before or as part of the load effect, so a new entry always
starts fresh regardless of whether the parent remounts it. Use the existing
ManifestRiveMascot component, its useEffect, and the buffer/failed state
variables as the place to make the reset boundary self-contained.
- Around line 166-169: The idle cleanup in ManifestRiveMascot’s effect is
writing restPose directly, which bypasses the case-insensitive enum
normalization used elsewhere. Update the cleanup path in the effect that returns
the timer teardown and setPoseRef.current to pass the idle/rest pose through
matchEnumValue so assets exposed as Idle or IDLE still resolve correctly when
clearing a flourish state.

In `@app/src/features/human/useHumanMascot.ts`:
- Around line 315-322: The lipsync fallback is not actually using a wall-clock
source yet; `useHumanMascot` still depends on `playback.currentMs()`, which
ultimately reads `audio.currentTime`, so the CEF blob-audio freeze can still
happen. Add a real playback-start timestamp/ref in `useHumanMascot` and derive
elapsed playback time from `performance.now()` (or equivalent monotonic clock)
when advancing viseme selection, rather than relying only on
`PlaybackHandle.currentMs()` or the existing log-throttle ref. Keep the change
localized to the playback timing path in `useHumanMascot` and, if needed, the
`PlaybackHandle` contract in `audioPlayer.ts` so the lipsync loop reads the new
wall-clock-based time source.

In `@src/openhuman/voice/reply_speech.rs`:
- Around line 307-315: The duration fallback in reply_speech::read_ms is missing
the short seconds aliases, so it can ignore valid inputs like startSec or
durationSec and fall back to the default. Update the fallback branch in the end
calculation so it uses the same alias set as the initial start parsing, or
remove the short alias support from the start parser for consistency. Keep the
alias handling aligned across the read_ms calls used for start, time, and
duration.

---

Nitpick comments:
In `@app/src/features/human/Mascot/manifest/manifestService.ts`:
- Around line 27-28: The manifest snapshot is still being persisted directly
through `SNAPSHOT_KEY` in `manifestService`, which bypasses the Redux store and
creates a separate persistence/versioning path from `mascotSlice`. Move this
snapshot state into an existing or new store slice under `store/` and update the
relevant manifest load/save flow in `manifestService` to read and write through
Redux Toolkit state instead of raw `localStorage`, keeping `selectedMascotId`
and manifest data on the same persistence path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c2102bc9-ddac-4fb7-b890-b0d155818fa2

📥 Commits

Reviewing files that changed from the base of the PR and between 300d70a and 08c326f.

📒 Files selected for processing (38)
  • app/src/components/settings/panels/MascotPanel.tsx
  • app/src/components/settings/panels/__tests__/MascotPanel.test.tsx
  • app/src/features/human/HumanPage.test.tsx
  • app/src/features/human/HumanPage.tsx
  • app/src/features/human/Mascot/ManifestRiveMascot.test.tsx
  • app/src/features/human/Mascot/ManifestRiveMascot.tsx
  • app/src/features/human/Mascot/index.ts
  • app/src/features/human/Mascot/manifest/manifestService.test.ts
  • app/src/features/human/Mascot/manifest/manifestService.ts
  • app/src/features/human/Mascot/manifest/stateEngine.test.ts
  • app/src/features/human/Mascot/manifest/stateEngine.ts
  • app/src/features/human/Mascot/manifest/types.ts
  • app/src/features/human/Mascot/manifest/useMascotManifest.test.tsx
  • app/src/features/human/Mascot/manifest/useMascotManifest.ts
  • app/src/features/human/useHumanMascot.lipsync.test.ts
  • app/src/features/human/useHumanMascot.test.ts
  • app/src/features/human/useHumanMascot.ts
  • app/src/features/human/voice/ttsClient.test.ts
  • app/src/features/human/voice/ttsClient.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/store/index.ts
  • app/src/store/mascotSlice.ts
  • app/src/test/setup.ts
  • app/src/utils/config.ts
  • src/openhuman/voice/reply_speech.rs

Comment thread app/src/features/human/Mascot/manifest/manifestService.ts
Comment thread app/src/features/human/Mascot/manifest/manifestService.ts
Comment thread app/src/features/human/Mascot/manifest/useMascotManifest.ts
Comment thread app/src/features/human/Mascot/ManifestRiveMascot.tsx
Comment thread app/src/features/human/Mascot/ManifestRiveMascot.tsx Outdated
Comment thread app/src/features/human/useHumanMascot.ts
Comment thread src/openhuman/voice/reply_speech.rs

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f839a39139

ℹ️ 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 thread app/src/features/human/Mascot/manifest/stateEngine.ts Outdated
Comment thread app/src/features/human/useHumanMascot.ts Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c684c24f02

ℹ️ 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 thread app/src/components/settings/panels/MascotPanel.tsx
Comment thread app/src/features/human/Mascot/manifest/stateEngine.ts Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 47ab49b4a4

ℹ️ 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 thread app/src/features/human/useHumanMascot.ts Outdated
Comment thread app/src/features/human/Mascot/manifest/manifestService.ts
@coderabbitai coderabbitai Bot removed the agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. label Jun 30, 2026

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79477917ef

ℹ️ 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 thread app/src/features/human/Mascot/manifest/stateEngine.ts

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/features/human/Mascot/manifest/useMascotManifest.ts`:
- Around line 53-56: The fallback mascot is not being persisted because
useMascotManifest exits early when selectedMascotId is null, so the default
manifest mascot never gets written to Redux. Update the effect in
useMascotManifest to allow syncing fallbackEntry?.id into state when there is no
current selection, while still avoiding unnecessary writes when selectedEntry
already matches. Keep the logic centered around selectedMascotId,
fallbackEntry?.id, selectedEntry, and setSelectedMascotId so the
persisted-selection contract is maintained.

In `@app/src/features/human/useHumanMascot.lipsync.test.ts`:
- Around line 100-137: Update makePlaybackWithDeferredMetadata so the
FakePlayback handle’s stop() also settles ended, matching the playBase64Audio
contract used by useHumanMascot. When stopped, make ended reject or otherwise
resolve in the same way the real playback does so interruption and unmount paths
exercise the hook’s ended.catch(swallowAudioStop) cleanup instead of leaving the
promise pending. Keep the behavior aligned with finish() and the FakePlayback
shape in this test helper.

In `@src/openhuman/about_app/catalog_data.rs`:
- Around line 79-87: The disclosure for GITHUB_MASCOT_MANIFEST underreports
egress by naming only raw.githubusercontent.com, while the Persona Pack flow
also fetches runtime assets from the manifest’s files[].url. Update the
CapabilityPrivacy destinations used in catalog_data.rs for this manifest to
describe the broader GitHub/raw-plus-asset-host behavior, and keep the privacy
metadata aligned with the actual fetch path in the mascot picker / Human page
flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 285af5c6-6d4a-4705-8141-dfba634e165b

📥 Commits

Reviewing files that changed from the base of the PR and between 08c326f and 7947791.

📒 Files selected for processing (16)
  • app/src/components/skills/MeetingBotsCard.tsx
  • app/src/components/skills/__tests__/MeetingBotsCard.test.tsx
  • app/src/features/human/Mascot/ManifestRiveMascot.test.tsx
  • app/src/features/human/Mascot/ManifestRiveMascot.tsx
  • app/src/features/human/Mascot/manifest/manifestService.test.ts
  • app/src/features/human/Mascot/manifest/manifestService.ts
  • app/src/features/human/Mascot/manifest/stateEngine.test.ts
  • app/src/features/human/Mascot/manifest/stateEngine.ts
  • app/src/features/human/Mascot/manifest/useMascotManifest.test.tsx
  • app/src/features/human/Mascot/manifest/useMascotManifest.ts
  • app/src/features/human/useHumanMascot.lipsync.test.ts
  • app/src/features/human/useHumanMascot.ts
  • app/test/playwright/specs/settings-feature-preferences.spec.ts
  • src/openhuman/about_app/catalog_data.rs
  • src/openhuman/about_app/catalog_tests.rs
  • src/openhuman/voice/reply_speech.rs
🚧 Files skipped from review as they are similar to previous changes (7)
  • app/src/features/human/Mascot/ManifestRiveMascot.test.tsx
  • app/src/features/human/Mascot/manifest/manifestService.ts
  • app/src/features/human/Mascot/manifest/stateEngine.test.ts
  • src/openhuman/voice/reply_speech.rs
  • app/src/features/human/Mascot/manifest/stateEngine.ts
  • app/src/features/human/Mascot/ManifestRiveMascot.tsx
  • app/src/features/human/useHumanMascot.ts

Comment thread app/src/features/human/Mascot/manifest/useMascotManifest.ts Outdated
Comment thread app/src/features/human/useHumanMascot.lipsync.test.ts
Comment thread src/openhuman/about_app/catalog_data.rs
@coderabbitai coderabbitai Bot added the rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. label Jun 30, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9765130594

ℹ️ 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 thread app/src/features/human/Mascot/manifest/useMascotManifest.ts
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9efb1247f1

ℹ️ 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 thread app/src/features/human/Mascot/manifest/useMascotManifest.ts
@coderabbitai coderabbitai Bot removed the rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. label Jun 30, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 30, 2026
@senamakel senamakel merged commit d746fec into tinyhumansai:main Jun 30, 2026
17 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Net-new user-facing capability or product behavior.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant