Skip to content

Update tagline: Summon your AI superpower - #44

Merged
sonichi merged 1 commit into
mainfrom
tagline-update
Mar 30, 2026
Merged

sonichi merged 1 commit into
mainfrom
tagline-update

Conversation

@sonichi

@sonichi sonichi commented Mar 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • GitHub description: "Summon your AI superpower — voice, vision, and autonomous action"
  • Web UI tagline: "Summon your AI superpower"
  • README: Updated to match

Per owner direction — removed "on your Mac" (sounds platform-limited), added "Summon" (signature command).

Test plan

  • Refresh web UI — tagline shows "Summon your AI superpower"
  • GitHub repo page shows updated description

🤖 Generated with Claude Code

GitHub description + README: "Summon your AI superpower — voice,
vision, and autonomous action"

Web UI: "Summon your AI superpower"

Removed "on your Mac" (sounds platform-limited) and added "Summon"
(the signature command). Per owner direction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sonichi
sonichi merged commit 74ed502 into main Mar 30, 2026
@sonichi
sonichi deleted the tagline-update branch March 30, 2026 14:02
sonichi added a commit that referenced this pull request Apr 20, 2026
…, #44) (#486)

Two clear-text-logging alerts both involved slice()-ing a sensitive env
var and printing the substring. CodeQL's taint model treats any
substring as clear-text-logging of the secret, even when the exposed
bytes are trivial (public prefix, last 2 digits).

- `src/voice-agent.ts:66` — GEMINI_API_KEY / GEMINI_VOICE_API_KEY startup
  assertion printed the first 4 chars ("AIza" for valid keys). Replaced
  with a boolean "prefix matches AIza? yes/no" — same diagnostic signal
  (detects truncated paste + wrong-var), no taint flow.
- `skills/phone-conversation/scripts/conversation-server.ts:1625` —
  Phone-server banner printed a masked TWILIO_PHONE_NUMBER (first 2 +
  last 2). Replaced with presence-only signal "configured" / "MISSING".
  Inspect via `env | grep TWILIO_PHONE_NUMBER` if needed.

Both are startup-banner context; no runtime or debugging impact.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219 added a commit that referenced this pull request Apr 21, 2026
…-logging) (#493)

## #43 js/resource-exhaustion (src/web-client.ts:2549)

#489's `Math.min(ttl, MAX_TTL_MS)` is an `isNumericFlowStep` (numeric
passthrough) in `codeql/javascript-all@2.6.27` — it narrows the value but
doesn't register as a sanitizer. The `js/resource-exhaustion` config only
blocks taint via `UpperBoundsCheckSanitizerGuard`, which matches
`RelationalComparison` AST nodes (`<`, `<=`, `>`, `>=`).

Rewrote the clamp as `ttl <= MAX_TTL_MS ? ttl : MAX_TTL_MS` — semantically
identical, but CodeQL now sees `ttl` as the lesser operand in a `<=`
comparison and blocks taint in the true branch.

## #44 js/clear-text-logging (src/voice-agent.ts:71)

The `${value.length}` and `${prefixOk}` interpolations in `console.error`
both read properties of `value`. The env var `GEMINI_API_KEY` triggers
`HeuristicNames` → tainted source; `allowImplicitRead` in the cleartext
config pulls any property of a tainted value into the logger sink.
#486 stopped echoing substrings but the length + ternary-prefix diagnostic
still flow the taint.

Dropped those two interpolations from the log; kept the name, expected
format ("AIza..." 35-60 chars), and remediation URL. Diagnostic loss is
minor — a malformed key always needs to be regenerated anyway.

## Verification

Local CodeQL CLI 2.25.2 + codeql/javascript-queries@2.3.7:
- main (dc7bfbe):  2 alerts (resource-exhaustion @ web-client.ts:2549, clear-text-logging @ voice-agent.ts:71)
- this branch:     0 alerts

`npx tsc --noEmit` clean.

Closes #43, #44. Together with #492 (merged earlier this session), this
zeroes the CodeQL security-code-scanning queue.

Co-authored-by: Xueqing Liu <xueqingliu@Xueqings-Mac-Studio.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
sonichi pushed a commit that referenced this pull request May 15, 2026
Layers the original PR #44 CTA verb back into README hero + web-client
tagline without removing the PR #666 "My AI Stand" brand line.

Why now: Robin Li keynoted Baidu Create 2026 on 2026-05-14 framing the
personal-AI category as "the rise of super individuals" — restores the
verb-pair (summon + superpower) at the moment that discourse window
opened, ahead of Observe Summit (June 4).

Diff is surgical:
- README hero gains one bolded CTA line under the brand line
- web-client.ts:649 tagline becomes "My AI Stand · Summon your AI superpower"
  (the dynamic stand-identity branch at :590-591 still overrides this
  with the named-Stand origin once the user names their Stand)

Per owner pick A (layer, not replace) from 2026-05-15 16:06.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
sonichi added a commit that referenced this pull request May 15, 2026
…tagline (#718)

* feat(framing): add "Summon your AI superpower" CTA layer

Layers the original PR #44 CTA verb back into README hero + web-client
tagline without removing the PR #666 "My AI Stand" brand line.

Why now: Robin Li keynoted Baidu Create 2026 on 2026-05-14 framing the
personal-AI category as "the rise of super individuals" — restores the
verb-pair (summon + superpower) at the moment that discourse window
opened, ahead of Observe Summit (June 4).

Diff is surgical:
- README hero gains one bolded CTA line under the brand line
- web-client.ts:649 tagline becomes "My AI Stand · Summon your AI superpower"
  (the dynamic stand-identity branch at :590-591 still overrides this
  with the named-Stand origin once the user names their Stand)

Per owner pick A (layer, not replace) from 2026-05-15 16:06.

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

* feat(framing): align CTA pronoun to first-person ("my", not "your")

Hero is otherwise first-person — "when I'm engaged", "Learns my
patterns", "Runs across my Macs" — so the JoJo Stand voice is the
user claiming their Stand. "Summon your AI superpower" broke that
voice; "Summon my AI superpower" restores it.

Per owner direction in PR #718 review thread.

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

---------

Co-authored-by: Chi <wangchi@Chis-Mac-mini.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219 pushed a commit to liususan091219/sutando-fork that referenced this pull request May 28, 2026
GitHub description + README: "Summon your AI superpower — voice,
vision, and autonomous action"

Web UI: "Summon your AI superpower"

Removed "on your Mac" (sounds platform-limited) and added "Summon"
(the signature command). Per owner direction.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
liususan091219 pushed a commit to liususan091219/sutando-fork that referenced this pull request May 28, 2026
…onichi#24, sonichi#44) (sonichi#486)

Two clear-text-logging alerts both involved slice()-ing a sensitive env
var and printing the substring. CodeQL's taint model treats any
substring as clear-text-logging of the secret, even when the exposed
bytes are trivial (public prefix, last 2 digits).

- `src/voice-agent.ts:66` — GEMINI_API_KEY / GEMINI_VOICE_API_KEY startup
  assertion printed the first 4 chars ("AIza" for valid keys). Replaced
  with a boolean "prefix matches AIza? yes/no" — same diagnostic signal
  (detects truncated paste + wrong-var), no taint flow.
- `skills/phone-conversation/scripts/conversation-server.ts:1625` —
  Phone-server banner printed a masked TWILIO_PHONE_NUMBER (first 2 +
  last 2). Replaced with presence-only signal "configured" / "MISSING".
  Inspect via `env | grep TWILIO_PHONE_NUMBER` if needed.

Both are startup-banner context; no runtime or debugging impact.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219 added a commit to liususan091219/sutando-fork that referenced this pull request May 28, 2026
… (clear-text-logging) (sonichi#493)

## sonichi#43 js/resource-exhaustion (src/web-client.ts:2549)

sonichi#489's `Math.min(ttl, MAX_TTL_MS)` is an `isNumericFlowStep` (numeric
passthrough) in `codeql/javascript-all@2.6.27` — it narrows the value but
doesn't register as a sanitizer. The `js/resource-exhaustion` config only
blocks taint via `UpperBoundsCheckSanitizerGuard`, which matches
`RelationalComparison` AST nodes (`<`, `<=`, `>`, `>=`).

Rewrote the clamp as `ttl <= MAX_TTL_MS ? ttl : MAX_TTL_MS` — semantically
identical, but CodeQL now sees `ttl` as the lesser operand in a `<=`
comparison and blocks taint in the true branch.

## sonichi#44 js/clear-text-logging (src/voice-agent.ts:71)

The `${value.length}` and `${prefixOk}` interpolations in `console.error`
both read properties of `value`. The env var `GEMINI_API_KEY` triggers
`HeuristicNames` → tainted source; `allowImplicitRead` in the cleartext
config pulls any property of a tainted value into the logger sink.
sonichi#486 stopped echoing substrings but the length + ternary-prefix diagnostic
still flow the taint.

Dropped those two interpolations from the log; kept the name, expected
format ("AIza..." 35-60 chars), and remediation URL. Diagnostic loss is
minor — a malformed key always needs to be regenerated anyway.

## Verification

Local CodeQL CLI 2.25.2 + codeql/javascript-queries@2.3.7:
- main (dc7bfbe):  2 alerts (resource-exhaustion @ web-client.ts:2549, clear-text-logging @ voice-agent.ts:71)
- this branch:     0 alerts

`npx tsc --noEmit` clean.

Closes sonichi#43, sonichi#44. Together with sonichi#492 (merged earlier this session), this
zeroes the CodeQL security-code-scanning queue.

Co-authored-by: Xueqing Liu <xueqingliu@Xueqings-Mac-Studio.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219 pushed a commit to liususan091219/sutando-fork that referenced this pull request May 28, 2026
…tagline (sonichi#718)

* feat(framing): add "Summon your AI superpower" CTA layer

Layers the original PR sonichi#44 CTA verb back into README hero + web-client
tagline without removing the PR sonichi#666 "My AI Stand" brand line.

Why now: Robin Li keynoted Baidu Create 2026 on 2026-05-14 framing the
personal-AI category as "the rise of super individuals" — restores the
verb-pair (summon + superpower) at the moment that discourse window
opened, ahead of Observe Summit (June 4).

Diff is surgical:
- README hero gains one bolded CTA line under the brand line
- web-client.ts:649 tagline becomes "My AI Stand · Summon your AI superpower"
  (the dynamic stand-identity branch at :590-591 still overrides this
  with the named-Stand origin once the user names their Stand)

Per owner pick A (layer, not replace) from 2026-05-15 16:06.

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

* feat(framing): align CTA pronoun to first-person ("my", not "your")

Hero is otherwise first-person — "when I'm engaged", "Learns my
patterns", "Runs across my Macs" — so the JoJo Stand voice is the
user claiming their Stand. "Summon your AI superpower" broke that
voice; "Summon my AI superpower" restores it.

Per owner direction in PR sonichi#718 review thread.

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

---------

Co-authored-by: Chi <wangchi@Chis-Mac-mini.local>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219 added a commit that referenced this pull request Oct 7, 2026
…p the local copy

Review: the Transcribe Live provider is a common component, not a
Sutando one. It moves to bodhi in randombet/bodhi_realtime_agent#44.
voice-agent now imports it from bodhi-realtime-agent. Its tests moved
with it.

This does not compile against bodhi 0.4.0. It needs the bodhi release
that contains #44, and the dependency bump to that version lands here
once it is published.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
liususan091219 added a commit that referenced this pull request Oct 8, 2026
…ve (replaces the prompt-only mode) (#5184)

* feat(voice): meeting mode transcribes via Gemini Transcribe Live on bodhi dictation mode

switch_mode("meeting") now puts the bodhi session into transcription mode:
the voice model is quiesced, gemini-3.5-transcribe-live transcribes the mic,
and each final line is appended to notes/meeting-<date>.md. An exit phrase
("Sutando, come back", "meeting is over", "end meeting", ...) or the
menu-bar toggle returns to agent mode.

GeminiLiveTranscribeSTTProvider implements bodhi's STTProvider over the Live
API WebSocket and rotates sessions before the 10-minute cap, handing over at
a speech pause so no word is split across sessions.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs(src-map): index the meeting dictation modules

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(voice): hint Transcribe Live with the name Sutando so the exit phrase is heard

Live test on xueqing: "Sutando, come back" was transcribed as "Siddhartha
comeback", "Siddhant will come back", "Sutanu", so meeting mode never exited.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(voice): meeting mode is dictation only; remove the prompt-only meeting mode

Owner: two meeting modes is confusing; "switch to meeting mode" means dictation.

- switch_mode("meeting") always enters bodhi dictation; the old instruction
  (stay silent, call save_meeting_note every 5-10 min) is gone.
- save_meeting_note is removed.
- The meeting prompts (tool list, critical rules, greeting, reconnect hint,
  base-mode marker) now describe dictation: the model does not hear the meeting.
- Zoom detection at startup and summon/join_zoom/join_gmeet no longer turn on
  meeting mode by themselves: under dictation the agent could not hear the user
  in a summoned call. Meeting mode starts only when asked.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(voice): enter meeting dictation after the spoken confirmation, not 1.5 s after switch_mode

Live on xueqing the confirmation "I have switched to meeting mode." completed
about 1 s after dictation had already quiesced audio output, so it was never heard
and the owner could not tell whether transcription had started. Entry now waits for
the turn after the one carrying switch_mode, with an 8 s fallback.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(voice): carry the meeting transcript back into the agent when meeting mode ends

Dictation keeps the meeting out of the voice model's context, so after
"Sutando, come back" the agent knew only the note's path and line count,
and could not answer questions about what was said. Exiting now injects
this meeting's lines (from entering meeting mode to leaving it), framed
as data, not as user speech or an instruction. A meeting longer than
30k characters carries its end, and the agent is told the full text is
in the note.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(voice): take GeminiLiveTranscribeSTTProvider from bodhi, drop the local copy

Review: the Transcribe Live provider is a common component, not a
Sutando one. It moves to bodhi in randombet/bodhi_realtime_agent#44.
voice-agent now imports it from bodhi-realtime-agent. Its tests moved
with it.

This does not compile against bodhi 0.4.0. It needs the bodhi release
that contains #44, and the dependency bump to that version lands here
once it is published.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(voice): type the meeting-dictation stub provider instead of any

The meeting-dictation tests used `const provider: any`. ESLint's
no-explicit-any is an error in this file, which failed the lint job.
They now use a StubProvider that implements STTProvider, plus a say()
helper that delivers a final line.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(voice): leave meeting mode only on a deliberate exit command

Review: an exit phrase anywhere in a segment ended the meeting. For
example, "Do not stop dictation until we finish the budget review."
recorded "Do not" and switched to agent mode, and discussing how to
"end the meeting" did the same.

A segment now exits only when its last exit phrase ends the segment
(trailing please/now/thanks aside) and the segment either
- is only that command, apart from fillers like "okay" and "hi", or
- addresses it to Sutando ("..., Sutando, end the meeting").

Meeting speech before an addressed command is still recorded. A
segment of only fillers before it is no longer written to the note
(the stray "Hi" line). "Switch back to active mode" counts as one
command.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* build(deps): bodhi-realtime-agent 0.4.1, which exports GeminiLiveTranscribeSTTProvider

0.4.1 includes randombet/bodhi_realtime_agent#44, the Transcribe Live
provider that voice-agent now imports, and #42 (function-call behavior).
This clears the TS2305 import error and the bundle-smoke failure.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(voice): meeting notes subscribe to bodhi's dictation transcripts

Review: attachMeetingDictation captured provider.onTranscript and
replaced it after VoiceSession was built, taking over a callback that
bodhi's DictationController owns. bodhi 0.4.2 adds
VoiceSession.onDictationTranscript (randombet/bodhi_realtime_agent#46).
Meeting dictation now subscribes there instead:
- bodhi buffers each final before telling listeners, so the
  bufferSink hand-off is gone;
- partials are ignored;
- the provider is no longer passed in.

Bumps bodhi-realtime-agent to 0.4.2. That release also takes over the
provider's onPartialTranscript, so nothing in sutando may set it any
more.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(voice): serialize meeting enter/exit; carry the exit request; report unsaved lines

Review (Blue, reproduced against the real VoiceSession): enter() and
exit() changed notePath and lines outside bodhi's mode queue, so mode
switches that raced lost state.
- Exiting while entry was still starting the transcriber left the
  session in transcription.
- Entering during an unfinished exit kept transcription on with
  notePath=null.

Enter and exit now run one at a time, each after the previous one's
mode switch has settled. A failed entry clears its note state and
rethrows, so the caller rolls back and can retry.

The other review notes:
- An exit command addressed to Sutando may carry a request
  ("Sutando, come back and summarize"). It exits, and the request is
  passed to the agent.
- Lines that could not be appended still reach the agent. The exit
  message then says the notes are incomplete, not that they are saved.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(voice): keep CJK and numbers as meeting speech; address Sutando only at a sentence start

- isFiller tokenizes on Unicode letters/numbers, so CJK text and numbers are
  never filler: they stay in the note and cannot make a mention an exit.
- An addressed command counts only at the start of a sentence; a request is
  carried only when joined with "and"/"then". A further sentence after the
  command is recorded as meeting speech, not passed as a request. A mid-sentence
  mention ("We said Sutando come back online and ...") stays in the meeting.
- The note and transcript heading are written once transcription is on (or with
  the first line), so a failed entry leaves no orphan heading.
- Only the latest entry's failure turns meeting mode off.
- Log when the transcript cannot be injected into the session.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant