Commit Graph
6 Commits
Author SHA1 Message Date
Miguel Ángel 693c385508 fix(cli): commands exit right away even when the network or DNS is broken (#4604)
* fix(cli): commands exit without waiting on update checks or telemetry

The update and skills checks run in a detached child that refreshes the
caches for the next run; the parent only reads the caches. finalizeCli no
longer awaits the telemetry flush: the exit handler flushSync() delivers
what is queued. The events beacon, feedback and figma error paths stop
awaiting flush() too.

* fix(cli): retry a failed background check at most once an hour

Before starting the background worker, the CLI stamps a per-check attempt
time and skips a check it attempted within the hour, so a dead network no
longer starts a worker on every command. The stale-pin notice writes onto a
fresh read, detached spawns set windowsHide, and a test ties the worker path
to its build entry.

* fix(cli): a failed-check stamp dated in the future no longer silences update checks
2026-09-28 02:22:12 +00:00
Miguel Ángel 627e9476af fix(cli): a failed command sends one error report, naming its real cause (#4586)
* fix(cli): a failed command sends one cli_error, naming its real cause

* chore(cli): drop a comment the parameter name already says

* fix(cli): a failure caught by its own command is still reported, and only once

* test(cli): normalize-audio test passes the flags it requires

* style(cli): format the failure tracking test

* fix(cli): one function unwraps and reports a command failure, once

* docs(cli): shorten the command failure reporter's comment
2026-09-27 13:06:42 +00:00
Miguel Ángel de9206e0f8 fix(cli): detect a missing or stale studio build before it crashes (#4076)
* fix(cli): name the missing or stale workspace package before preview crashes

Running hyperframes preview from source with an unbuilt or stale
package previously crashed deep inside that package's own import
graph with a raw resolver error naming neither the package nor the
fix. Add a preflight that runs before the preview command's own
module import, so it also catches the crash that happens at CLI load
time before the studio dev server ever spawns.

* test(cli): cover the preview workspace-build gate wiring

Adds a test that exercises the real CLI dispatch path (mocked module
loaders, not source-text matching) to prove the preview command's
build-check runs before its module loads and that a failure exits
non-zero without double-printing. Also guards the exports-map reader
against a malformed package.json instead of crashing raw.

* fix(cli): correct why the audio-fx generated file is checked

The comment claimed core/src/index.ts imports both generated files
directly. Only runtime-inline.ts is; audio-fx-runtime-inline.ts is
reachable solely via core's own audio-fx-runtime export subpath,
which the engine package imports. The check itself was already
correct to require both, only the stated reason was wrong.
2026-09-18 09:27:39 -04:00
Miguel Ángel ea95b7d44e fix(cli): stop a caught post-render throw reporting a valid render as failed (#3409)
A render that produced and validated its artifact still exited 1. Reported
again from the field on 0.8.7: the MP4 was on disk and an independent ffprobe
and full decode both passed, and the CLI exited 1 immediately after logging
`artifact validated`.

`render-success-state.ts` exists for exactly this and documents three earlier
cases, so the sentinel was already there. Its gap is which paths read it: the
uncaughtException and unhandledRejection handlers both consult
`isRenderSucceeded()`, but a post-render throw that the command wrapper CATCHES
never reaches either. It becomes an ordinary non-zero CommandResult, and
`finalizeCli` wrote that straight to `process.exitCode`.

The result was a run that disagreed with itself: `commandSucceededForTelemetry()`
already lets a validated render override a failure, so telemetry recorded
success while the shell saw exit 1.

Sanitize once in `finalizeCli`, where every command result funnels through,
rather than wrapping the individual steps. Which step threw does not matter;
that the artifact is committed does. The throw is still printed, so it stays
visible for diagnosis without being fatal.

Reproduced first as a failing test (`expected 1 to be +0`) on macOS, so this is
not Windows-specific — the field reports are one instance of it. A second test
pins the other side: a command that throws with no validated render still exits
non-zero, so the sanitizer cannot swallow a genuine failure.
2026-08-21 21:01:43 -04:00
WaterrrForever bc6dbc7e21 fix(cli): stop dropping queued telemetry when process.exit races the final flush (#2970)
* fix(cli): stop dropping queued telemetry when process.exit races the final flush

Two exit-path defects introduced by the 0.7.65 process-lifecycle refactor:

1. The 'exit' handler returned early once finalizeCli had started, which
   also skipped the flushSync() fallback. When an agent-pipe EPIPE killed
   the process mid-flush (the NORMAL teardown under Claude Code / Codex),
   the still-queued render_complete was silently dropped — fleet delivery
   fell from ~90% (0.7.55-0.7.64) to ~35%. flushSync() is now
   unconditional: empty queue is a no-op, event uuids dedupe re-sends.

2. The EPIPE handlers set commandFailed unconditionally, so every piped
   successful render scored success:false in cli_command_result (fleet
   success rate collapsed 89% -> 5-25%). EPIPE now only marks failure
   when the pipe died before the render artifact was validated, matching
   the existing isRenderSucceeded() exemption on the uncaughtException
   path.

Regression tests cover both: flushSync-after-finalize, and EPIPE
before/after artifact validation.

* fix(cli): don't score a validated render as failed due to pre-artifact noise

Review follow-up: commandFailed can be set by noise that precedes artifact
validation — a stray unhandledRejection mid-render, or an EPIPE firing
before markRenderSucceeded on a run that still completes. Once the
artifact validates, that earlier noise must not flip the run's
cli_command_result to success:false. Genuine failures keep a non-zero
exit code and are still caught by the exitCode check.

Extracted commandSucceededForTelemetry() and applied it at both tracking
sites (finalizeCli and the exit handler), with a regression test.

* test(cli): pin the production-reachable producer of the stale-failure override

Review note: the pre-artifact-noise test drives the scenario with an
EPIPE, which only reaches 'render validates afterwards' because
process.exit is mocked — that sequence can't occur in production. Add a
test for the reachable producer: an unhandledRejection before validation
(the handler deliberately does not exit), followed by a validated render,
must score success:true at exit code 0. Verified red on the pre-override
cli.ts.
2026-08-04 02:02:55 +08:00
James a9338a4e0f fix(cli): await error telemetry before finalization 2026-07-20 09:45:54 -07:00