Skip to content

fix(axi-sdk-js): route initialize and resolveContext failures through the AXI error contract - #122

Open
nathanbenn18 wants to merge 3 commits into
kunchenguid:mainfrom
nathanbenn18:fm/axi-opportunities-scout-a1
Open

fix(axi-sdk-js): route initialize and resolveContext failures through the AXI error contract#122
nathanbenn18 wants to merge 3 commits into
kunchenguid:mainfrom
nathanbenn18:fm/axi-opportunities-scout-a1

Conversation

@nathanbenn18

Copy link
Copy Markdown

Intent

Corrigir upstream o limite de tratamento de erros de axi-sdk-js identificado e reproduzido na investigação em /Users/nathanbennesby/firstmate/data/axi-opportunities-scout-a1/report.md. Falhas de initialize() e resolveContext() devem seguir o contrato público do handler: saída AXI estruturada em stdout, stderr vazio para erros de domínio e exit code apropriado. AxiError deve preservar código, mensagem e sugestões; erros desconhecidos devem ser normalizados como UNKNOWN sem stack trace exposto. Ajuda, versão, home, comando desconhecido, contexto lazy e precedência de handler não podem regredir. A investigação deve reproduzir primeiro pelo executável real usando o build atual, registrar trigger, condição e sintoma, comparar initialize e resolveContext com o handler, e inspecionar histórico e testes procurando inclusive evidência que refute a causa. Os testes de regressão devem começar vermelhos para initialize, resolveContext no home e resolveContext em comando, cobrindo AxiError e erro genérico, stdout, stderr e exit status pelo contrato público ou subprocesso. Fazer a menor mudança coerente que coloque essas fases sob o limite correto, sem duplicar formatadores nem esconder erros de programação além do contrato existente. Atualizar documentação somente se o comportamento público documentado realmente mudar; não editar CHANGELOG.md, arquivos gerados, benchmarks, hooks, update ou divergências documentais alheias. Executar build, formato, lint, testes do SDK e checks relevantes do repositório. A entrega local não basta: executar o pipeline no-mistakes completo a partir do commit, tratar seus retornos pela própria pipeline, abrir PR upstream, aguardar checks verdes e nunca fazer merge.

What Changed

  • runAxiCli() now awaits options.initialize?.() inside an error boundary and moves resolveContext into runHandler, so failures in either phase emit structured AXI output on stdout with the mapped exit code instead of an unhandled rejection and raw stack trace. initialize is widened to () => MaybePromise<void>, and context is still resolved only for the home view and real commands, so --help, --version and unknown commands stay lazy.
  • Error formatting is consolidated into a single writeFormattedError() helper shared by the handler path and the built-in update path; formatError precedence and the existing AxiError code/message/suggestion mapping are unchanged.
  • Added subprocess regression coverage (test/cli.test.ts plus a new test/fixtures/error-boundary-bin.mjs) asserting stdout, stderr and exit status for initialize (sync and async) and resolveContext failures on both the home view and a command, for AxiError and generic errors.

Note for consumers: initialize/resolveContext rejections no longer propagate out of runAxiCli(), so a tool wrapping the call in its own try/catch will no longer see them for those phases — they are formatted by the SDK, still overridable via formatError.

Risk Assessment

✅ Low: The change is a small, well-bounded error-boundary fix confined to one SDK file plus new tests, it preserves every lazy-context and dispatch-precedence invariant the intent marks as non-regressable, and it is covered by public-contract subprocess tests asserting stdout, stderr, and exit code together.

Testing

I installed deps, built the SDK, and ran the targeted test/cli.test.ts suite plus the small axi-sdk-js package suite (all green), then proved the intent at product level: a real demo-axi executable built on the compiled dist shows initialize() and resolveContext() failures now rendering structured AXI errors on stdout with empty stderr and correct exit codes (AxiError keeps code/message/suggestions, VALIDATION_ERROR maps to 2, plain errors normalize to UNKNOWN with no stack), whereas the same transcript against a dist rebuilt from the base commit reproduces the reported stack-trace-on-stderr/empty-stdout defect. The new regression tests were confirmed to start red on the base cli.ts and green on the fix, and help, version, home, command dispatch, unknown command, leading-flag error, lazy context and built-in-update precedence all behave unchanged through the real binary. Build output was removed afterwards and the worktree is clean.

Evidence: Before/after comparison of the real CLI (stdout, stderr, exit) for all four failure phases

$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi issue list BEFORE (93c5f33) AFTER (98b0072) stdout: <empty> stdout: error: Not authenticated to demo service code: AUTH_ERROR help[2]: Run demo-axi auth login,Set DEMO_TOKEN in the environment stderr: AxiError stack… stderr: <empty> exit: 1 exit: 1 $ DEMO_FAIL=initialize DEMO_ERROR=generic demo-axi BEFORE: stdout <empty>, stderr "Error: socket hang up" + stack, exit 1 AFTER: stdout "error: socket hang up / code: UNKNOWN", stderr <empty>, exit 1

# axi-sdk-js error boundary: real CLI, before vs after

`demo-axi` is a real executable built on the freshly compiled `packages/axi-sdk-js/dist`.
`DEMO_FAIL` picks the phase that throws; `DEMO_ERROR=axi` throws an `AxiError`, `generic` a plain `Error`.

## `$ DEMO_FAIL=initialize DEMO_ERROR=axi demo-axi`

| | before (93c5f33) | after (98b0072) |
| --- | --- | --- |
| stdout | `<empty>` | <pre>error: Not authenticated to demo service<br>code: AUTH_ERROR<br>help[2]: Run `demo-axi auth login`,Set DEMO_TOKEN in the environment</pre> |
| stderr | stack trace (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000g …) | `<empty>` |
| exit | 1 | 1 |

## `$ DEMO_FAIL=initialize DEMO_ERROR=generic demo-axi`

| | before (93c5f33) | after (98b0072) |
| --- | --- | --- |
| stdout | `<empty>` | <pre>error: socket hang up<br>code: UNKNOWN</pre> |
| stderr | stack trace (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000g …) | `<empty>` |
| exit | 1 | 1 |

## `$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi`

| | before (93c5f33) | after (98b0072) |
| --- | --- | --- |
| stdout | `<empty>` | <pre>error: Not authenticated to demo service<br>code: AUTH_ERROR<br>help[2]: Run `demo-axi auth login`,Set DEMO_TOKEN in the environment</pre> |
| stderr | stack trace (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000g …) | `<empty>` |
| exit | 1 | 1 |

## `$ DEMO_FAIL=resolveContext DEMO_ERROR=generic demo-axi`

| | before (93c5f33) | after (98b0072) |
| --- | --- | --- |
| stdout | `<empty>` | <pre>error: socket hang up<br>code: UNKNOWN</pre> |
| stderr | stack trace (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000g …) | `<empty>` |
| exit | 1 | 1 |

## `$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi issue list`

| | before (93c5f33) | after (98b0072) |
| --- | --- | --- |
| stdout | `<empty>` | <pre>error: Not authenticated to demo service<br>code: AUTH_ERROR<br>help[2]: Run `demo-axi auth login`,Set DEMO_TOKEN in the environment</pre> |
| stderr | stack trace (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000g …) | `<empty>` |
| exit | 1 | 1 |

## `$ DEMO_FAIL=resolveContext DEMO_ERROR=generic demo-axi issue list`

| | before (93c5f33) | after (98b0072) |
| --- | --- | --- |
| stdout | `<empty>` | <pre>error: socket hang up<br>code: UNKNOWN</pre> |
| stderr | stack trace (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000g …) | `<empty>` |
| exit | 1 | 1 |

## Reproducing

`` `sh
pnpm install --filter axi-sdk-js...
pnpm --dir packages/axi-sdk-js run build     # demo-axi imports the compiled dist/
bash <evidence-dir>/transcript.sh            # full CLI transcript (all surfaces)
pnpm --dir packages/axi-sdk-js exec vitest run test/cli.test.ts
`` `

The "before" column was produced by `git checkout 93c5f33 -- packages/axi-sdk-js/src/cli.ts`,
rebuilding, rerunning the same transcript, then restoring the file (worktree verified clean afterwards).
Evidence: Full CLI transcript with the fix (failure phases + non-regression surfaces + lazy context)
############ FAILURE PHASES (the reported defect) ############

==============================================================
$ DEMO_FAIL=initialize DEMO_ERROR=axi demo-axi 
--- stdout ---
error: Not authenticated to demo service
code: AUTH_ERROR
help[2]: Run `demo-axi auth login`,Set DEMO_TOKEN in the environment
--- stderr ---
<empty>
--- exit code: 1

==============================================================
$ DEMO_FAIL=initialize DEMO_ERROR=generic demo-axi 
--- stdout ---
error: socket hang up
code: UNKNOWN
--- stderr ---
<empty>
--- exit code: 1

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi 
--- stdout ---
error: Not authenticated to demo service
code: AUTH_ERROR
help[2]: Run `demo-axi auth login`,Set DEMO_TOKEN in the environment
--- stderr ---
<empty>
--- exit code: 1

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=generic demo-axi 
--- stdout ---
error: socket hang up
code: UNKNOWN
--- stderr ---
<empty>
--- exit code: 1

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi issue list
--- stdout ---
error: Not authenticated to demo service
code: AUTH_ERROR
help[2]: Run `demo-axi auth login`,Set DEMO_TOKEN in the environment
--- stderr ---
<empty>
--- exit code: 1

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=generic demo-axi issue list
--- stdout ---
error: socket hang up
code: UNKNOWN
--- stderr ---
<empty>
--- exit code: 1

==============================================================
$ DEMO_FAIL=none DEMO_ERROR=axi demo-axi boom
--- stdout ---
error: Not authenticated to demo service
code: AUTH_ERROR
help[2]: Run `demo-axi auth login`,Set DEMO_TOKEN in the environment
--- stderr ---
<empty>
--- exit code: 1

############ SURFACES THAT MUST NOT REGRESS ############

==============================================================
$ DEMO_FAIL=none demo-axi 
--- stdout ---
bin: /var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi
description: Demo agent-ergonomic CLI for the error-boundary evidence run
repo: kunchenguid/axi
issues: 3
"help[1]"[1]: Run `demo-axi issue list`
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=none demo-axi issue list
--- stdout ---
repo: kunchenguid/axi
issues[2]{number,title,state}:
  121,New community AXI,open
  117,bench grading hints,open
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=none demo-axi --help
--- stdout ---
bin: demo-axi
help[1]:
  Run `demo-axi issue list`
"built-in":
  update: Upgrade `demo-axi` to the latest published version
  "update --check": Report current vs latest without installing
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=none demo-axi --version
--- stdout ---
1.2.3
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=none demo-axi nope
--- stdout ---
error: "Unknown command: nope"
code: VALIDATION_ERROR
help[1]: Run `--help` to see available commands
--- stderr ---
<empty>
--- exit code: 2

==============================================================
$ DEMO_FAIL=none demo-axi --oops
--- stdout ---
error: Flags must come after the command
code: VALIDATION_ERROR
help[2]: "Run `demo-axi <command> [args] [flags]`",Move `--oops` after the command instead of before it
--- stderr ---
<empty>
--- exit code: 2

############ LAZY CONTEXT: help/version/unknown must not resolve context ############
(resolveContext is rigged to throw; a clean help/version/unknown proves it never ran)

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi --help
--- stdout ---
bin: demo-axi
help[1]:
  Run `demo-axi issue list`
"built-in":
  update: Upgrade `demo-axi` to the latest published version
  "update --check": Report current vs latest without installing
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi --version
--- stdout ---
1.2.3
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi nope
--- stdout ---
error: "Unknown command: nope"
code: VALIDATION_ERROR
help[1]: Run `--help` to see available commands
--- stderr ---
<empty>
--- exit code: 2
Evidence: Same transcript against the pre-fix build — reproduces the reported defect
############ FAILURE PHASES (the reported defect) ############

==============================================================
$ DEMO_FAIL=initialize DEMO_ERROR=axi demo-axi 
--- stdout ---
<empty>
--- stderr ---
file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:11
    return new AxiError("Not authenticated to demo service", "AUTH_ERROR", [
           ^

AxiError: Not authenticated to demo service
    at boom (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:11:12)
--- exit code: 1

==============================================================
$ DEMO_FAIL=initialize DEMO_ERROR=generic demo-axi 
--- stdout ---
<empty>
--- stderr ---
file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:16
  return new Error("socket hang up");
         ^

Error: socket hang up
    at boom (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:16:10)
--- exit code: 1

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi 
--- stdout ---
<empty>
--- stderr ---
file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:11
    return new AxiError("Not authenticated to demo service", "AUTH_ERROR", [
           ^

AxiError: Not authenticated to demo service
    at boom (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:11:12)
--- exit code: 1

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=generic demo-axi 
--- stdout ---
<empty>
--- stderr ---
file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:16
  return new Error("socket hang up");
         ^

Error: socket hang up
    at boom (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:16:10)
--- exit code: 1

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi issue list
--- stdout ---
<empty>
--- stderr ---
file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:11
    return new AxiError("Not authenticated to demo service", "AUTH_ERROR", [
           ^

AxiError: Not authenticated to demo service
    at boom (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:11:12)
--- exit code: 1

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=generic demo-axi issue list
--- stdout ---
<empty>
--- stderr ---
file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:16
  return new Error("socket hang up");
         ^

Error: socket hang up
    at boom (file:///private/var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi:16:10)
--- exit code: 1

==============================================================
$ DEMO_FAIL=none DEMO_ERROR=axi demo-axi boom
--- stdout ---
error: Not authenticated to demo service
code: AUTH_ERROR
help[2]: Run `demo-axi auth login`,Set DEMO_TOKEN in the environment
--- stderr ---
<empty>
--- exit code: 1

############ SURFACES THAT MUST NOT REGRESS ############

==============================================================
$ DEMO_FAIL=none demo-axi 
--- stdout ---
bin: /var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi
description: Demo agent-ergonomic CLI for the error-boundary evidence run
repo: kunchenguid/axi
issues: 3
"help[1]"[1]: Run `demo-axi issue list`
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=none demo-axi issue list
--- stdout ---
repo: kunchenguid/axi
issues[2]{number,title,state}:
  121,New community AXI,open
  117,bench grading hints,open
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=none demo-axi --help
--- stdout ---
bin: demo-axi
help[1]:
  Run `demo-axi issue list`
"built-in":
  update: Upgrade `demo-axi` to the latest published version
  "update --check": Report current vs latest without installing
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=none demo-axi --version
--- stdout ---
1.2.3
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=none demo-axi nope
--- stdout ---
error: "Unknown command: nope"
code: VALIDATION_ERROR
help[1]: Run `--help` to see available commands
--- stderr ---
<empty>
--- exit code: 2

==============================================================
$ DEMO_FAIL=none demo-axi --oops
--- stdout ---
error: Flags must come after the command
code: VALIDATION_ERROR
help[2]: "Run `demo-axi <command> [args] [flags]`",Move `--oops` after the command instead of before it
--- stderr ---
<empty>
--- exit code: 2

############ LAZY CONTEXT: help/version/unknown must not resolve context ############
(resolveContext is rigged to throw; a clean help/version/unknown proves it never ran)

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi --help
--- stdout ---
bin: demo-axi
help[1]:
  Run `demo-axi issue list`
"built-in":
  update: Upgrade `demo-axi` to the latest published version
  "update --check": Report current vs latest without installing
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi --version
--- stdout ---
1.2.3
--- stderr ---
<empty>
--- exit code: 0

==============================================================
$ DEMO_FAIL=resolveContext DEMO_ERROR=axi demo-axi nope
--- stdout ---
error: "Unknown command: nope"
code: VALIDATION_ERROR
help[1]: Run `--help` to see available commands
--- stderr ---
<empty>
--- exit code: 2
Evidence: VALIDATION_ERROR from initialize/resolveContext exits 2 with empty stderr (real binary)

$ DEMO_FAIL=resolveContext DEMO_ERROR=validation demo-axi issue list error: Missing --repo flag code: VALIDATION_ERROR help[1]: Run demo-axi issue list --repo owner/name stderr: <empty> exit: 2

$ DEMO_FAIL=initialize DEMO_ERROR=validation demo-axi 
error: Missing --repo flag
code: VALIDATION_ERROR
help[1]: Run `demo-axi issue list --repo owner/name`
stderr: <empty>
exit: 2

$ DEMO_FAIL=initialize DEMO_ERROR=validation demo-axi issue list
error: Missing --repo flag
code: VALIDATION_ERROR
help[1]: Run `demo-axi issue list --repo owner/name`
stderr: <empty>
exit: 2

$ DEMO_FAIL=resolveContext DEMO_ERROR=validation demo-axi 
error: Missing --repo flag
code: VALIDATION_ERROR
help[1]: Run `demo-axi issue list --repo owner/name`
stderr: <empty>
exit: 2

$ DEMO_FAIL=resolveContext DEMO_ERROR=validation demo-axi issue list
error: Missing --repo flag
code: VALIDATION_ERROR
help[1]: Run `demo-axi issue list --repo owner/name`
stderr: <empty>
exit: 2
Evidence: Regression tests start red on the base cli.ts (only the 8 new cases fail)

× formats 'axi' initialize failures on stdout × formats 'generic' initialize failures on stdout × formats 'axi' asynchronous initialize rejections on stdout × formats 'generic' asynchronous initialize rejections on stdout × formats 'axi' resolveContext failures for home on stdout × formats 'generic' resolveContext failures for home on stdout × formats 'axi' resolveContext failures for commands on stdout × formats 'generic' resolveContext failures for commands on stdout Tests 8 failed | 24 passed (32)


 RUN  v3.2.4 /Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js

 ❯ test/cli.test.ts (32 tests | 8 failed) 2195ms
   ✓ runAxiCli > runs initializer before dispatch 1ms
   ✓ runAxiCli > shows top-level help for bare --help without resolving context 1ms
   ✓ runAxiCli > shows version for bare --version without resolving context 0ms
   ✓ runAxiCli > shows version for bare -v without resolving context 0ms
   ✓ runAxiCli > shows version for bare -V without resolving context 0ms
   ✓ runAxiCli > uses explicit argv when provided instead of process.argv 0ms
   ✓ runAxiCli > routes command help through getCommandHelp without resolving context 0ms
   ✓ runAxiCli > writes a structured error when flags appear before the command 0ms
   ✓ runAxiCli > writes structured unknown-command errors without resolving context 0ms
   ✓ runAxiCli > routes to the matching command handler with lazy context resolution 0ms
   ✓ runAxiCli > serializes structured handler output at the boundary 0ms
   ✓ runAxiCli > adds bin and description to the home view automatically 0ms
   ✓ runAxiCli > resolves home context only when the home handler actually runs 0ms
   ✓ runAxiCli > does not install hooks automatically from the executable path 0ms
   ✓ runAxiCli > does not auto-install hooks from test worker entrypoints 0ms
   ✓ runAxiCli > handles the built-in update command via runUpdate 1ms
   ✓ runAxiCli > defers to a tool's own update command when registered 0ms
   ✓ runAxiCli > shows built-in update help without running the upgrade 0ms
   ✓ runAxiCli > advertises the built-in update command in bare --help 0ms
   ✓ runAxiCli > does not advertise the built-in update when a tool overrides it 0ms
   ✓ runAxiCli > maps validation errors to exit code 2 0ms
   × runAxiCli subprocess integration > formats 'axi' initialize failures on stdout 190ms
     → expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 2, …(2) }
   × runAxiCli subprocess integration > formats 'generic' initialize failures on stdout 196ms
     → expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 1, …(2) }
   × runAxiCli subprocess integration > formats 'axi' asynchronous initialize rejections on stdout 182ms
     → expected { exitCode: 1, …(2) } to deeply equal { exitCode: 2, …(2) }
   × runAxiCli subprocess integration > formats 'generic' asynchronous initialize rejections on stdout 190ms
     → expected { exitCode: 1, …(2) } to deeply equal { exitCode: 1, …(2) }
   × runAxiCli subprocess integration > formats 'axi' resolveContext failures for home on stdout 190ms
     → expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 2, …(2) }
   × runAxiCli subprocess integration > formats 'generic' resolveContext failures for home on stdout 188ms
     → expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 1, …(2) }
   × runAxiCli subprocess integration > formats 'axi' resolveContext failures for commands on stdout 181ms
     → expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 2, …(2) }
   × runAxiCli subprocess integration > formats 'generic' resolveContext failures for commands on stdout 192ms
     → expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 1, …(2) }
   ✓ runAxiCli subprocess integration > prints version from a real entrypoint for bare --version 225ms
   ✓ runAxiCli subprocess integration > prints version from a real entrypoint for bare -v 226ms
   ✓ runAxiCli subprocess integration > prints version from a real entrypoint for bare -V 227ms

⎯⎯⎯⎯⎯⎯⎯ Failed Tests 8 ⎯⎯⎯⎯⎯⎯⎯

 FAIL  test/cli.test.ts > runAxiCli subprocess integration > formats 'axi' initialize failures on stdout
AssertionError: expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 2, …(2) }

�[32m- Expected�[39m
�[31m+ Received�[39m

�[2m  {�[22m
�[32m-   "exitCode": 2,�[39m
�[32m-   "stderr": "",�[39m
�[32m-   "stdout": "error: Invalid fixture request�[39m
�[32m- code: VALIDATION_ERROR�[39m
�[32m- help[1]: Run `fixture --help`�[39m
�[31m+   "exitCode": 1,�[39m
�[31m+   "stderr": "/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:8�[39m
�[31m+     return new __vite_ssr_import_0__.AxiError(\"Invalid fixture request\", \"VALIDATION_ERROR\", [�[39m
�[31m+            ^�[39m
�[31m+�[39m
�[31m+ AxiError: Invalid fixture request�[39m
�[31m+     at fixtureError (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:7:12)�[39m
�[31m+     at Object.initialize (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:22:17)�[39m
�[31m+     at runAxiCli (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/src/cli.ts:77:11)�[39m
�[31m+     at /Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:15:16�[39m
�[31m+     at ViteNodeRunner.runModule (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:397:4)�[39m
�[31m+     at ViteNodeRunner.directRequest (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:375:3)�[39m
�[31m+     at ViteNodeRunner.cachedRequest (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:189:11)�[39m
�[31m+     at ViteNodeRunner.executeFile (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:162:10)�[39m
�[31m+     at CAC.run (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/cli.mjs:102:28) {�[39m
�[31m+   code: 'VALIDATION_ERROR',�[39m
�[31m+   suggestions: [ 'Run `fixture --help`' ]�[39m
�[31m+ }�[39m
�[31m+�[39m
�[31m+ Node.js v26.5.1�[39m
�[2m  ",�[22m
�[31m+   "stdout": "",�[39m
�[2m  }�[22m

 ❯ test/cli.test.ts:499:22
    497|       );
    498| 
    499|       expect(result).toEqual({ exitCode, stdout, stderr: "" });
       |                      ^
    500|     },
    501|   );

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/8]⎯

 FAIL  test/cli.test.ts > runAxiCli subprocess integration > formats 'generic' initialize failures on stdout
AssertionError: expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 1, …(2) }

�[32m- Expected�[39m
�[31m+ Received�[39m

�[2m  {�[22m
�[2m    "exitCode": 1,�[22m
�[32m-   "stderr": "",�[39m
�[32m-   "stdout": "error: Dependency exploded�[39m
�[32m- code: UNKNOWN�[39m
�[31m+   "stderr": "/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:13�[39m
�[31m+   return new Error(\"Dependency exploded\");�[39m
�[31m+          ^�[39m
�[31m+�[39m
�[31m+ Error: Dependency exploded�[39m
�[31m+     at fixtureError (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:12:10)�[39m
�[31m+     at Object.initialize (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:22:17)�[39m
�[31m+     at runAxiCli (/Users/nathanbenn

... [13545 bytes truncated] ...

rees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:397:4)�[39m
�[31m+     at ViteNodeRunner.directRequest (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:375:3)�[39m
�[31m+     at ViteNodeRunner.cachedRequest (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:189:11)�[39m
�[31m+     at ViteNodeRunner.executeFile (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:162:10)�[39m
�[31m+     at CAC.run (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/cli.mjs:102:28)�[39m
�[31m+�[39m
�[31m+ Node.js v26.5.1�[39m
�[2m  ",�[22m
�[31m+   "stdout": "",�[39m
�[2m  }�[22m

 ❯ test/cli.test.ts:525:22
    523|       );
    524| 
    525|       expect(result).toEqual({ exitCode, stdout, stderr: "" });
       |                      ^
    526|     },
    527|   );

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/8]⎯

 FAIL  test/cli.test.ts > runAxiCli subprocess integration > formats 'axi' resolveContext failures for commands on stdout
AssertionError: expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 2, …(2) }

�[32m- Expected�[39m
�[31m+ Received�[39m

�[2m  {�[22m
�[32m-   "exitCode": 2,�[39m
�[32m-   "stderr": "",�[39m
�[32m-   "stdout": "error: Invalid fixture request�[39m
�[32m- code: VALIDATION_ERROR�[39m
�[32m- help[1]: Run `fixture --help`�[39m
�[31m+   "exitCode": 1,�[39m
�[31m+   "stderr": "/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:8�[39m
�[31m+     return new __vite_ssr_import_0__.AxiError(\"Invalid fixture request\", \"VALIDATION_ERROR\", [�[39m
�[31m+            ^�[39m
�[31m+�[39m
�[31m+ AxiError: Invalid fixture request�[39m
�[31m+     at fixtureError (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:7:12)�[39m
�[31m+     at Object.resolveContext (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:32:17)�[39m
�[31m+     at runAxiCli (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/src/cli.ts:151:33)�[39m
�[31m+     at /Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:15:16�[39m
�[31m+     at ViteNodeRunner.runModule (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:397:4)�[39m
�[31m+     at ViteNodeRunner.directRequest (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:375:3)�[39m
�[31m+     at ViteNodeRunner.cachedRequest (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:189:11)�[39m
�[31m+     at ViteNodeRunner.executeFile (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:162:10)�[39m
�[31m+     at CAC.run (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/cli.mjs:102:28) {�[39m
�[31m+   code: 'VALIDATION_ERROR',�[39m
�[31m+   suggestions: [ 'Run `fixture --help`' ]�[39m
�[31m+ }�[39m
�[31m+�[39m
�[31m+ Node.js v26.5.1�[39m
�[2m  ",�[22m
�[31m+   "stdout": "",�[39m
�[2m  }�[22m

 ❯ test/cli.test.ts:538:22
    536|       );
    537| 
    538|       expect(result).toEqual({ exitCode, stdout, stderr: "" });
       |                      ^
    539|     },
    540|   );

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/8]⎯

 FAIL  test/cli.test.ts > runAxiCli subprocess integration > formats 'generic' resolveContext failures for commands on stdout
AssertionError: expected { exitCode: 1, stdout: '', …(1) } to deeply equal { exitCode: 1, …(2) }

�[32m- Expected�[39m
�[31m+ Received�[39m

�[2m  {�[22m
�[2m    "exitCode": 1,�[22m
�[32m-   "stderr": "",�[39m
�[32m-   "stdout": "error: Dependency exploded�[39m
�[32m- code: UNKNOWN�[39m
�[31m+   "stderr": "/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:13�[39m
�[31m+   return new Error(\"Dependency exploded\");�[39m
�[31m+          ^�[39m
�[31m+�[39m
�[31m+ Error: Dependency exploded�[39m
�[31m+     at fixtureError (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:12:10)�[39m
�[31m+     at Object.resolveContext (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:32:17)�[39m
�[31m+     at runAxiCli (/Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/src/cli.ts:151:33)�[39m
�[31m+     at /Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/packages/axi-sdk-js/test/fixtures/error-boundary-bin.mjs:15:16�[39m
�[31m+     at ViteNodeRunner.runModule (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:397:4)�[39m
�[31m+     at ViteNodeRunner.directRequest (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:375:3)�[39m
�[31m+     at ViteNodeRunner.cachedRequest (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:189:11)�[39m
�[31m+     at ViteNodeRunner.executeFile (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/client.mjs:162:10)�[39m
�[31m+     at CAC.run (file:///Users/nathanbennesby/.no-mistakes/worktrees/fc703883fc95/01KZ28RZ3KEVVAHR61VPRAP47R/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vite-node/dist/cli.mjs:102:28)�[39m
�[31m+�[39m
�[31m+ Node.js v26.5.1�[39m
�[2m  ",�[22m
�[31m+   "stdout": "",�[39m
�[2m  }�[22m

 ❯ test/cli.test.ts:538:22
    536|       );
    537| 
    538|       expect(result).toEqual({ exitCode, stdout, stderr: "" });
       |                      ^
    539|     },
    540|   );

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/8]⎯


 Test Files  1 failed (1)
      Tests  8 failed | 24 passed (32)
   Start at  19:22:25
   Duration  2.42s (transform 50ms, setup 0ms, collect 59ms, tests 2.19s, environment 0ms, prepare 36ms)
- Evidence: Reproducible demo CLI + transcript driver used for the manual verification (local file: /var/folders/dh/ny_k7wbn1lv56zxvwr3jz8100000gn/T/no-mistakes-evidence/01KZ28RZ3KEVVAHR61VPRAP47R/demo-axi)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 3 infos
  • ℹ️ packages/axi-sdk-js/src/cli.ts:144 - Residual gap of the same class, outside this change's authorized scope: options.getCommandHelp?.(command) (line 144), options.renderUnknownCommand?.(command) (line 154), and options.formatError inside writeFormattedError (line 211) are still invoked with no error boundary. A tool whose getCommandHelp throws on tool issue --help still produces a raw stack trace on stderr with empty stdout and exit 1 — the exact contract violation just fixed for initialize/resolveContext. The intent scopes the fix to those two phases and asks for the smallest coherent change, so this is reported as informational only, not as an incomplete fix.
  • ℹ️ packages/axi-sdk-js/test/cli.test.ts:40 - runErrorBoundaryFixture re-derives the fixture path and the ../node_modules/.bin/vite-node path plus the execFileAsync invocation that the pre-existing version test already inlines at lines 545-557. Extracting one runFixtureBin(fixtureName, args) helper that both call would remove the duplicated path resolution and the duplicated cwd wiring. Test-only, no behavior impact.
  • ℹ️ packages/axi-sdk-js/src/cli.ts:175 - Observable behavior change for published-SDK consumers: previously initialize/resolveContext rejections propagated out of runAxiCli(), so a tool wrapping the call in its own try/catch saw them. They are now caught and formatted by the SDK, so such an outer catch no longer fires for these phases. This is exactly what the intent requires and tools can still override via formatError, so no action is needed — but it is worth one line in the PR body since it ships as a patch bump under the pre-1.0 release-please config.
✅ **Test** - passed

✅ No issues found.

  • pnpm install --filter axi-sdk-js... then pnpm --dir packages/axi-sdk-js run build (tsc build succeeds with the widened initialize?: () =&gt; MaybePromise&lt;void&gt; signature)
  • vitest run test/cli.test.ts in packages/axi-sdk-js — 32 passed, including the 8 new subprocess error-boundary cases
  • Red-baseline check: git checkout 93c5f33 -- packages/axi-sdk-js/src/cli.ts + rebuild, then vitest run test/cli.test.ts — exactly the 8 new tests fail (initialize sync/async, resolveContext home, resolveContext command × AxiError/generic), 24 others pass; file restored and worktree verified clean
  • vitest run for the axi-sdk-js package (5 suites) to confirm errors/output/hooks/update suites are unaffected by the boundary change
  • Manual CLI transcript over a real demo-axi executable importing the freshly compiled dist/index.js: bash transcript.sh capturing stdout/stderr/exit separately for initialize and resolveContext failures (AxiError and generic), handler-throw control, home, issue list, --help, --version, unknown command and leading-flag error
  • Same transcript re-run against a dist rebuilt from base cli.ts to reproduce the reported defect (empty stdout, stack trace on stderr, exit 1) before/after comparison
  • Lazy-context check through the real binary: --help, --version and an unknown command with resolveContext rigged to throw — all succeed, proving context is still resolved only for views that need it
  • Exit-code mapping check through the real binary with a VALIDATION_ERROR AxiError thrown from initialize and from resolveContext (home and command) — exit 2, stderr empty
⚠️ **Document** - 1 info
  • ℹ️ packages/axi-sdk-js/README.md:105 - Judgment call, left as-is: the public initialize option is not documented in packages/axi-sdk-js/README.md, and this change widened it to MaybePromise&lt;void&gt; and moved initialize/resolveContext failures under the handler error boundary. No existing doc states anything now false (the README's "lazy context resolution" claim still holds), and the invariant is owned by the code comment in packages/axi-sdk-js/src/cli.ts at the boundary, so documenting initialize here would add a new fact rather than fix a stale one. If maintainers want the option surfaced to AXI authors, a follow-up should add it to the README Reference table alongside the structured-error contract for the initialize phase.
✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

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