Commit graph

752 commits

Author SHA1 Message Date
A
050cdfdf21
test: add 58 tests for untested internal helper functions in commands.ts (#559)
Cover groupByType, buildAgentLines, buildCloudLines, credentialHint,
mapToSelectOptions, buildRecordLabel, buildRecordHint, and
resolveDisplayName edge cases. Uses the established replica pattern
since these functions are not exported.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 16:47:34 -08:00
A
fad2560a23
feat: Add netcup/plandex implementation (#558)
Implements Plandex on Netcup VPS using netcup/lib/common.sh primitives.
Updates manifest.json to mark netcup/plandex as implemented.
Updates netcup/README.md with Plandex usage instructions.

Agent: gap-filler-netcup

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 16:43:23 -08:00
A
a7291ac98b
feat: Add local/interpreter implementation (#557)
Implements Open Interpreter on local machine using local lib/common.sh primitives.

Agent: gap-filler-local

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 16:41:37 -08:00
A
1bdf6012e0
feat: Add ramnode/nanoclaw implementation (#556)
Agent: gap-filler-ramnode

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 16:41:33 -08:00
A
67297c0e2c
fix: add actionable guidance to exit code 126 and 137 failure messages (#555)
Exit codes 126 (permission denied) and 137 (killed/OOM) previously
showed terse one-line messages with no suggestions for what to do.
Now they include specific causes and remediation steps, consistent
with all other exit codes in getScriptFailureGuidance.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 16:40:05 -08:00
A
3679fd2b3a
fix: redirect echo to stderr in get_model_id_interactive to prevent JSON corruption (#554)
The `echo ""` on line 351 of get_model_id_interactive() was going to
stdout, causing it to be captured by command substitution into MODEL_ID.
This injected a newline into the openclaw.json config, breaking JSON
parsing with "invalid character '\n' at 15:0".

Fixes #553

Agent: issue-fixer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 16:28:21 -08:00
A
7c693db35b
refactor: extract check_ssh_key_by_fingerprint into shared helper (#552)
13 cloud providers had identical 5-line check_ssh_key functions that
fetch SSH keys from the provider API and grep for the fingerprint.
Extract this pattern into a shared check_ssh_key_by_fingerprint helper
in shared/common.sh, reducing each cloud's function to a single line.

Affected clouds: BinaryLane, Cherry, Civo, Contabo, DigitalOcean,
Genesis Cloud, Hetzner, Hostinger, Latitude, Linode, OVH, Scaleway,
Vultr.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 16:12:07 -08:00
A
11b5567b20
test: add 130 tests for index.ts dispatch routing, flag extraction, and error paths (#551)
Cover untested functions from recent PRs (#531, #537, #540, #549):
- extractFlagValue: value extraction, missing value detection, flag-as-value
- parseListFilters: -a/--agent, -c/--cloud, positional filter, error paths
- handleDefaultCommand: help-as-cloud, dry-run error, prompt-no-cloud routing
- dispatchCommand: immediate, list, subcommand, verb alias, default routing
- hasTrailingHelpFlag: trailing help detection, first-position exclusion
- warnExtraArgs (getExtraArgs): extra positional arg detection
- KNOWN_FLAGS completeness: all 15 flags including new -a/-c/--agent/--cloud
- LIST_COMMANDS: verify 'history' alias (PR #540) is included

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 16:02:15 -08:00
A
08104e1afb
fix: add actionable guidance to instance timeout and auth failure errors (#550)
The generic_wait_for_instance timeout message previously just said
"did not become active in time" with no guidance. Now it follows the
same pattern as generic_ssh_wait by telling users what to do next.

Similarly, _validate_token_with_provider now shows the env var name
so users can set it directly instead of re-running interactively.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 16:00:09 -08:00
A
407f79e7b5
fix: improve spawn list UX with positional filters and long flags (#549)
- Support `spawn list claude` as shorthand for `spawn list -a claude`
- Add --agent and --cloud as long-flag aliases for -a and -c
- Fix flaky cmdlist-integration tests by priming manifest cache in
  beforeEach and isolating XDG_CACHE_HOME to prevent cross-test leakage
- Export _resetCacheForTesting from manifest.ts for deterministic tests
- Update help text with new filter syntax and examples

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 15:46:39 -08:00
B
7c03d215f2 docs: Sync README matrix with manifest.json
Agent: team-lead
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 23:46:01 +00:00
A
cc23013e7c
fix: validate MODEL_ID from environment to prevent command injection (#548)
The get_model_id_interactive function returned MODEL_ID from env vars
without calling validate_model_id, bypassing the allowlist check. Also
migrated 13 legacy scripts from raw safe_read to get_model_id_interactive
which includes validation.

Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 15:41:10 -08:00
B
46349ab8c0 docs: Sync README matrix with manifest.json
Agent: team-lead
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 23:39:18 +00:00
A
62a28312f1
fix: remove double-quoting in openclaw.json config generation (#547)
The json_escape function already adds quotes around strings, so using
"%s" in printf was adding a second set of quotes, resulting in invalid
JSON like `"OPENROUTER_API_KEY": ""value""`.

Fixed railway/openclaw.sh and koyeb/openclaw.sh to use %s (unquoted)
for API key and token fields, matching the correct pattern used in
fly/openclaw.sh and shared/common.sh.

Fixes #542

Agent: issue-responder

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-11 15:38:01 -08:00
A
8459e2b2f6
test: add 33 tests for cmdList display-name filter resolution and picker helpers (#545)
Cover the untested filter resolution path added in PR #537 where
cmdList resolves display names (e.g., "Claude Code" -> "claude") before
querying history. Also cover buildRecordLabel/buildRecordHint helpers
from PR #531 and the double-quote escaping in rerun prompt suggestions.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 15:36:51 -08:00
A
385a8a9b56
refactor: split 3 large test functions in test/run.sh into focused units (#544)
- _test_browser_and_cloud_init (94 lines) -> _test_open_browser (54) + _test_cloud_init (42)
- test_common_source (87 lines) -> _test_sprite_functions_and_syntax + _test_sprite_log_and_name + _test_sprite_remote_source
- _test_json_ssh_utils (59 lines) -> _test_json_escape + _test_ssh_key_utils (49)

All 75 tests pass. No behavioral changes.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 15:34:06 -08:00
A
d624c9219c
test: add 22 tests for history MAX_HISTORY_ENTRIES trimming and boundaries (#541)
The saveSpawnRecord MAX_HISTORY_ENTRIES=100 trimming was completely untested.
These tests cover: trimming at boundary (99->100, 100->101), trimming well
over limit (150+1), prompt preservation through trimming, sequential saves
crossing the limit, filterHistory reverse-chronological ordering, boundary
conditions (empty/missing dir), and file format after trimming.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-11 15:18:23 -08:00
A
52904a9163
fix: add 'spawn history' alias for 'spawn list' and document aliases in help (#540)
The word "list" is ambiguous in a CLI that also has "spawn agents" and
"spawn clouds" -- users naturally expect "spawn list" to list resources,
not show history. Adding "spawn history" as a first-class alias makes
the history command more discoverable. Also documents both aliases (ls,
history) in the help text.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 15:13:32 -08:00
A
e97a061129
refactor: reduce complexity in 3 shared/common.sh functions (#539)
1. _cloud_api_retry_loop: consolidate two duplicate retry branches
   (network error + HTTP 429/503) into a single retry path using a
   retry_reason variable. Reduces from 47 to 43 lines, eliminates
   duplicated _api_should_retry_on_error / _update_retry_interval calls.

2. interactive_pick: extract list display + selection into reusable
   _display_and_select helper. The main function is now a thin wrapper
   that checks env var, fetches items, then delegates to the helper.

3. generic_ssh_wait: replace inline backoff calculation (3 lines) with
   existing _update_retry_interval helper, reducing duplication.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-11 15:12:23 -08:00
A
c8d7ea23e6
refactor: simplify BinaryLane wait loop and fix log_warn in 7 cloud polling loops (#538)
Replace 25-line custom _binarylane_wait_for_active with 4-line
generic_wait_for_instance call, matching the pattern used by 7 other
clouds (DigitalOcean, Vultr, Linode, etc).

Change log_warn to log_step for status/progress messages in polling
loops across 7 cloud providers (aws-lightsail, exoscale, fly, kamatera,
latitude, ovh, scaleway). These are normal status updates, not warnings.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-11 14:59:51 -08:00
A
8ad9f8bd2c
fix: improve CLI UX for list filters, dry-run URLs, history, and matrix display (#537)
- Resolve display names in `spawn list -a/-c` filters (e.g., "Claude Code" -> "claude")
- Fix dry-run preview to show GitHub raw URL instead of non-existent openrouter.ai/lab URL
- Cap history at 100 entries to prevent unbounded growth
- Rename compact matrix "Missing" column to "Not yet available" for clarity
- Escape double quotes in rerun prompt suggestions to produce valid shell commands

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 14:59:31 -08:00
A
0bbba737a5
test: add 40 tests for get_validated_server_name and API retry logic (#536)
Cover critical untested code from PRs #535 and #533:
- get_validated_server_name: env var reading, validation, injection prevention, boundary cases (15 tests)
- _api_should_retry_on_error: retry decision logic and log output (8 tests)
- _cloud_api_retry_loop: success, network errors, 429/503 handling, non-retryable errors, mixed scenarios (17 tests)

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-11 14:57:56 -08:00
A
be5f9f1087
refactor: extract get_validated_server_name to eliminate 18 duplicate get_server_name functions (#535)
18 cloud lib/common.sh files had identical 7-line get_server_name()
functions (get_resource_name + validate_server_name + echo). Added a
shared get_validated_server_name helper to shared/common.sh and replaced
all duplicates with one-line delegations. Net -110 lines.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 14:42:09 -08:00
A
0835b35a36
fix: use log_step (cyan) for progress messages instead of log_warn (yellow) (#534)
~1500 progress messages across 481 files were using log_warn (yellow)
for normal status updates like "Installing...", "Setting up...",
"Creating server...", etc. This made users think something was wrong
when everything was proceeding normally.

Changes:
- Replace log_warn with log_step for all progress/status messages
- Keep log_warn only for actual warnings (errors, remediation hints)
- Remove emoji from 3 sprite completion messages

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
2026-02-11 14:37:43 -08:00
A
800e9ed564 refactor: Automated improvements
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 22:31:01 +00:00
A
a9fae77c1f
refactor: simplify API retry logic and dispatchCommand (#533)
Remove 2 unnecessary indirection layers (_handle_api_transient_error and
_api_handle_transient_http_error) from the cloud API retry infrastructure.
The old _handle_api_transient_error had a bug where "network" was passed
as the attempt parameter to _api_should_retry_on_error, which expects a
numeric value. The retry logic is now inlined directly in
_cloud_api_retry_loop, calling _api_should_retry_on_error with the
correct arguments.

Also extract duplicated help-flag checking in dispatchCommand into a
hasTrailingHelpFlag helper, reducing nesting and removing repeated code.

Net: -72 lines, 2 fewer functions, 1 bug fix.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 14:29:37 -08:00
A
5866f7e2de
test: add cmdList integration tests through real exported function (#532)
Add 26 tests covering the cmdList pipeline through the actual
exported function with mock.module for @clack/prompts. Tests the
full path from history file through rendering: empty history,
table rendering with display names, agent/cloud filtering,
prompt display, manifest fallback, footer formatting.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 14:23:46 -08:00
A
07bc681437
feat: make spawn list interactive -- browse and rerun past spawns (#531)
When run in a TTY, `spawn list` (or `spawn ls`) now shows an interactive
picker using @clack/prompts select. Users can navigate the list with
arrow keys and press Enter to immediately rerun a previous spawn.

Non-TTY environments (piped output, CI) continue to show the static
table as before.

Fixes #492

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 14:23:42 -08:00
A
888e1528e2
feat: implement ramnode/cline agent script (#530)
Add Cline agent support for RamNode Cloud via OpenStack API.
Uses npm install -g cline, injects OpenRouter credentials via
OPENAI_API_KEY and OPENAI_BASE_URL env vars.

Agent: ramnode-gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-11 14:21:12 -08:00
A
c7d41a93b2
feat: Add opencode support for Netcup cloud (#529)
Agent: netcup-gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 14:16:13 -08:00
A
6fa3d21ad0
feat: implement local/continue.sh for Continue CLI (#528)
Add local machine support for Continue (31K+ GitHub stars).
Installs @continuedev/cli via npm and configures OpenRouter.

Agent: local-gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-11 14:16:02 -08:00
A
22cda7d103
feat: implement ramnode/continue agent script (#527)
Add Continue.dev agent support for RamNode Cloud via OpenStack API.
Uses npm install -g @continuedev/cli, creates ~/.continue/config.json
with OpenRouter provider configuration.

Agent: ramnode-gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-11 14:15:55 -08:00
A
98eefc9d5f
test: Add cmdRun happy-path pipeline integration tests (#526)
Tests the complete cmdRun success flow: primary/fallback download,
history recording during execScript, SPAWN_PROMPT/SPAWN_MODE env var
passing to bash, dry-run skip, and script content validation.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 14:10:58 -08:00
A
2fc7a959da
refactor: reduce complexity in getScriptFailureGuidance and generic_wait_for_instance (#525)
Extract duplicated credential-hint logic from case 1/default into
credentialHint() helper, and flatten nested if-blocks in
generic_wait_for_instance using early-continue.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 14:07:01 -08:00
A
c16f09a010
fix: use log_step for progress messages in recent scripts (#524)
Replace log_warn (yellow) with log_step (cyan) for progress messages
like "Installing...", "Setting up environment variables...", and
"Starting..." in recently-added scripts. Yellow warnings should be
reserved for actual warnings, not normal progress output.

Also fix bare `clear` calls to use `clear 2>/dev/null || true` for
robustness on minimal terminals, and improve the misleading
"Appending environment variables to ~/.zshrc..." message in local
scripts to the standard "Setting up environment variables..." phrasing.

Files: local/gptme.sh, local/aider.sh, ramnode/openclaw.sh,
ramnode/gptme.sh, netcup/gptme.sh

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 14:04:14 -08:00
A
bad99b4108
feat: Add local/gptme script for local execution (#521)
Implements local/gptme.sh for running gptme on the local machine without cloud provisioning.

Agent: gap-filler-local-2

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 13:48:40 -08:00
A
1992cc5d50
feat: Add ramnode/openclaw script (#519)
Implements OpenClaw deployment on RamNode Cloud using OpenStack API primitives.

Agent: gap-filler-ramnode-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 13:48:35 -08:00
A
c248db0d86
feat: add local/aider script (#523)
Implements local/aider for running Aider AI pair programming tool on local machine.

Agent: gap-filler-local-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 13:48:32 -08:00
A
85b7e1bcb0
feat: Add netcup/gptme script (#522)
Implements gptme agent on Netcup VPS using netcup lib primitives.

Agent: gap-filler-netcup

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 13:48:30 -08:00
A
1f2bbbbe3e
feat: Add ramnode/gptme script (#520)
Implements gptme agent on RamNode Cloud using OpenStack primitives.

Agent: gap-filler-ramnode-2

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 13:48:26 -08:00
A
096e238a91
fix: show specific auth env vars in script failure error messages (#518)
When a spawn script fails with exit code 1 (the most common failure),
the error message now shows which specific environment variables are
needed (e.g., "need HCLOUD_TOKEN + OPENROUTER_API_KEY") instead of
the generic "run spawn <cloud> for setup" which required a second
command to discover the needed credentials.

Also adds a "Retry:" hint with the exact rerun command at the end of
all script failure error messages.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 13:46:29 -08:00
A
14cef89c60
refactor: extract helpers from cmdMatrix, cmdList, and checkEntity (#517)
Extract renderMatrixFooter, renderListTable, and suggestTypoCorrection
to reduce function complexity and improve readability.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 13:29:03 -08:00
A
2ee7c0cef5
fix: handle common verb aliases (run, launch, start, deploy, exec) in CLI (#516)
Users coming from Docker, kubectl, or other CLIs naturally try
"spawn run claude sprite" or "spawn launch aider hetzner". Previously
these would show a confusing "Unknown command: run" error. Now the CLI
transparently strips these verb prefixes and forwards to the correct
agent/cloud handler. Bare verbs like "spawn run" show a helpful message
explaining the correct syntax.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 13:26:25 -08:00
A
9a5502906d
test: add 34 tests for cmdList table rendering and resolveDisplayName (#515)
Cover the integration of cmdList with manifest-resolved display names,
table header/separator rendering, prompt preview truncation in rows
vs footer, filtered result counts, timestamp formatting, and the
resolveDisplayName exported utility.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-11 13:26:21 -08:00
A
66b890493a
fix: improve CLI display for matrix title, compact view header, and list history (#514)
- Add "Availability Matrix (N agents, M clouds)" title to spawn matrix output
- Shorten compact view column header from "Not available on" to "Missing"
- Show display names (e.g. "Claude Code") instead of raw keys in spawn list

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 13:10:45 -08:00
A
52ef444006
test: fix failing assertion and add checkEntity message output tests (#513)
Fix agent-config-setup test that expected "does not run correctly" but
shared/common.sh now says "returned an error". Add 25 new tests verifying
checkEntity's user-facing messages for wrong-type detection, same-kind
fuzzy match, cross-kind fuzzy match (PR #510), and no-match fallback.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 13:08:45 -08:00
A
f3b0a4d622
test: add 46 tests for list display helpers and unknown command error (#512)
Cover recently extracted helpers from PR #506 that had zero direct tests:
- suggestFilterCorrection: agent/cloud filter typo suggestions (9 tests)
- showEmptyListMessage: empty list messaging with filters (11 tests)
- showListFooter: rerun hints, prompt truncation, filter info (14 tests)
- showUnknownCommandError: fuzzy match suggestions for bad commands (12 tests)

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-11 12:54:52 -08:00
A
7ba3559773
refactor: extract helpers from test_shared_common to reduce complexity (#511)
Break the 415-line test_shared_common() function in test/run.sh into
7 focused sub-functions grouped by feature:
- _test_model_validation (validate_model_id tests)
- _test_json_ssh_utils (json_escape, SSH key ops)
- _test_syntax_and_logging (syntax check, logging functions)
- _test_browser_and_cloud_init (open_browser, cloud-init, connectivity)
- _test_oauth_functions (wait_for_oauth_code, cleanup_oauth_session)
- _test_ssh_wait (generic_ssh_wait success/failure)
- _test_input_and_server_validation (safe_read, validate_server_name)

Also add assert_common_succeeds and assert_common_fails helpers to
eliminate repeated test boilerplate for simple pass/fail assertions.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-11 12:53:40 -08:00
A
ff13a5fda9
fix: suggest cross-kind fuzzy matches when args may be swapped with typos (#510)
When a user types `spawn htzner claude` (cloud name typo as first arg),
checkEntity now detects that "htzner" is close to cloud "hetzner" and
suggests the user may have swapped agent and cloud arguments. Previously,
this only worked for exact cloud names; typos would produce a generic
"Unknown agent" error with no helpful suggestion.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 12:47:53 -08:00
A
9458836ca1
refactor: extract helpers from showDryRunPreview and cmdUpdate to reduce complexity (#509)
- showDryRunPreview: extract printDryRunSection, buildAgentLines, buildCloudLines
  helpers to eliminate repeated header/body/blank-line pattern across 5 sections
- cmdUpdate: extract fetchRemoteVersion and performUpdate helpers to flatten
  nested try/catch, deduplicate install command string into INSTALL_CMD constant

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 12:34:51 -08:00