Skip to content

feat(cli): add Goose (AAIF) as the 16th CLI vendor - #524

Closed
nt-nerdtechnic wants to merge 6 commits into
mainfrom
feat/goose-vendor
Closed

nt-nerdtechnic wants to merge 6 commits into
mainfrom
feat/goose-vendor

Conversation

@nt-nerdtechnic

@nt-nerdtechnic nt-nerdtechnic commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds Goose (AAIF, formerly Block — aaif-goose/goose) as the 16th CLI vendor at tier L4: install detection, launch, kickoff-marker session binding, a SQLite reader (turn end, reply text, tokens) and goose session -r --session-id <id> resume with a db preflight, plus a screen awaitingInput pattern for the tool-approval prompt.

Why

User decision 2026-10-20 23:27 (0.2.28). Research note n6 in plan cli-10-19-0-2-28_411e93 was source-only; this PR verifies each fact live before relying on it.

Live verification (scratch only)

goose 1.55.0, goose-aarch64-apple-darwin.tar.gz sha256 153425d6dc3a49afce85e70009eff87f6020e3ed029bb56fae1b523f7f2d8107 (matches the GitHub asset digest), binary sha256 cabeb1c0…2491844c. Run with env -i, a scratch HOME/XDG dirs/GOOSE_PATH_ROOT, GOOSE_DISABLE_KEYRING=1, GOOSE_TELEMETRY_OFF=1, against a loopback mock OpenAI endpoint started for the run (no account, no credential, no provider call, no global install; goose has no self-running updater). Findings that changed the design:

  • macOS data dir is the XDG one (~/.local/share/goose/sessions/sessions.db), not ~/Library/Application Support as the research note said (goose info).
  • -n <name> is not unique: reusing a name creates a new session (20261020_2), so binding uses the kickoff marker, not names. Session ids are YYYYMMDD_N in UTC.
  • goose session -r --session-id <id> resumes; an unknown id exits with no such session exists → session_exists asks the db.
  • Text and a tool call of one model response are one messages row (verified by streaming them as separate chunks), and the loop ends on a response without a tool request → an agent-visible text-only assistant row is the turn end.
  • Ctrl+C mid-response writes no row: that turn is seen to end only when the next prompt starts (disclosed in the docs; no silence timer added).
  • usage_ledger has one row per model call; input_tokens already includes cache (goose-provider-types token_usage.rs), matching TokenUsage.
  • Approve-mode prompt ◆ Goose would like to call the above tool, do you allow? (cliclack); ESC[?2004h at startup, no ESC[?1049h.
  • --version prints a bare 1.55.0; pressly's migration tool also installs goose (goose version: v3.x), so identity_regex accepts only the bare shape.

Not wired (left unsupported, stated in docs): MCP, skills, plugin hooks/Guard, usage/quota, account switching, model flag; Windows path (%APPDATA%\Block\goose\data) and Windows install are source-only (wizard shows the docs link on win32).

Test plan (red → green)

  • Red: on origin/main import agent_team_backend.cli_vendors.goose → ModuleNotFoundError, so backend/tests/vendors/test_goose.py and the [goose] contract cases cannot run.
  • Green (safe-pytest, sandboxed, fake-security calls: 0):
    • safe-pytest.sh <wt> -n 1 -k "test_goose or test_cli_vendors_registry or test_install_deps_snapshot or test_risk_declarations or test_cli_launch_argv or test_native_memory or test_cli_extensions or goose or test_catalog" → 208 passed
    • safe-pytest.sh <wt> -n 1 -k goose -rA → 24 passed, incl. test_vendor_reader[goose], test_vendor_resume[goose], test_vendor_launch[goose]
  • Frontend: pnpm vitest run src/renderer/src/platform/plugin-shell/agents tests/cli/vendorContracts.test.ts src/renderer/src/components/__tests__/CliAgentsHelp.test.ts src/renderer/src/platform/plugin-shell/lib/cliPermission.test.ts src/renderer/src/platform/plugin-shell/lib/resume-command.test.ts plugins/navide-plans src/renderer/src/lib/__tests__/quotaFailover.test.ts --maxWorkers=1 → 27 files, 584 passed
  • pnpm typecheck → exit 0; ruff check on changed Python → clean.
  • Fixture tests/fixtures/cli-regression/goose.json (provenance recorded): the real schema from the 1.55.0 db and the recorded row shapes, with fixture text/ids/counts.

Regression: existing plugins / features

The change is additive: one new vendor file per side plus registration lines. No shared module gained a goose branch; the only shared-harness change is VendorData setting GOOSE_PATH_ROOT (read by goose only) so the Windows runner keeps the goose store inside the scratch home. Plans/Git/mini-IDE, messaging, channels and account switching code are untouched; the Plans retained-spec parity test (plugins/navide-plans, 74+82+… tests above) passes with the new row. Full suites are left to CI.

Protection check

  • Credential / account-switch / quota / usage paths: git diff 49721cd8e -- 'backend/agent_team_backend/credential_*' 'backend/agent_team_backend/quota_*' 'backend/agent_team_backend/usage_*' | wc -l → 0. Goose declares no account_switch, fetch_usage or credential fields.
  • No function deleted: git diff 49721cd8e | grep -E '^-\s*(def |async def |export (function|const)|class )' → no match.
  • Signature changes: none.
  • Limits: none added or changed.
  • gitleaks: default rules on a clean clone without the repo's .gitleaks.toml/.gitleaksignore → 0 leaks (canary detected).
  • Merge with main: branch base 49721cd8e; files changed on main since (fix(claude): read the 2.1.304 resume dialogs as awaiting input #507, fix(registry): local Registry applies native backend package rules; prefix error names the prefix #510) do not overlap this PR (comm -12 empty).

Follow-ups on this branch

  • 57c97b1c3 closes five shared inventories the 16th vendor had missed (CI on 989d40a6c): cli_vendors.goose in the PyInstaller hiddenimports; osplat.platform_id instead of sys.platform in goose.py; the + menu roster scroller raised from 360px (fifteen rows) to 384px with ADD_MENU_MAX_H 450 → 474; TURN_START_SIGNAL.goose = true; and the feat(cli): disclose a CLI newer than its verified version in the startup probe #502 version-drift check.
  • Disclosed exception — version drift (decision: deferred to 0.2.29). feat(cli): disclose a CLI newer than its verified version in the startup probe #502's startup probe adds an "untested version" note by comparing --version with AccountSwitchSpec.verified_version. Goose has no account-switch adapter, so it has no verified_version and the note never appears for goose panes in 0.2.28. test_spawn_probe_version_drift.py lists goose as the single exception (_NO_ACCOUNT_SWITCH) and still asserts the other 15 vendors carry one; the vendor matrix says the same. Giving goose the note needs a version field independent of account switching — planned for 0.2.29.
  • 820881be6 merges main fb1729cd6 (incl. fix(kimi): read Kimi Code 0.39+/2.x state.json cwd and turn.ended; name the archived kimi-cli #531 Kimi); the only conflict was the version-on-record note in docs/en-US/cli-vendor-matrix.md, resolved by keeping both sides.

🤖 Generated with Claude Code

Goose keeps every session in one SQLite db (schema v17). The reader reads
it like OpenCode's: kickoff-marker binding on user rows of top-level
interactive sessions, tokens from usage_ledger (input already includes
cache), and a text-only agent-visible assistant row as the turn end.
Resume is `goose session -r --session-id <id>` with a db preflight.

Facts recorded live from goose 1.55.0 in a scratch HOME/GOOSE_PATH_ROOT
against a loopback mock endpoint (no account, keyring and telemetry off):
the macOS data dir is the XDG one, `-n` names are not unique, text and a
tool call of one response share a row, Ctrl+C writes no row, the approve
prompt is a cliclack select, bracketed paste on, no alternate screen.

Not wired: MCP, skills, plugin hooks, usage/quota, account switching,
model flag. pressly's migration tool also ships `goose`; identity_regex
accepts only goose's bare version output.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
nt-nerdtechnic and others added 5 commits October 21, 2026 01:42
…by default

review-524 MEDIUM-1. Goose has no permission-bypass flag because its default
GOOSE_MODE=auto already approves every tool, and Navide's Guard does not
cover Goose yet; the help table showed only "—" in the flag column, the same
as CLIs that ask first. The Goose row now says so in en-US, zh-TW and ja-JP
and how to be asked (GOOSE_MODE=approve or smart_approve). Disclosure only:
Goose's launch command and behaviour are unchanged, no limit added.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CI on #524 found five places the Goose vendor had not reached:

- The packaged backend's hiddenimports did not list cli_vendors.goose
  (test_pyinstaller_spec).
- goose.py branched on sys.platform; it now takes osplat.platform_id like
  droid, with a platform argument for tests (test_osplat).
- The + menu roster scroller was capped at 360px, which carries fifteen
  CLIs: the sixteenth was cut off. Raised to 384px, and the flip threshold
  with it (ControlPane.addMenu).
- TURN_START_SIGNAL did not classify goose. Its reader reports the user's
  prompt, so it gets the turn watch (submitTurnConfirm).
- The version-drift check from main (#502) expects every vendor to carry an
  account-switch verified_version. Goose has no account-switch adapter, so
  it is listed as the one exception and its probe stays quiet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings in #531 (Kimi Code). docs/en-US/cli-vendor-matrix.md conflicted in
the version-on-record note: kept both the goose sentence and main's
reworded (silence) bullet, and noted that the untested-version probe note
never appears for goose (planned for 0.2.29). goose.py line ref updated.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nt-nerdtechnic
nt-nerdtechnic marked this pull request as ready for review October 21, 2026 01:20
nt-nerdtechnic added a commit that referenced this pull request Oct 21, 2026
Squash-merged from origin/pr-524.

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

Copy link
Copy Markdown
Collaborator Author

Squash-merged into main as b361afe.

nt-nerdtechnic added a commit that referenced this pull request Oct 21, 2026
Translate the 55 en-US strings that landed after the catalogs were cut
(#515, #524, #530) and check ko-KR in the message syntax test.

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