test(xce-test-cli-ux): verify help/completion/context-switching hold together (task 4.4)

Add one black-box regression test proving process-level help, in-session
help content, and context-scoped tab completion work correctly when
exercised together in one continuous session (context switches +
completion + help lookups), not just individually as each was already
covered by tasks 1.6/2.3/3.5. This closes the final task of the
xce-test-cli-ux implementation plan (23/23).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
This commit is contained in:
Rongsong Shen 2026-09-10 04:36:42 +00:00
parent 31d6606067
commit 38595099b9
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
2 changed files with 366 additions and 1 deletions

View file

@ -172,11 +172,12 @@
- _Depends: 2.4, 3.3, 1.7_
- _Done (requirement 13.7 MET): run twice independently (implementer + reviewer), each against separately-deployed live single-node controllers, sourcing a script file containing a destructive `qctrl -i` line from an otherwise-interactive session. With the confirmation toggle at its default, the prompt appeared on stderr with wording byte-identical to a directly-typed invocation of the same command, and decline reported "qctrl: not run (declined)" -- proving the gate fires for a sourced-file line exactly as it would for a typed one. After `set -y` (issued at the top-level context), re-sourcing the same file produced zero prompt text, and `set +y` afterward restored prompting for a directly-typed invocation, confirming no lingering session-state confusion. The reviewer additionally confirmed this structurally, not just behaviorally: `confirm_destructive()`'s only gating checks are `confirm_is_skip_set()` and `!xcetest_is_interactive()` (a read-only accessor over `g_interactive`, set once at startup from `isatty(STDIN_FILENO)` and never reassigned), and the only per-source-invocation state that exists (`g_source_depth`, used solely for cycle detection) has zero references anywhere near the gate -- there is no code path capable of distinguishing a sourced line from a typed one for this decision. Also verified the bonus interaction flagged by task 3.3's Implementation Note: with `set -e` active, a sourced file's declined destructive line does NOT trip abort-on-failure (a subsequent `echo` line in the same file still ran), confirming decline's `return 0` per `confirm.h`'s contract. No defect found. The already-logged bug-1797 (`cmd_qctrl`'s RPC-error-path queue-name leak) recurred via the `source` call path in both runs -- confirmed to be the identical pre-existing leak, not a new one; occurrence count bumped in buglog.json. No source files were changed; both deploys were fully cleaned up._
- [ ] 4.4 Verify process-level help, tab completion, and consolidated help content end-to-end
- [x] 4.4 Verify process-level help, tab completion, and consolidated help content end-to-end
- Confirm the help/version flags and in-session help behavior from 1.6 and 3.5, and the tab-completion behavior from 2.3, hold together in the full built client, not just in isolation
- Observable completion: a black-box run confirms the help flag's output describes the in-session help command, a representative command's help output includes its generated flag block and hand-authored example, and tab completion in two different contexts offers the expected candidates
- _Requirements: 4.1, 4.2, 4.3, 7.1, 7.2, 7.3, 7.4, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 11.2_
- _Depends: 1.6, 2.3, 3.5, 1.7_
- _Done (requirements 4.1-4.3, 7.1-7.4, 8.1-8.7, 11.2 MET): no live cluster needed (purely client-side). Existing per-mechanism coverage from tasks 1.6/2.3/3.5 was confirmed solid, but no test chained context-switching + tab completion + help lookup together in one continuous session -- a genuine "holds together, not just in isolation" gap. Added one new black-box test, `test_help_completion_and_context_switching_hold_together_in_one_session` (test_test_cli.c), covering: top-level vs. client-context double-Tab on the identical "w" prefix producing different, context-correct candidate sets; an unambiguous Tab-completion executed as a real (safely no-op, pre-RPC-validated) command; a mid-session `help jobkill` showing its purpose description, generated flag block, and hand-authored example; a further switch to worker context; and a `help jobkill` lookup there correctly reported not-found with the corrected grammar, leaking no client-context text. Both implementer and reviewer independently reproduced all three observable-completion criteria via their own standalone driver runs against the real binary, and the reviewer additionally cross-checked the completion candidate sets directly against test.c's four command tables. No defect found; no product code changed, only the one new permanent test (1331/1331 tests, 0 ASAN diagnostics)._
## Implementation Notes
- Audited all 139 `printf(` call sites in test.c; 33 were genuine diagnostic/warning/failure-path messages misrouted to stdout (not covered by the already-correct `flagspec_reject`/`perror` mechanisms) and were converted to `fprintf(stderr, ...)` — concentrated in `cmd_expect_jobs`/`cmd_expect_job`/`cmd_wait_primary` (entirely unrouted; these predate the flagspec migration since they take positional args, not flags), plus `get_setting`, `cmd_help`'s not-found path (a shared `FILE* out` var, stderr only when not-found; bare `help`'s listing and a successful lookup stay stdout), `cmd_ctrlstatus`, `cmd_jobrun`, `cmd_jobsub`, `cmd_jobstart`/`jobfinish`/`jobfail`, `resupdate_report_one`/`cmd_resupdate`, `cmd_set`. Deliberately left as stdout (Requirement 3 doesn't apply): `cmd_resval`'s intentional always-succeeds "not found" design, and the entire async worker/scheduler RPC-handler subsystem (`handle_notify`/`run_job`/etc.) — these are inbound-request callbacks dispatched outside the REPL's `cmd_*` table, not "a command's own diagnostic or result data." Found but explicitly left alone as pre-existing and out of THIS task's scope (stream routing, not return-code correctness): `cmd_resupdate` still unconditionally `return 0`s even on an outright RPC failure or a per-resource rejection — worth a follow-up bug entry if this area is touched again. Requirement 3.4 (redirection-invariance) holds by construction: no code branches a stream CHOICE on `isatty`/`g_interactive` anywhere in the file. (task 3.6)

View file

@ -2852,6 +2852,368 @@ test_help_context_scoped_not_found_no_cross_context_hint(void)
clitest_buf_free(&err);
}
/*
* test_help_completion_and_context_switching_hold_together_in_one_session --
* xce-test-cli-ux task 4.4, Requirements 4.1-4.3, 7.1-7.4, 8.1-8.7, 11.2.
*
* Every mechanism this test touches (process-level help/version, in-session
* `help <cmd>`, tab completion) already has dedicated per-mechanism coverage
* elsewhere in this file (and, for process-level flags, in
* test_xcetest_process_entry.c from task 1.6). What none of those tests do
* is run several of these mechanisms back-to-back in ONE live session,
* interleaved with real context switches -- exactly task 4.4's own
* "hold together ... not just in isolation" framing. This test is that
* missing combined/integration run:
*
* 1. Top-level, ambiguous "w" (ambiguous across worker/waldump/
* walcompare) is double-Tab listed; the candidate set is confirmed to
* include "worker" (a top-level-only command, not present at all in
* the client context) and to EXCLUDE "workerlist"/"wait-primary"
* (client-only).
* 2. Top-level, unambiguous "cl" -> Tab -> Enter completes to "client" in
* full and switches context (Requirement 7.1/7.2).
* 3. Client context, ambiguous "w" is double-Tab listed; the candidate
* set now includes "workerlist"/"waldump"/"walcompare"/"wait-primary"
* -- a DIFFERENT set than step 1's, for the IDENTICAL typed prefix, in
* the SAME running process (Requirement 7.1/7.4).
* 4. Client context, unambiguous "jobk" -> Tab -> Enter completes to
* "jobkill" and actually executes it bare (no live controller needed:
* cmd_jobkill's own missing-jobid validation returns before ever
* reaching the RPC/confirmation-gate code, exactly like task 2.3's
* "jstart" proof step).
* 5. Still in the client context -- and only NOW, after two context
* switches and two tab-completion demonstrations -- `help jobkill` is
* looked up. Its rendered text is confirmed to include the
* hand-authored purpose description (8.1), the flagspec_render_help()
* -generated "-y, --yes" flag line (8.2), the hand-authored example
* invocation (8.3), and the confirmation-gate/`set -y` scripting note
* (8.4) -- proving prior session state (context switches, completion)
* did not corrupt this content.
* 6. `..` then `worker` switches to a THIRD context (a context this
* session has not yet visited).
* 7. Worker context, ambiguous "j" (jstart/jfinish/jfail) is double-Tab
* listed; the candidate set is confirmed to include jstart/jfinish/
* jfail and to EXCLUDE every client-only "job*" command (jobkill,
* jobrun, jobsub, jobinfo, jobckpt) -- a second, independent
* different-contexts-different-candidates proof (worker vs. client).
* 8. `help jobkill` in the worker context -- a name valid in the OLD
* (client) context but not this one -- is confirmed reported as not
* found, with the corrected grammar (11.2: "match", not "matchs"),
* never leaking client context's jobkill text into the not-found
* response.
*
* Buffers are freed and reinitialized between stages (the same idiom
* test_help_context_scoped_not_found_no_cross_context_hint above already
* uses across its own context switch) so each stage's assertions search
* only that stage's own freshly captured output, never a stale match left
* over from an earlier stage's text.
*
* Requirement 4.1-4.3 (process-level -h/--help/--version describing the
* in-session `help` command) is deliberately NOT re-exercised here: the
* task's own guidance treats a process-level flag invocation as inherently
* a separate process from an interactive session, and
* test_xcetest_process_entry.c (task 1.6) already covers it end-to-end
* against the real binary. This task's implementer report quotes that
* output directly instead of duplicating the check here.
*/
static void
test_help_completion_and_context_switching_hold_together_in_one_session(void)
{
char xce_test_path[PATH_MAX];
char* const argv[] = { "xce_test", "--norc", NULL };
clitest_session_t sess;
clitest_buf_t out;
clitest_buf_t err;
int exit_code = -999;
const char ctrl_u = '\x15'; /* unix-line-discard */
const char enter = '\n';
TEST_ASSERT_EQUAL_INT_MESSAGE(
0, resolve_xce_test_path(xce_test_path, sizeof(xce_test_path)),
"must be able to resolve the sibling xce_test binary's path");
clitest_buf_init(&out);
clitest_buf_init(&err);
/* disable_echo=false for the WHOLE session: it needs libedit's live
* completion feedback (steps 1, 3, 7) as well as ordinary command
* output (steps 2, 4, 5, 6, 8) -- task 2.3's own header comment
* confirms full-line sends behave identically either way, and its own
* combined tab-completion test already mixes both under
* disable_echo=false throughout. */
TEST_ASSERT_EQUAL_INT_MESSAGE(
0, clitest_spawn_ex(&sess, xce_test_path, argv, false),
"clitest_spawn_ex must launch xce_test behind a real pty with "
"kernel ECHO left on, so libedit's own tab-completion feedback is "
"observable");
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "xce>", false, 5000),
"expected the initial 'xce>' interactive prompt on stdout");
/* --- Step 1: top-level, ambiguous "w" -> {worker, waldump,
* walcompare}. "worker" exists ONLY at top level (client has
* "workerlist" instead), so its presence here plus its absence in step
* 3's client-context listing is the clearest possible proof that
* candidates are context-scoped for the SAME typed prefix. */
clitest_buf_free(&out);
clitest_buf_free(&err);
clitest_buf_init(&out);
clitest_buf_init(&err);
TEST_ASSERT_EQUAL_INT(0, clitest_send_partial(&sess, "w"));
TEST_ASSERT_EQUAL_INT(0, clitest_send_tab(&sess));
TEST_ASSERT_EQUAL_INT(0, clitest_send_tab(&sess));
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "walcompare", false, 3000),
"top-level ambiguous 'w' must list 'walcompare' among the "
"candidates");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(out.data, "worker"),
"top-level ambiguous 'w' must list 'worker' among the candidates "
"(Requirement 7.1/7.3)");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(out.data, "waldump"),
"top-level ambiguous 'w' must list 'waldump' among the "
"candidates");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "workerlist"),
"top-level ambiguous 'w' must NOT offer 'workerlist' -- that "
"command exists only in the client context (Requirement 7.4)");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "wait-primary"),
"top-level ambiguous 'w' must NOT offer 'wait-primary' -- that "
"command exists only in the client context (Requirement 7.4)");
/* Clear the unaltered "w" input line (Requirement 7.3) and confirm the
* session is still usable by switching context next. */
TEST_ASSERT_EQUAL_INT(0, clitest_send_raw(&sess, &ctrl_u, 1));
/* --- Step 2: top-level, unambiguous "cl" -> Tab -> Enter completes in
* full to "client" and switches context (Requirement 7.1/7.2). */
clitest_buf_free(&out);
clitest_buf_free(&err);
clitest_buf_init(&out);
clitest_buf_init(&err);
TEST_ASSERT_EQUAL_INT(0, clitest_send_partial(&sess, "cl"));
TEST_ASSERT_EQUAL_INT(0, clitest_send_tab(&sess));
TEST_ASSERT_EQUAL_INT(0, clitest_send_raw(&sess, &enter, 1));
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "xce/client>", false, 5000),
"single unambiguous match 'cl' must complete in full to 'client' "
"and switch context (Requirement 7.1/7.2)");
/* --- Step 3: client context, ambiguous "w" -> {workerlist, waldump,
* walcompare, wait-primary} -- a DIFFERENT candidate set than step 1's,
* for the IDENTICAL typed prefix, in the SAME running process. */
clitest_buf_free(&out);
clitest_buf_free(&err);
clitest_buf_init(&out);
clitest_buf_init(&err);
TEST_ASSERT_EQUAL_INT(0, clitest_send_partial(&sess, "w"));
TEST_ASSERT_EQUAL_INT(0, clitest_send_tab(&sess));
TEST_ASSERT_EQUAL_INT(0, clitest_send_tab(&sess));
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "wait-primary", false,
3000),
"client-context ambiguous 'w' must list 'wait-primary' among the "
"candidates -- proving the SAME prefix offers a DIFFERENT "
"candidate in this context than at top level (Requirement 7.1/7.4)");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(out.data, "workerlist"),
"client-context ambiguous 'w' must list 'workerlist' (not bare "
"'worker', which is not a client command) among the candidates");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(out.data, "waldump"),
"client-context ambiguous 'w' must also list 'waldump'");
TEST_ASSERT_NOT_NULL_MESSAGE(
strstr(out.data, "walcompare"),
"client-context ambiguous 'w' must also list 'walcompare'");
TEST_ASSERT_EQUAL_INT(0, clitest_send_raw(&sess, &ctrl_u, 1));
/* --- Step 4: client context, unambiguous "jobk" -> Tab -> Enter
* completes in full to "jobkill" and actually runs it bare. No live
* controller is needed: cmd_jobkill's own missing-'-j' validation
* returns (to stderr) before ever reaching the RPC/confirmation-gate
* code, exactly like task 2.3's "jstart" proof step above. */
clitest_buf_free(&out);
clitest_buf_free(&err);
clitest_buf_init(&out);
clitest_buf_init(&err);
TEST_ASSERT_EQUAL_INT(0, clitest_send_partial(&sess, "jobk"));
TEST_ASSERT_EQUAL_INT(0, clitest_send_tab(&sess));
TEST_ASSERT_EQUAL_INT(0, clitest_send_raw(&sess, &enter, 1));
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err,
"you need to specify jobid with -j", true,
3000),
"single unambiguous match 'jobk' must complete in full to "
"'jobkill' in the client context (a command absent from both the "
"top-level and worker contexts), proven by hitting cmd_jobkill's "
"own bare-invocation validation message (Requirement 7.1/7.2/7.4)");
/* --- Step 5: NOW, mid-session (after two context switches and two
* tab-completion demonstrations), look up jobkill's full help text.
* Requirements 8.1-8.4: purpose description, generated flag block,
* hand-authored example, and confirmation-gate scripting note. */
clitest_buf_free(&out);
clitest_buf_free(&err);
clitest_buf_init(&out);
clitest_buf_init(&err);
TEST_ASSERT_EQUAL_INT(0, clitest_send_line(&sess, "help jobkill"));
/* Each phrase gets its OWN clitest_wait_for_text() call (not a single
* wait followed by plain strstr) -- cmd_help composes this output from
* several separate prints (description -> generated flagspec_render_
* help() block -> hand-authored tail), which this harness's poll loop
* can observe arriving across more than one read() chunk. This matches
* test_help_jobkill_shows_generated_flag_and_confirmation_note's own
* established pattern above, not the single-wait-then-strstr shortcut
* used for the double-Tab candidate listings elsewhere in this test
* (those really are one burst -- this multi-part composition is not,
* confirmed by this exact test failing on a bare strstr on first
* write). */
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err,
"Sends a signal to a running job", false,
5000),
"Requirement 8.1: mid-session 'help jobkill' must still include "
"its purpose description");
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "-y, --yes", false, 5000),
"Requirement 8.2: mid-session 'help jobkill' must still show the "
"generated -y/--yes flag line");
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "example: jobkill", false,
5000),
"Requirement 8.3: mid-session 'help jobkill' must still retain "
"its example invocation");
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err,
"destructive action and prompts for "
"confirmation",
false, 5000),
"Requirement 8.4: mid-session 'help jobkill' must still mention "
"the confirmation gate as a related scripting note");
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "set -y", false, 5000),
"the confirmation note must still point at `set -y` as the "
"session-wide bypass, even mid-session");
/* --- Step 6: switch to a THIRD context this session has not yet
* visited (worker), via '..' then 'worker' as plainly-typed lines. */
clitest_buf_free(&out);
clitest_buf_free(&err);
clitest_buf_init(&out);
clitest_buf_init(&err);
TEST_ASSERT_EQUAL_INT(0, clitest_send_line(&sess, ".."));
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "xce>", false, 5000),
"expected to return to the top-level context after '..'");
TEST_ASSERT_EQUAL_INT(0, clitest_send_line(&sess, "worker"));
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "xce/worker>", false, 5000),
"expected to enter the worker context");
/* --- Step 7: worker context, ambiguous "j" -> {jstart, jfinish,
* jfail}, and NONE of the client-only "job*" commands -- a second,
* independent different-contexts-different-candidates proof. */
clitest_buf_free(&out);
clitest_buf_free(&err);
clitest_buf_init(&out);
clitest_buf_init(&err);
TEST_ASSERT_EQUAL_INT(0, clitest_send_partial(&sess, "j"));
TEST_ASSERT_EQUAL_INT(0, clitest_send_tab(&sess));
TEST_ASSERT_EQUAL_INT(0, clitest_send_tab(&sess));
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err, "jfinish", false, 3000),
"worker-context ambiguous 'j' must list 'jfinish' among the "
"candidates");
TEST_ASSERT_NOT_NULL_MESSAGE(strstr(out.data, "jstart"),
"worker-context ambiguous 'j' must also "
"list 'jstart'");
TEST_ASSERT_NOT_NULL_MESSAGE(strstr(out.data, "jfail"),
"worker-context ambiguous 'j' must also "
"list 'jfail'");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "jobkill"),
"worker-context ambiguous 'j' must NOT offer 'jobkill' -- that "
"command exists only in the client context (Requirement 7.4)");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "jobrun"),
"worker-context ambiguous 'j' must NOT offer 'jobrun' either "
"(client-only)");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "jobsub"),
"worker-context ambiguous 'j' must NOT offer 'jobsub' either "
"(client-only)");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "jobinfo"),
"worker-context ambiguous 'j' must NOT offer 'jobinfo' either "
"(client-only)");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "jobckpt"),
"worker-context ambiguous 'j' must NOT offer 'jobckpt' either "
"(client-only)");
TEST_ASSERT_EQUAL_INT(0, clitest_send_raw(&sess, &ctrl_u, 1));
/* --- Step 8: 'help jobkill' in the worker context -- a name valid in
* the OLD (client) context but not this one -- must be reported not
* found, with the corrected grammar (Requirement 11.2), never leaking
* client context's jobkill text into the not-found response. This is
* the same not-found behavior test_help_context_scoped_not_found_no_
* cross_context_hint proves from the top-level context; here it is
* proven from the worker context, mid-session, after everything above
* has already run. */
clitest_buf_free(&out);
clitest_buf_free(&err);
clitest_buf_init(&out);
clitest_buf_init(&err);
TEST_ASSERT_EQUAL_INT(0, clitest_send_line(&sess, "help jobkill"));
TEST_ASSERT_TRUE_MESSAGE(
clitest_wait_for_text(&sess, &out, &err,
"No commands match `jobkill'", true, 5000),
"Requirement 8.7/11.2: from the worker context (jobkill's OLD "
"context, client, is not the active one), 'help jobkill' must be "
"reported as not found there, with corrected grammar");
TEST_ASSERT_NULL_MESSAGE(
strstr(err.data, "matchs"),
"the corrected not-found message must not contain the old "
"'matchs' typo anywhere in the captured output");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "No commands match"),
"the not-found diagnostic must not also appear on stdout");
TEST_ASSERT_NULL_MESSAGE(
strstr(out.data, "Sends a signal to a running job"),
"the worker-context not-found response must never leak client "
"context's jobkill help content");
TEST_ASSERT_NULL_MESSAGE(
strstr(err.data, "Sends a signal to a running job"),
"the worker-context not-found response must never leak client "
"context's jobkill help content, on stderr either");
TEST_ASSERT_EQUAL_INT(0, clitest_send_line(&sess, "quit"));
TEST_ASSERT_EQUAL_INT_MESSAGE(
0, clitest_wait_for_exit(&sess, &out, &err, 5000, &exit_code),
"xce_test did not exit within the harness's safety timeout after "
"'quit'");
/* Step 4's deliberate bare "jobkill" latches g_session_failed for the
* rest of the session (same mechanism, and same deliberate choice of
* proof command, as test_tab_completion_context_scoped_single_and_
* multi_match above) even though the REPL itself kept running to
* completion through every later step. */
TEST_ASSERT_EQUAL_INT_MESSAGE(
1, exit_code,
"xce_test should exit 1 -- the deliberate bare-'jobkill' proof "
"step in step 4 latches g_session_failed even though the REPL "
"itself kept running to completion through every later step");
clitest_kill_and_reap(&sess);
clitest_close(&sess);
clitest_buf_free(&out);
clitest_buf_free(&err);
}
/*
* test_expect_jobs_malformed_count_diagnostic_on_stderr_not_stdout --
* xce-test-cli-ux task 3.6, Requirement 3.1/3.2/3.3/3.4: `expect-jobs` given
@ -3074,6 +3436,8 @@ void test_test_cli(void)
RUN_TEST(test_help_reslist_shows_json_example);
RUN_TEST(test_help_unknown_command_shows_corrected_grammar);
RUN_TEST(test_help_context_scoped_not_found_no_cross_context_hint);
RUN_TEST(
test_help_completion_and_context_switching_hold_together_in_one_session);
RUN_TEST(test_expect_jobs_malformed_count_diagnostic_on_stderr_not_stdout);
RUN_TEST(test_wait_primary_invalid_timeout_diagnostic_on_stderr_not_stdout);
RUN_TEST(test_set_list_success_result_on_stdout_not_stderr);