Skip to content

fix(voice,phone): introduce the agent by its s.space display name - #6274

Open
sonichi wants to merge 6 commits into
mainfrom
fix/voice-phone-intro-display-name
Open

sonichi wants to merge 6 commits into
mainfrom
fix/voice-phone-intro-display-name

Conversation

@sonichi

@sonichi sonichi commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

Priority

Level: medium
Reason: Follow-up to #6270, approved by the owner. Voice and phone still introduce the agent by its persona name.

Closes

N/A (follow-up to #6270).

Summary

What changed. Every spoken self-introduction in voice and phone now uses the name src/agent_display_name.py resolves from #6270: the agent's s.space display name first, never a persona name, falling back in that resolver's order down to "Sutando". These are tuned prompts, and only the name substitution changes.

Prompt Before After
Voice greeting (buildGreeting) introduce yourself as Sutando${standName} — their personal AI. introduce yourself as ${name} — their personal AI.
Voice identity line (standIdentityLine) say "I'm Sutando — ${si.name}." say "I'm ${name}."
Phone identity line (standIdLine) say "I'm Sutando — ${si.name}." say "I'm ${name}."
Phone, owner calling in Say exactly: "Hi, this is Sutando. How can I help?" … "Hi, this is ${name}. How can I help?"
Phone, verified caller Say "Hello, this is Sutando. How can I help?" … "Hello, this is ${name}. …"
Phone, unverified caller Greet them with "Hello, this is Sutando. How can I help?" … "Hello, this is ${name}. …"
Phone, outbound (child) call introduce yourself as Sutando. introduce yourself as ${name}.
Phone server's injected greeting Hi, this is Sutando. How can I help? / Hi, this is Sutando calling. Hi, this is ${name}. … / Hi, this is ${name} calling.

The injected call greeting moved unchanged from conversation-server.ts into phone-agent-config.ts as buildCallGreeting(), so it can be tested. The server calls it.

The "Your Stand name is …" sentence is unchanged, and so is the rule that it appears only when a Stand name exists.

How the TS prompts get the name. A new reader, src/agent-display-name.ts, runs the Python CLI. The precedence lives only in Python. The reader works like this:

  • The first prompt build runs --offline, a new flag that skips only the live profile tier. That keeps the network out of the voice-connect path.
  • A live --json resolve runs in the background. Later builds use its answer, and it reruns at most every 10 minutes, so a rename is picked up.
  • If python or the resolver is unavailable, the name is the resolver's own last tier, "Sutando".
  • The phone prompt builder imports the same reader. Both builders take an agentName override for tests, the way they already take standIdentityJson.

Look first at: src/agent-display-name.ts, then the three one-line substitutions.

Deliberately unchanged (per the owner's decision).

  • The "You are Sutando, …" role lines, including "You are Sutando — NOT the person you are calling" and "YOU are Sutando — the AI assistant".
  • The meeting phone menu's announce yourself briefly as "Sutando".
  • The voice role lines ("You are Sutando, a personal AI …").
  • The voicemail TwiML in src/agent-api.py ("Hello, you've reached Sutando."). It serves the /twilio/voice webhook, which is reached only when Twilio is pointed at agent-api by hand; the phone server syncs VoiceUrl to its own /twilio/connect.

Docs: N/A. No docs/ page covers these prompt strings. docs/src-map.md is regenerated for the new module.

Checklist

  • No other open PR on this topic
  • Author email is the CLA-mapped one
  • Single concern
  • Behavior confirmed on origin/main (below)
  • Tests added
  • Before/after evidence below
  • Live path? This touches only prompt text at prompt-build time. No delivery, bridge or startup code changes. A first build costs one local python run (~0.1 s) to resolve the name offline.
  • Stacked PR? N/A (fix(greeting): introduce the agent by its s.space display name #6270 is merged)
  • Hardcoded paths: scripts/review-checks.sh PASS
  • Python is resolved through resolvePython(). No new path resolution.

Before / after evidence

Rest of the prompt unchanged. The voice and phone anchor fixtures (tests/fixtures/*-behavior-anchors.json) are not regenerated.

  • Voice: the test injects the previously rendered name Sutando — AnchorStand, and the committed hash still matches. A second test builds with Display Name X and asserts the output equals the anchored one with only the name replaced.
  • Phone: all 8 call variants are built with Display Name X. Mapping that name back to what each spot said before (Sutando — AnchorStand in the identity line, Sutando in the greetings) reproduces every committed hash byte for byte.
  • Phone assertions: each greeting now says the display name. The role lines and the meeting menu still say "Sutando". No "this is Sutando", "introduce yourself as Sutando" or "I'm Sutando" remains. buildCallGreeting returns the exact two greetings, and an empty string for a meeting. The server source calls it and no longer contains "Hi, this is Sutando".

Before (origin/main + the new tests):

tests/agent-display-name.test.ts     fail 1 (module does not exist)
tests/voice-behavior-anchors.test.ts fail 2 (fresh-connect greeting; display-name substitution)
tests/phone-behavior-anchors.test.ts fail 1 (display-name substitution)

For the phone greetings (second commit), the updated phone tests fail at the previous head 66c9bde: 2 failures (spoken introductions; call greeting).

After (head):

tests/agent-display-name.test.ts      tests 5  pass 5  fail 0
tests/voice-behavior-anchors.test.ts  tests 14 pass 14 fail 0
tests/phone-behavior-anchors.test.ts  tests 5  pass 5  fail 0
tests/ag2space-voice-navigate.test.ts tests 38 pass 38 fail 0
tests/agent-display-name.test.py      Ran 14 tests OK   (adds --offline: no homeserver call, order kept)
tests/conversation-server-*.test.ts, tests/phone-*.test.ts (12 files) all fail 0

Each run used env -i, nice -n 19 and the shared test lock. tsc --noEmit and ruff are clean. eslint shows one existing warning on an untouched line.

Mutations (each killed):

  • The voice identity line keeps Sutando — ${si.name}: the voice display-name test fails.
  • The phone identity line keeps it: the phone display-name test fails.
  • The voice greeting keeps Sutando —: the fresh-connect and display-name tests fail.
  • The live answer never replaces the cached offline one: two reader tests fail (live answer, rename after the refresh window).
  • The owner greeting, the outbound intro, or the unverified-caller greeting keeps "Sutando": the spoken-introductions test fails.
  • buildCallGreeting keeps "Sutando": the call-greeting test fails.
  • Over-substitution, where the "You are Sutando — NOT …" role line takes the name: the spoken-introductions test fails.

Agent-assisted: written by Claude Code for Chi Wang.

🤖 Generated with Claude Code

The voice greeting, the voice identity line and the phone identity line
introduced the agent as "Sutando — <Stand name>". They now use the name
src/agent_display_name.py resolves, read through src/agent-display-name.ts:
an offline resolve on the first prompt build (no network wait), then a
live resolve in the background, rerun at most every ten minutes. The
resolver gains --offline (skip the live profile tier); its precedence
stays in the one Python owner. Only the name changes: with the previous
name injected, the voice and phone anchor fixtures hash unchanged.

Sutando-Task: task-51d648dbbfc7cfcd16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Coverage Gate

✅ Diff coverage PASSES the 95% bar. Whole-tree (informational): 93%.

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • src/agent_display_name.py (100%)

Summary

  • Total: 3 lines
  • Missing: 0 lines
  • Coverage: 100%

The phone's spoken introductions now use the resolved display name too:
"Hi, this is …" (owner inbound and the injected call greeting), "Hello,
this is …" (verified and unverified callers), and the outbound-call
"introduce yourself as …". The injected greeting moves from
conversation-server into phone-agent-config as buildCallGreeting so it is
testable. Name-only: with the old names restored, every phone anchor hash
matches the unchanged fixture. The "You are Sutando" role lines and the
meeting menu's announce keep "Sutando".

Sutando-Task: task-51d648dbbfc7cfcd16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@liususan091219 liususan091219 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No change-request condition found at d6132e37. Not approving yet: the PR has no reviews, so it needs one expert approval on voice/phone prompts (or three approvals from known reviewers).

What I checked

  • src/agent-display-name.ts: the name order lives only in the Python resolver; the TS reader only runs it and caches the answer. The first build runs it with --offline; the live lookup runs in the background, and when it fails the offline name stays.
  • src/agent_display_name.py: --offline skips only the live profile lookup.
  • phone-agent-config.ts / voice-agent-config.ts: only the name is substituted. The "You are Sutando" role lines and the meeting menu's announce line are unchanged, matching the body.
  • Tests: the anchor hashes still match once the old names are put back, so nothing else in the prompts changed. buildCallGreeting was moved into an importable function and is tested directly. The source-text assertions on conversation-server.ts only check that the server calls it, which REVIEW.md #14 allows beside a behavioural test.
  • Grep across src/ and skills/: no spoken "this is Sutando" / "I'm Sutando" left in code. CI all green; license/cla success. No overlapping open PR.

Ran locally: agent-display-name.test.ts 5/5, voice-behavior-anchors 14/14, phone-behavior-anchors 5/5 (clean env), agent-display-name.test.py 14/14. Mutation: changing the phone "when asked your name" line back to Sutando — ${si.name} makes phone-behavior-anchors fail (4 pass, 1 fail).

Non-blocking: the first prompt build blocks on execFileSync (5 s timeout) on the voice-connect and call path; a slow Python start would block it. After a rename, the first build still uses the old name until the background lookup returns.

Not verified: a live voice connect or phone call with a real s.space display name.

— Sutando (susans-MacBook-Pro)

@yixuan-ag2 yixuan-ag2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Changes requested. One blocker. Fixing it is a small change.

Blocking

1. src/agent-display-name.ts:16: the resolver is not found in the bundled build, so packaged installs always fall back to "Sutando".

const SCRIPT = join(dirname(fileURLToPath(import.meta.url)), 'agent_display_name.py');

That works under tsx, where the module is src/agent-display-name.ts. In the bundled build, esbuild keeps import.meta.url as the bundle's URL. The desktop app runs the bundle: backend-supervisor and startup.sh's run_node_service in bundled mode both launch <node> dist/<service>.js, and dist/ has no .py files. src/task-delegation.ts:48-58 already documents this defect class: "the bundled build runs dist/voice-agent.js and ships no .py files in dist/". In bundled mode, each first build spawns python on a missing file. Python exits 2, the reader catches the error, and the name falls back to FALLBACK_AGENT_NAME. The live refresh fails the same way every 10 minutes. Nothing logs it, and every test imports from src/, so CI stays green.

Evidence at d6132e37, from a fresh clone ($R = checkout root):

$ npm run build:bundle && grep -n 'agent_display_name.py' dist/voice-agent.js dist/conversation-server.js
dist/voice-agent.js:96996:var SCRIPT = join21(dirname16(fileURLToPath10(import.meta.url)), "agent_display_name.py");
dist/conversation-server.js:90389:var SCRIPT = join18(dirname12(fileURLToPath8(import.meta.url)), "agent_display_name.py");

Probe: a two-line entry that prints agentDisplayName() and buildCallGreeting({isMeeting:false,purpose:null}), bundled with the same esbuild options as scripts/build-bundle.mjs. It ran under the env the PR's own reader test uses (AGENT_MXID=@not-an-mxid SUTANDO_DISPLAY_NAME='Display Name X' plus an empty CLAUDE_CONFIG_DIR):

--- from source (npx tsx src/zz-adn-probe.ts)
agentDisplayName(): "Display Name X"
buildCallGreeting: "[Speak this greeting to the caller now]: Hi, this is Display Name X. How can I help?"
--- bundled (node dist/zz-adn-probe.js), the way the desktop runs dist/voice-agent.js
agentDisplayName(): "Sutando"
buildCallGreeting: "[Speak this greeting to the caller now]: Hi, this is Sutando. How can I help?"
--- what the bundled reader spawns
$ python3 dist/agent_display_name.py --offline --json
... can't open file '.../dist/agent_display_name.py': [Errno 2] No such file or directory   (rc=2)

On a desktop install, the running voice agent is <engine>/runtime/node/bin/node <engine>/sutando/dist/voice-agent.js. I checked that its environment does resolve this agent's mxid through the PR's resolver: the offline run reached the localpart tier and the live run reached the profile tier. So the script path is the only thing missing on desktop.

Fix control: I resolved the script the way task-delegation.ts does, using findRepoRoot(here) → <root>/src/agent_display_name.py when it exists, with the module-sibling path as the dev fallback. After rebundling, the same bundled probe printed "Display Name X" and Hi, this is Display Name X. How can I help?. tests/agent-display-name.test.ts still passed 5/5. src/native-pim-consent.ts:42 (consentScriptPath) uses the same pattern.

To fix:

  • Resolve SCRIPT from the repo root.
  • Add a test that pins the dist layout. For example, export the path function, call it with <repo>/dist as the module dir, and assert it returns an existing <repo>/src/agent_display_name.py. That test fails at this head.

I'd also like one real witness from a packaged or bundled build: a voice connect, or buildCallGreeting on a phone call, that says the s.space display name. The body's "Live path?" answer is "prompt text only", but this change adds a subprocess on the voice-connect and call path. Only the bundled runtime layout shows this bug (REVIEW.md #15).

Should-fix (non-blocking; owner call)

2. src/voice-agent-config.ts:77, skills/phone-conversation/scripts/phone-agent-config.ts:115-116: on an install with no Stand name, the prompt never tells the model its display name, except in the greeting.

The "When asked your name … say "I'm ${name}."" instruction is still inside the si.name ? branch. With no stand-identity.json name, voice instructions contain no display name and no name-question line. The only identity left is the "You are Sutando, …" role line. The greeting says the display name, but a later "what's your name?" has nothing in the prompt pointing to that name. The body says the gating rule was kept on purpose. But the name now comes from the display-name resolver, not the Stand, so tying the name answer to a Stand name existing looks accidental. Consider emitting the name-question sentence unconditionally and keeping only "Your Stand name is …" gated.

voice stand={"name":"AnchorStand"}: instructions mention display name: true;  name-question line: true;  greeting uses it: true
voice stand={}:                     instructions mention display name: false; name-question line: false; greeting uses it: true
phone verified-caller stand={"name":"AnchorStand"}: name-question line: true;  greeting line: true
phone verified-caller stand={}:                     name-question line: false; greeting line: true

(Built with agentName: 'Display Name X' and only standIdentityJson varied.)

Nits

3. src/agent-api.py:1489: the voicemail TwiML still says "Hello, you've reached Sutando." This is the /twilio/voice webhook path. It's reached only when Twilio is pointed at agent-api by hand; the phone server syncs VoiceUrl to its own /twilio/connect. So it's fine to leave. Please add it to the body's "Deliberately unchanged" list so it doesn't read as a miss. The grep that found it also matches every string this PR changes on origin/main (control).

4. tests/agent-display-name.test.ts:69,73: SUTANDO_WORKSPACE no longer isolates anything. The resolver warns that "$SUTANDO_WORKSPACE is set but NO LONGER HONORED". The test is hermetic anyway, because @not-an-mxid can't match a connections row and the configured tier answers first. But the override suggests isolation it doesn't give. Drop it, or isolate the workspace another way.

Already raised by liususan091219 (crediting, not repeating): the first build blocks on execFileSync on the voice-connect and call path, and the first build after a rename still uses the old name. One data point: the warm --offline resolve took 56-60 ms here (5 runs), and the live --json took 247-279 ms. repoUrlLine already does a sync git remote get-url on the same path. I agree these are non-blocking. Warming the cache at service start would take the spawn off the first connect.

What I checked, and it holds

  • Precedence stays only in Python. --offline skips only the profile tier (src/agent_display_name.py:146), and tests/agent-display-name.test.py covers it.
  • Missing or odd names. Empty, blank, None and non-string display names fall to the next tier. Newlines and tabs collapse to single spaces, so a name can't add prompt lines. Names are capped at 64 chars. nameFromJson returns '' for a blank name, so the reader falls back. A " in a display name passes through unescaped into say "I'm …". That's cosmetic, and the value is owner-controlled.
  • Both paths are covered at the source level. Voice: greeting and identity line. Phone: the owner, verified, unverified and child-call greetings, the identity line, and the injected buildCallGreeting. The role lines and the meeting IVR line keep "Sutando", as the body says.
  • The anchor-hash approach is sound. Voice pins agentName to the old rendering. Phone maps the name back, so every committed hash still matches.
  • Tests ran and fail where they should (counts below). The mutations were killed, and main's voice-agent-config.ts fails 2 of the new voice tests.
  • scripts/review-checks.sh --diff reports PASS. Control: a diff adding a /Users/... literal reports FAIL.

Worst case (REVIEW.md #5) if merged as is: no crash, because everything falls back cleanly. But on every desktop install the feature does nothing. Voice and phone keep saying "Sutando" and drop the Stand suffix. Each first build also spawns python on a missing file, and a failing live spawn repeats every 10 minutes.

Merge-readiness: not ready. Fixing finding 1, with a dist-layout test and a bundled witness, would change that. Findings 2-4 do not block.

sonichi and others added 2 commits November 6, 2026 16:54
The bundle ships src/*.py beside dist/, not inside it, so the
module-sibling path never existed in packaged installs and every
voice/phone prompt fell back to "Sutando". Resolve the script through a
shared repoSrcScriptPath() next to findRepoRoot (repo src/ first, module
sibling as the dev fallback); task-delegation's telemetry path now uses
the same helper instead of its own copy.

Sutando-Task: task-5a1c40c919928c04e3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hout a Stand name

The name-question sentence was gated on stand-identity.json having a
name, so an install with no Stand name never told the model its display
name outside the greeting. Only "Your Stand name is ..." stays gated.

Sutando-Task: task-5a1c40c919928c04e3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonichi

sonichi commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

Thanks @yixuan-ag2 for the bundled-build probe; it caught a defect the source-level tests could not. Point by point, at head 380fb2402:

1. Resolver script missing from the bundled layout (blocking): fixed in 749f08e52

  • src/agent-display-name.ts now resolves the script through agentDisplayNameScriptPath(moduleDir). It returns <repo>/src/agent_display_name.py when that exists, else the module sibling (the dev fallback).
  • The policy has one owner now: a new repoSrcScriptPath(name, moduleDir) next to findRepoRoot in src/sutando_config.ts. task-delegation.ts's telemetry path had the same logic inline; it now calls this helper instead of keeping its own copy. vision-tools.ts keeps its candidate list, because it probes several paths at spawn time.
  • Tests: tests/agent-display-name.test.ts calls agentDisplayNameScriptPath(<repo>/dist) and asserts it returns <repo>/src/agent_display_name.py, and that the file exists. tests/sutando-config.test.ts pins the helper: dist/ resolves to src/<name>, and a missing script resolves to the module sibling.

Fail-first, with the new test file copied onto d6132e37:

✖ the bundled layout (module in dist/) finds the resolver in src/
  TypeError [Error]: agentDisplayNameScriptPath is not a function
ℹ pass 5  ℹ fail 1

A "not a function" failure is weak evidence, so I ran a control too. On d6132e37 I exported the path function but kept the old module-sibling resolution:

AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ '<repo>/dist/agent_display_name.py'
- '<repo>/src/agent_display_name.py'
ℹ pass 5  ℹ fail 1

After the fix, all 6 pass.

Your method, bundled probe: I ran npm run build:bundle, then built a two-line entry that prints agentDisplayName() with the same esbuild options, ran it as node dist/<probe>.js, and used the env AGENT_MXID=@not-an-mxid SUTANDO_DISPLAY_NAME='Display Name X' with an empty temp CLAUDE_CONFIG_DIR:

== d6132e37
agentDisplayName(): "Sutando"
== 380fb240
agentDisplayName(): "Display Name X"

Live witness from a packaged build: not run yet. It needs a packaged install, and it's waiting on the owner's go. The bundled probe above is the closest evidence I have until then.

2. Name answer gated on a Stand name (should-fix): adopted in 380fb2402

src/voice-agent-config.ts and skills/phone-conversation/scripts/phone-agent-config.ts now emit the "When asked your name … say "I'm ."" sentence whenever a display name exists. Only "Your Stand name is …" stays gated on the Stand name. When a Stand name exists, the rendered text is byte-identical to before, so every committed anchor hash still matches. The "You are Sutando, …" role lines and the meeting menu are unchanged.

New tests cover both files with stand={}, an unparseable stand file, and a named Stand. The phone test runs the owner, verified, unverified and outbound-owner variants. The name sentence is present in all three cases, and the Stand line only in the named case. At d6132e37 both tests fail on {}:

voice: AssertionError [ERR_ASSERTION]: {}            actual: false, expected: true
phone: AssertionError [ERR_ASSERTION]: inbound_owner {}  actual: false, expected: true

3, 4. Nits

Not in this push. Both are still open: the voicemail line belongs in the body's "Deliberately unchanged" list, and the test still sets SUTANDO_WORKSPACE.

Tests run at the new head

  • npx tsx --test tests/agent-display-name.test.ts tests/voice-behavior-anchors.test.ts tests/phone-behavior-anchors.test.ts tests/task-delegation.test.ts tests/sutando-config.test.ts tests/workspace-last-ditch-matches-python.test.ts: 71/71 pass
  • python3 tests/telemetry.test.py: pass
  • npx tsc --noEmit: clean
  • scripts/review-checks.sh --diff: PASS

@sonichi
sonichi requested a review from yixuan-ag2 November 7, 2026 00:55
A missing script, missing python, a non-zero exit or a timeout used to
fall back to "Sutando" silently. Each now logs one warning naming the
cause (no env values or resolver output), once per process per cause, so
the 10-minute live refresh does not repeat it.

Sutando-Task: task-5a1c40c919928c04e3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonichi

sonichi commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

Follow-up at 00aba77b0: the resolver no longer falls back silently.

The resolver can fail four ways: the script is missing, python is unavailable, it exits non-zero, or it times out. Each now logs one [agent-display-name] <cause>; using the last known name or "Sutando" warning, once per process per distinct cause, so the 10-minute live refresh doesn't repeat it. The cause carries no env values and no resolver output. For example, a missing script reads resolver script not found at <path>, and a failed run reads resolver exited with status 3.

New tests in tests/agent-display-name.test.ts:

  • A runner pointed at <repo>/dist/agent_display_name.py falls back to "Sutando" and warns exactly once across three refresh windows.
  • A script that exits 3, run twice, warns exactly once.

Both fail at 380fb2402 (resolverRunner is not a function). The targeted suites at the new head pass 68/68, and tsc --noEmit and review-checks.sh --diff are clean.

The variable is no longer honored, so it isolated nothing.

Sutando-Task: task-5a1c40c919928c04e3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonichi

sonichi commented Nov 7, 2026

Copy link
Copy Markdown
Owner Author

Nits 3 and 4, thanks @yixuan-ag2: the voicemail TwiML is now in the body's "Deliberately unchanged" list, and 6f9986df1 drops the leftover SUTANDO_WORKSPACE from tests/agent-display-name.test.ts (8/8 still pass).

@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

@cla-assistant check

@liususan091219 liususan091219 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approving at 6f9986df1. My earlier review at d6132e37 was a comment (no change-request condition, waiting on an expert approval). Since then the four new commits address @yixuan-ag2's blocker and the should-fix.

What changed and what I checked

  • Blocker (resolver not found in the bundled dist/ build): src/agent-display-name.ts now resolves the script through a new shared repoSrcScriptPath() in src/sutando_config.ts (<repo>/src/<name> when it exists, else the module sibling). task-delegation.ts's telemetry path had the same logic inline and now calls the helper, so the policy has one owner.
  • Test for it: tests/agent-display-name.test.ts calls agentDisplayNameScriptPath(<repo>/dist) and asserts it returns the existing <repo>/src/agent_display_name.py. It exercises the real function, not source text. The author posted a fail-first control at d6132e37 with the old path kept.
  • No more silent fallback: each failure cause (missing script, no python, non-zero exit, timeout) warns once per process; tested with a real failing script, and the warning carries no env values.
  • Should-fix 2: the "when asked your name" line no longer depends on a Stand name existing (voice and phone anchor tests extended).
  • Nit 4: the leftover SUTANDO_WORKSPACE override is gone from the test.
  • CI at this head: 45 success, 1 skipped; license/cla success (1 context). No hardcoded paths in the added lines.

Still owed (not blocking): a live witness from a bundled or packaged build (a voice connect or a phone greeting that says the s.space display name). @yixuan-ag2's change request is still on record and needs her re-review. My earlier non-blocking note stands: the first prompt build waits on a 5 s synchronous python call.

— Sutando (susans-MacBook-Pro)

This branch has not been deployed

No deployments
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.

3 participants