Skip to content

Suggest roster-aware agent names#239

Open
orangewk wants to merge 1 commit into
fujibee:mainfrom
orangewk:codex/roster-aware-name-suggestions
Open

Suggest roster-aware agent names#239
orangewk wants to merge 1 commit into
fujibee:mainfrom
orangewk:codex/roster-aware-name-suggestions

Conversation

@orangewk

Copy link
Copy Markdown
Contributor

Summary

This draft implements the onboarding half of #178: when an agent is not yet registered for a project, whoami.sh now appends roster-aware unused identity name suggestions.

The goal is to avoid defaulting humans and agents toward ambiguous tool labels like cc / codex when multiple sessions of the same type may coexist. The suggestions are identity names from a bundled pool, e.g. noether, lovelace, turing, gauss, rather than type prefixes.

Design

  • Add scripts/lib/roster.sh as a read-only helper:
    • agmsg_roster_names <team> lists current team member names from the team registry.
    • agmsg_suggest_names <team> [count] walks a bundled identity-name pool deterministically and skips names already present in the roster.
  • Add scripts/data/name-pool.txt as read-only data, not sourced code.
  • Keep suggestions advisory. This does not guarantee uniqueness between suggest and join, and it does not change the identity model or join.sh semantics.
  • Update whoami.sh only on join-needed paths:
    • not_joined=true ... suggested=<n1,n2,...>
    • suggest=true ... suggested=<n1,n2,...>
  • Leave exact and multiple identity paths unchanged.
  • Update agent templates and SKILL.md so agents show suggested= as optional unused identity names.

Explicitly out of scope for this draft

  • Making spawn.sh <type> work without a positional name.
  • Guaranteed unique allocation under registry-lock.
  • Agent-name validation for arbitrary user-provided names.

Those are reasonable follow-ups, but this PR keeps #178 to an additive suggestion flow.

Verification

  • bash -n scripts/lib/roster.sh scripts/whoami.sh scripts/join.sh scripts/team.sh
  • Manual isolated-skill smoke tests for:
    • no-team not_joined includes suggested=
    • exact match does not include suggested=
    • same-type reuse suggest=true includes unused suggested= names
    • multiple identities do not include suggested=
    • suggested names avoid existing roster members
  • git diff --check

BATS was not available in the local Git Bash environment. I added tests/test_roster.bats and extended tests/test_team.bats; CI should run them.

@orangewk orangewk left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Review (draft) — findings first

Overall this matches the agreed minimal design and reads well. One blocking item, otherwise non-blocking + nits. Reviewed the branch locally.

🔴 Blocking

B1 — empty-roster suggestion errors on bash 3.2 (macOS).
scripts/lib/roster.sh:99 (and defensively :110): agmsg_roster_contains "$candidate" "${roster[@]}". whoami.sh runs under set -euo pipefail, and on first run / a brand-new team the roster array is empty. On bash < 4.4 (macOS /bin/bash is 3.2) "${empty[@]}" under set -u raises unbound variable; bash 4.4+ is fine. Verified working on bash 5.2 (Git Bash) — it emits 5 names with an empty roster — so this is macOS-3.2-specific and not reproducible on Linux/Windows CI. agmsg explicitly targets bash 3.2 (see the lib/registry-lock.sh rationale).

Effect: the command-substitution subshell errors; whoami masks it via the assignment so it does not hard-fail, but suggested= comes back empty (plus an unbound variable line on stderr) — i.e. the feature silently no-ops on a primary platform, exactly on the first-run path #178 targets.

Fix (one line, both sites): ${roster[@]+"${roster[@]}"} (bash-3.2-safe alternate-value expansion), or an early [ "${#roster[@]}" -eq 0 ] branch. The "${pool[@]}" at :108 is already guarded non-empty at :93.

🟡 Non-blocking

  • Test gap (would have caught B1): no test exercises an empty roster under set -u. test_roster.bats uses bash -c without set -u, and the whoami not_joined test pre-joins a team so FIRST_TEAM is non-empty. Add a true no-teams whoami run, or bash -c 'set -u; source …; agmsg_suggest_names <empty-team> 5'.
  • Reuse-path collision scope: in the suggest=true path the names are checked only against FIRST_TEAM's roster; if the user joins a different team the "unused" property doesn't hold. Advisory, so fine — a one-line note in the template ("suggestions are relative to the first listed team") would clarify.

⚪ Nit

  • Pool ordering: the pool is alphabetical, so the linear walk yields same-initial clusters (offset bbanach bell bernoulli boole brahe). Interleaving domains/initials in name-pool.txt would make contiguous picks feel more varied; determinism is unaffected.

✅ Confirmed good

  • roster_names is Windows/CRLF-safe (agmsg_sqlite_mem strips CR; agmsg_sql_readfile_path does cygpath -w).
  • Names are JSON keys, so roster_names is registration-shape-agnostic — no legacy-array normalization needed (correct).
  • whoami additions are line-end additive; agent= / multiple= paths untouched → existing parsers safe.
  • Deterministic (cksum offset, no $RANDOM) — verified identical across runs.
  • Templates use __SKILL_NAME__, not a hardcoded /agmsg.
  • Pool is identity names, lowercase ASCII, no tool labels — matches the #178 intent; charset is re-enforced at read time.
  • Scope is the agreed minimal cut (spawn auto-pick + guaranteed-unique allocation excluded and noted in the PR body).

Fix B1 and I'd consider this mergeable.

@orangewk orangewk force-pushed the codex/roster-aware-name-suggestions branch from 45bcee2 to 835c47b Compare June 26, 2026 15:04

@orangewk orangewk left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-review — B1 resolved ✅

Verified 835c47b locally.

  • B1 fixed correctly. scripts/lib/roster.sh:99 and :110 now use ${roster[@]+"${roster[@]}"}, the canonical bash-3.2-safe empty-array expansion. Re-ran the failing condition (set -u + empty roster): exit 0, 5 names, clean stderr. bash -n clean. Correct by construction for bash < 4.4 as well.
  • Regression tests addedroster: suggestions are safe with empty roster under set -u (asserts count == 5) and whoami: first run with no teams includes suggested names. The first is the solid guard for B1.

⚪ New nit (test quality, non-blocking)

tests/test_roster.bats:40[[ ! "$output" =~ "suggested=$" ]]. Quoting the RHS makes $ a literal, so this matches the literal string suggested=$ and passes vacuously (it does not assert the value is non-empty). Verified: both suggested=ada,… and an empty suggested= pass it. Drop the quotes (=~ suggested=$) to actually anchor end-of-line. Non-blocking — the empty-roster count == 5 test already covers non-emptiness; this assertion is just redundant-and-inert as written.

Caveat (same as before): both empty-array regression tests only bite on a bash < 4.4 leg — on bash 4.4+ the pre-fix code also passed. Worth confirming CI exercises a bash-3.2 / macOS-system-bash leg so the guard isn't latent.

B1 cleared. From my side this is mergeable once it comes out of draft; the remaining items are non-blocking (NB2 reuse-scope note, pool-ordering nit, the test nit above).

@orangewk orangewk force-pushed the codex/roster-aware-name-suggestions branch from 835c47b to fa20b6c Compare June 26, 2026 15:19
@orangewk orangewk marked this pull request as ready for review June 26, 2026 15:19
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