Commit graph

1855 commits

Author SHA1 Message Date
6c201bb3e8
fix(scheduler): refuse a stale JOBS_PUSH resync claim that would destroy a real allocation
A resync redelivery (on_scheduler_join()'s full push, fired on every
scheduler reconnect) can race a job's own very-recent dispatch
confirmation and carry a stale, non-terminal state for it. The
duplicate-jobid merge in core_events.c trusted this claim
unconditionally, freeing the job's already-captured allocation and
regressing its state -- live-confirmed via a production scheduler.log
showing a resync WARN landing 16ms after the job's own RUN
confirmation, and matching a live-reported simulator symptom (a RUN
job silently missing from info worker's allocation listing).

Refuse a non-terminal claim when the existing job already has a real
allocation on record, mirroring the existing phantom-RUN guard's own
reasoning in the opposite direction; a genuinely terminal claim
(DONE/EXIT) still applies and releases the allocation correctly, same
as before.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-15 09:01:22 +00:00
89a3dec5d9
feat(xce-build): discount --jobs for forked compiler/assembler children per profile
nproc - load_avg treats one ninja job as one process, but the compiler
driver forks cc1/cc1plus then as, and asan/debug keep those children
resident far longer than release's leaner ones -- under-throttling by
roughly that factor. Apply a per-profile PROCESS_FACTOR (0.5 for
asan/debug, 0.7 for release) to the CPU term before taking the min with
the memory-budget term.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-15 06:35:34 +00:00
0f3919f195
fix(lib): stop cbuf_put/get orphaning their mutex on cancellation, hanging vtaskmgr_fini
pthread_cond_wait() reacquires its mutex before honoring a cancellation,
but mylock.c installed no cleanup handler to release it again -- a
thread cancelled mid-wait terminated holding the lock forever. vtaskmgr's
pthread_cancel()-based teardown could land there from three angles
(dispatcher cancelled while polling the shared queue, or a vcpu racing
back into it after its own shutdown signal), permanently deadlocking any
other thread that touched the same queue and hanging vtaskmgr_fini()'s
pthread_join() indefinitely.

Reproduced live as xce_test hanging on Ctrl-D exit once a connection
context was entered; gdb confirmed a vcpu thread blocked forever on a
mutex owned by an already-exited thread ID.

Fix: cbuf_put()/cbuf_get()/cbuf_timedget() now unlock via a
pthread_cleanup_push/pop handler around the wait, so a cancelled waiter
always releases the mutex. vcpu_idle()/vcpu_entry() also recognize the
teardown poison pill and exit immediately instead of needlessly
re-announcing into the already-dead shared queue.

New test_vtaskmgr_teardown.c reproduces the race deterministically
(self-pinned to one CPU, since true multi-core parallelism rarely hits
the window) and bounds vtaskmgr_fini() with a timed join so a
regression fails fast instead of hanging the suite. Logged as bug-1810.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-15 04:13:53 +00:00
b7250c2ec6
fix(scheduler): downgrade routine EEXIST resync log, dedup hash_string
xce_core_push_events() WARNed on every JOBS_PUSH resync redelivery
(sched_add_job rc=-EEXIST), which is the expected outcome under
on_scheduler_join()'s full resync or the array-push dedup race
(bug-1734/bug-1714) and flooded operational logs. Only that case now
logs via a new DBG() macro (utils.h); any other add_rc (e.g. -ENOMEM)
still WARNs. DBG is named to avoid colliding with the build's own
-DDEBUG command-line define (debug/asan buildtypes).

Also collapsed hash_string()'s duplicated djb2 loop to delegate to
hash_block(), which already implements the same RUN_HASH loop.

Logged as bug-1809 in .wolf/buglog.json.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-15 02:46:52 +00:00
868c6427c8
fix(harness): reset getopt_long via optind=0 to stop cross-command corruption
Every cmd_* REPL handler in test.c/join_worker_args.c reset flag parsing
with `optind = 1;` only. glibc's getopt_long only fully reinitializes its
internal scan state (nextchar/first_nonopt/last_nonopt) when optind==0, or
on the process's very first getopt_long() call ever -- optind=1 alone
leaves that state stale for every call after the first. Since xce_test's
REPL dispatches many independent cmd_*() calls per process, a command
whose parse ends on a short no-argument flag (`qctrl -a`, `hostctrl -o`)
left state that corrupted the NEXT unrelated command's parse badly enough
to misread its own name as an unrecognized flag. This was the actual
cause of harness_unit_test's 4 deterministic (not flaky -- 20/20 identical
repeat runs) test_test_cli.c failures, each burning its full 5s
confirmation-prompt timeout. Fixed by using optind=0 at all 21 reset
sites; confirmed via 3 isolated pty repros plus 10 consecutive clean
harness_unit_test runs (132/132, was 4 failures/run every time).

Also fixes a resource leak found while investigating: test_test_cli.c's
spawned xce_test sessions were only torn down by inline
clitest_kill_and_reap()/clitest_close() calls at the bottom of each test
function, which Unity's longjmp-based TEST_ASSERT abort skips entirely on
failure, leaking the child process and its pty/pipe fds. Added a static
session mirror (safe across the longjmp, unlike a stack pointer) reaped
from harness_test.c's tearDown(), which Unity guarantees runs after every
test regardless of outcome.

Logged as bug-1807/bug-1808 in .wolf/buglog.json, with the underlying
getopt/longjmp gotchas recorded in .wolf/cerebrum.md. Full ASAN
/xce-build harness also passes 5/5 with no sanitizer findings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 23:16:11 +00:00
cbf822fc53
fix: repoint stale controller/xce_test path references to harness/xce_test
Follow-up to the xce-harness-component spec, which relocated xce_test
from src/controller/testsuite/ into a standalone src/harness/
component (commits cf55d691..cf380750). These four files were outside
that spec's own file boundary (owned by other specs / general tooling)
so were deliberately left alone at the time, but their hardcoded
default path and error-message advice were now stale and would have
misled anyone who hit them:

- .claude/skills/xce-build/SKILL.md: added `harness` to both component
  lists (frontmatter description + args section), and replaced the
  "controller always builds xce_test too" claim with an accurate
  description of the harness component, its own build command, and
  the accepted Meson test-runner quirk (bug-1806) that can still
  transitively rebuild xce_test as a side effect of another
  component's default-profile test run.
- src/controller/testsuite/test_rcfile_integration.sh (owned by the
  xce-test-rc-file spec): XCE_TEST_BIN default and failure message.
- src/controller/testsuite/clean_failover_preservation.sh (owned by
  ha-term-safety task 5.2): same.
- src/tools/test-commit-durability.sh: same, plus its header comment.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 11:49:01 +00:00
cf380750a3
chore(xce-harness-component): mark spec implementation-complete
All 16 tasks implemented, independently reviewed, and feature-level
validated GO (/kiro-validate-impl): mechanical (173+1213 tests, 0
failures), design/boundary alignment (zero controller-private
dependency, both sanctioned exceptions exact match), requirements
coverage (22/22 mapped), and all four downstream workflows verified
end-to-end from a genuinely harness-absent build state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 11:28:00 +00:00
2f7b64b468
docs(xce-harness-component): refresh harness CLAUDE.md post-implementation
Feature-level validation (/kiro-validate-impl) found src/harness/CLAUDE.md
(written by task 1.3, before tasks 2.1/2.2/3.1 landed) still claimed no
/xce-build harness entry point and no unit-test binaries existed -- both
false by the time all 16 tasks completed. Updated to describe the real,
final state: /xce-build harness as the build command, and all 5 test
binaries (harness_unit_test + 4 standalone) under the harness suite.

Also logs one more out-of-boundary stale-path finding
(src/tools/test-commit-durability.sh:97) for a future owner.

This closes out feature-level validation for xce-harness-component --
mechanical (173+1213 tests, 0 failures), design/boundary alignment
(zero controller-private dependency, both sanctioned exceptions exact
match), and requirements coverage (22/22 mapped) all passed cleanly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 11:27:15 +00:00
9d81eda553
test(xce-harness-component): verify all downstream workflows end-to-end
Validation-only task, no source changes. Ran all four downstream
workflows (xce-test-ha, xce-deploy-ha, xce-test-multihost,
xce-test-resources) against a genuinely harness-absent, otherwise
fully-built dir -- established by explicitly removing harness/xce_test
immediately before each invocation, since sibling-component builds
(controller, worker, scheduler) kept transitively resurrecting it via
the same Meson mechanism task 4.3 documented.

xce-test-ha, xce-test-multihost, xce-test-resources all fail fast with
the documented clear, actionable "run /xce-build harness" message
before any expensive deploy work. xce-deploy-ha has zero harness
dependency (grep-verified) and deployed a real 3-node HA cluster
successfully with harness absent; its documented soft-skip path was
also exercised. All processes and deploy directories cleaned up and
independently re-verified by review.

This completes all 16 tasks of the xce-harness-component spec.

Task 4.4 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 10:36:43 +00:00
b3aa2af242
test(xce-harness-component): verify build isolation; narrow requirement 2.2
Validation task 4.3 found a real, deterministic conflict with the
original requirement 2.2 wording, not a flake: /xce-build controller
alone's default asan profile transitively rebuilds harness/xce_test,
because Meson's test-runner rebuilds every registered test's build-
order dependencies project-wide before filtering by --suite, and
harness_unit_test (task 2.1) depends on it. Confirmed via build-log
step-count analysis (explicit compile: 209 steps, clean; subsequent
meson test: 844 steps, resurrects it) and independently reproduced
twice, with an exact step-count match both times.

User decision (2026-09-14): accept as a documented Meson limitation
rather than auditing every component's test-target list (controller's
own suite already relies on this same mechanism for 4 of its own test
binaries) or weakening harness_unit_test's build-order guarantee
(verified load-bearing in task 4.2). Requirement 2.2 narrowed to what
the build system directly controls: its explicit compile-target list
never names xce_test. requirements.md/design.md/tasks.md updated to
match and cross-reference each other; logged as bug-1806 (accepted,
not fixed) for the record.

Also commits the xce-harness-component spec's remaining docs
(requirements.md, brief.md, research.md, spec.json) and the roadmap.md
promotion entry from discovery, none of which had been committed yet.

Task 4.3 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 09:59:15 +00:00
7958b395ae
test(xce-harness-component): verify harness_unit_test's build-order dependency
Validation-only task, no source changes. Proved the depends: [xce_test]
edge on harness_unit_test's meson test() registration is real, not
decorative, via two experiments: (A) renaming xce_test aside and
running via meson test -- meson auto-relinked it before testing,
confirming the build-graph edge genuinely exists (verified against
meson-info/intro-tests.json); (B) renaming it aside again and invoking
harness_unit_test directly, bypassing meson's dependency-aware rebuild
-- test_test_cli.c (25) and test_xcetest_process_entry.c (4) failed
loudly with clear exec-failure messages (132 Tests 29 Failures), never
silently passing. Binary restored and checksum-verified after each
experiment; final suite confirmed green (4/20/5/12/132, 0 failures).

Independently reproduced by review with a fresh temp binary name,
including catching an ASAN_OPTIONS environment-inheritance quirk in
raw (non-meson) invocation before matching the exact result.

Task 4.2 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 08:35:50 +00:00
973d38f20b
test(xce-harness-component): verify xce_test behavioral parity after relocation
Validation-only task, no source changes. Confirmed via: file-identity
spot-checks (7 of 15 production files across two independent passes,
all zero content drift since relocation beyond the one documented
ctrlstatus_fmt.h include-path edit); a fresh harness suite run
reproducing known-good counts (4/20/5/12/132 tests, 0 failures);
byte-diffing a genuine pre-relocation binary (src/build.dbg/controller/
xce_test, predates the move by 3 days) against the harness-built binary
for --help/--usage/piped REPL commands -- identical output, confirmed
independently by two separate passes.

Found a real, non-blocking follow-up (pre-scoped as out of this spec's
boundary): two integration scripts outside the 15 relocated files
(test_rcfile_integration.sh, clean_failover_preservation.sh) hardcode
a stale default xce_test path. Logged in Implementation Notes for
whoever owns those scripts next.

Task 4.1 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 08:10:48 +00:00
64e4ccb308
docs(xce-harness-component): list harness in structure.md
Add harness to structure.md's top-level src/ directory tree (after
controller/) and extend the flat-root Exceptions bullet to cover it
alongside controller. Verified against the real src/harness/ layout
(14 flat .c files, no nested src/, own include/ and testsuite/).

This completes Major Task 3 (Integration) -- all downstream skills and
steering docs now correctly describe the harness component.

Task 3.7 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 07:56:15 +00:00
6318183b67
docs(xce-harness-component): document harness in root CLAUDE.md and build-deployment.md
Add harness to root CLAUDE.md's /xce-build component list and
Subdirectory Guidelines (pointing at src/harness/CLAUDE.md). Remove
build-deployment.md's false "controller always builds xce_test" claim
and add harness to its /xce-build command table, Meson Structure tree,
dependency-flow line, and worked compile-target example.

Review round 1 caught a third surviving instance of the same stale
claim in the bug-1565 illustrative paragraph, contradicting the
corrected text two paragraphs above it -- fixed to reference the
binaries controller actually produces (xce_controller,
controller_unit_test) instead of xce_test.

Task 3.6 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 07:45:26 +00:00
ae3ab2b47c
feat(xce-harness-component): xce-test-resources builds/checks harness explicitly
run-resource-verify.sh's XT default now points at
\$BUILD_DIR/harness/xce_test and fails fast (actionable "run
/xce-build harness" message) if missing -- it drives
inject_resources()'s worker join/resupdate and
internal_controller_check()'s client-context resval, so a hard
failure is correct, matching the precedent from tasks 3.2/3.4.

SKILL.md's build-prerequisite content folded into the existing Usage
section (this skill has no standalone Prerequisites heading, unlike
its siblings) plus a Dependencies section update.

Verified live: sourced the script (main() guarded), called
precondition_checks() present then absent then restored
(checksum-verified intact).

This completes all four downstream-workflow tasks (3.2-3.5) --
xce-test-ha, xce-deploy-ha, xce-test-multihost, and xce-test-resources
all now handle the harness/controller build decoupling correctly.

Task 3.5 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 07:29:23 +00:00
0626234792
feat(xce-harness-component): xce-test-multihost builds/checks harness explicitly
run-multihost-verify.sh's XT default now points at
\$BUILD_DIR/harness/xce_test and fails fast (actionable "run
/xce-build harness" message) if missing. xce_test is the sole
mechanism (xtest()) by which the script's job-scenario functions
talk to the cluster, so a hard failure is correct, matching task
3.2's already-approved precedent.

SKILL.md's Prerequisites, env-var docs, and Dependencies sections
updated to match.

Verified live: sourced the script (main() guarded from running),
called precondition_checks() with the binary present and then moved
aside, confirmed the exact failure message, restored the binary
(checksum-verified intact).

Task 3.4 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 07:21:28 +00:00
5bd1c75c8e
docs(xce-harness-component): document harness soft-skip in xce-deploy-ha
Extend SKILL.md's existing worker/scheduler/xceadmin soft-skip
documentation to cover harness/xce_test: a Prerequisites bullet and a
Troubleshooting row, matching the existing style exactly.

Confirmed documentation-only: deploy-ha.sh (653 lines, read in full)
has zero reference to xce_test/harness -- it only builds/wraps
worker/scheduler/apiserver/xceadmin, never touches xce_test, which is
a manually-invoked tool rather than something deploy-ha.sh generates
a wrapper for. No script change needed or made.

Task 3.3 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 07:08:25 +00:00
84c812b083
feat(xce-harness-component): xce-test-ha builds/checks harness explicitly
run-ha-soak.sh's XT default now points at src/xce.build/harness/xce_test
(where /xce-build harness places it) and fails fast (exit 2, actionable
"run /xce-build harness" message) if missing, rather than assuming a
controller build produced it. xce_test is the soak's own driver client
(~30 call sites: job submit/verify, walcompare, waldump, snapdiff,
worker join/cancel), so a hard failure is correct, not a soft-skip.

SKILL.md's build instructions, goal-loop rebuild step, and
troubleshooting table updated to mention building harness, with
--incremental guidance correctly conditioned on build-dir-clobbering
semantics (bug-1565) rather than blanket-recommended.

Verified live: moved the binary aside, ran the script, confirmed the
exact failure message, restored the binary (checksum-verified intact).

Task 3.2 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 06:57:08 +00:00
9a4f1aa942
feat(xce-harness-component): add /xce-build harness, decouple from controller
Add a harness) case to src/tools/xce-build.sh following the same
three-part template (setup_build / meson compile / conditional meson
test) already used by scheduler)/worker), building all 6 harness
targets (xce_test plus its 5 test binaries) and running suite harness.
Remove controller/xce_test from the controller) case's compile target
list -- it no longer exists as a controller target. Add harness to the
script's usage/component-list text.

Verified both directions: `/xce-build harness` alone produces xce_test
and all 5 test binaries (4/20/5/12/132 tests, 0 failures); `/xce-build
controller` alone no longer produces controller/xce_test while
controller_unit_test stays green at 1199 tests.

Task 3.1 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 06:45:11 +00:00
49cf25aa23
feat(xce-harness-component): relocate the four standalone test binaries
Move test_resval_typeresolve.c, test_joblist_display.c,
test_join_worker_args.c, and test_listrow_json.c into
src/harness/testsuite/, and re-create their executable()/test() blocks
verbatim in src/harness/meson.build under suite 'harness' (task 1.1 had
already fully deleted them from src/controller/meson.build, not just
moved them, so these had been orphaned on disk since that commit).
Fix test_joblist_display.c's ctrlstatus_fmt.h include path to the
xce/ location promoted in task 1.2.

Verified against the pre-task-1.1 baseline (git show cf55d691^): all
four blocks' source lists, c_args, and env are faithfully reproduced,
only paths and the suite tag changed.

harness suite: 5 binaries, all green (resval_typeresolve 4, joblist_display
20, join_worker_args 5, listrow_json 12, harness_unit_test 132 -- 173 total,
0 failures). controller suite unchanged: 1199 Tests 0 Failures 0 Ignored.

This completes Major Task 2 (Core) -- the harness component now owns all
5 of its test binaries independently of the controller build.

Task 2.2 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 06:08:55 +00:00
b5873a67aa
feat(xce-harness-component): consolidate harness_unit_test binary
Relocate the 13 test files that lived inside controller_unit_test into
src/harness/testsuite/, add a new Unity runner (harness_test.c, modeled
on controller_test.c) carrying their extern/RUN_TEST entries, and
register the new harness_unit_test executable + suite in
src/harness/meson.build with an explicit build-order dependency on
xce_test (two of its tests spawn that binary over a pty).

Finish clearing the controller side: remove test_test_cli.c/
test_xcetest_process_entry.c from controller_unit_test_src and their
extern/RUN_TEST entries from controller_test.c, and remove the
temporary xce_test_controller_link symlink bridge task 1.1 added (no
longer needed now that both binaries build as siblings under harness/).

Verified: harness suite 132 Tests 0 Failures 0 Ignored; controller suite
1199 Tests 0 Failures 0 Ignored. 1199+132=1331 matches the pre-move
controller_unit_test baseline exactly (cross-checked against buglog
bug-1798/bug-1805).

Task 2.1 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 05:49:31 +00:00
79628f7b2b
docs(xce-harness-component): add harness component guide
New src/harness/CLAUDE.md documenting the component's purpose, current
build command, and file layout -- every claim grounded in the live repo
state (verified: no /xce-build harness entry point yet, no
harness_unit_test binary yet, both land in later tasks of this spec).

Task 1.3 of xce-harness-component -- completes the Foundation phase.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 05:28:25 +00:00
9ed680258e
feat(xce-harness-component): promote ctrlstatus_fmt.h to shared xce/ include path
Move the one genuinely shared header (header-only, static inline, zero
link dependency) from src/controller/testsuite/ to src/include/xce/,
alongside the existing cross-daemon shared headers (cluster.h, types.h,
errnox.h). Repoint its three current consumers (harness's test.c and
joblist_display.c, controller's test_ctrlstatus.c) to the new path.
test_joblist_display.c is intentionally left on the old path -- it
relocates in task 2.2.

Also removes src/harness/meson.build's temporary '../controller/testsuite'
incdir shim, which task 1.1 added and explicitly marked for removal once
this task landed.

controller_unit_test: 1228 Tests 0 Failures 0 Ignored (unchanged from
task 1.1's baseline, confirming a header-path-only change).

Task 1.2 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 05:20:21 +00:00
cf55d691de
feat(xce-harness-component): relocate xce_test into standalone harness component
Move xce_test's 15 production sources + headers from src/controller/testsuite/
into a new src/harness/ component with its own meson.build, and strip every
now-dangling controller-side reference (11 controller_unit_test_src entries,
4 standalone test-binary blocks, 11 controller_test.c extern/RUN_TEST lines)
so the controller build is never left broken.

Fixes a broken relative-symlink bridge (xce_test_controller_link) added to
keep two controller-embedded tests (test_test_cli.c, test_xcetest_process_entry.c)
finding the relocated xce_test binary until task 2.1 moves them too.

Discovered and documented in design.md: four controller-domain regression
tests call functions directly from four of xce_test's own files, requiring
controller_unit_test to permanently recompile them from src/harness/ — a
real dependency neither the original discovery nor design audit caught.

controller_unit_test: 1228 Tests 0 Failures 0 Ignored (verified via the
Unity binary's own printed summary line, not just meson's aggregate count).

Task 1.1 of xce-harness-component.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-14 05:08:15 +00:00
b8ef82c1b2
chore(wolf): regenerate handoff, sync anatomy/memory bookkeeping
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-13 09:43:21 +00:00
0480798583
add weekly report and change log for Sep 06-12, 2026
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-13 09:40:47 +00:00
25fb5c115a
fix(scheduler): sim resource over-commit, byte-unit display, sync job-state-at-capture
- bug-1799/1801: fix resInUse over-commit in sim replay -- sched_account_jobs's
  per-round re-derive pass now skips RECONCILING/UNAVAIL workers the same way
  core_reset_workers already does (bug-1751), closing the gap that let a
  worker's used slots exceed its own capacity across a resync replay
- bug-1804: revise scheduler-sim-eager-reconciliation spec (user-directed) so
  a captured job's job->state is set to RUN synchronously at dispatch capture,
  mirroring sched_commit_decision's normal-mode semantics (bug-1624), instead
  of deferring until its separately-recorded JOB_STATE_CHANGE event replays
- bug-1800: render bytes-valued CONSUMABLE resources (mem/swp/tmp) with the
  same human-scaled unit formatting already used for maxmem/maxswap/maxtmp
- bug-1802/1803: add then revert a break-on-ANY-event breakpoint kind after
  live feedback that it over-fires inside busy sessions; replace it with a
  prescan-based "next non-dummy session" hint in info summary instead

Full scheduler suite: 77/77 tests pass (asan profile).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
2026-09-12 14:06:41 +00:00
ffca959ed9
docs(skills): note join's corrected maxmem default at bare-join call sites
Non-functional: a repo-wide audit of every xce_test consumer against the
xce-test-cli-ux spec's completed changes (confirmation prompts, joblist/
reslist format fixes, stream routing, join's maxmem default, qctrl/getconf
fixes) found zero functional breaks -- every script drives xce_test via
piped non-interactive stdin (Req 9.4 auto-skips confirmation prompts) and
either checks exit codes/structured markers or already redirects 2>&1.

Add a one-line comment at each of the three bare `join` (no -m) call
sites noting the default changed from a stale 64 bytes to the correct
64MB (bug-1557), for future-reader clarity -- harmless in all three since
none of these synthetic hosts are ever scheduled against.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 10:01:02 +00:00
a83d7087f2
docs(xce-test-cli-ux): document jobsub -n's min,max task-range format
The hand-written per-flag description explaining -n's <min>[,<max>]
format was dropped when task 3.5 moved the flag list to the generated
flagspec block (which only shows short/long/required/default, with no
room for a flag's value-format semantics). Restore the explanation as
prose in USAGE_JOBSUB_HEAD, following the same pattern already used by
resupdate's HEAD (-n/-v pairing, -t's conditional meaning).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 08:39:05 +00:00
f09fbdb342
fix(build): close the same codegen race for the four PEG parsers (bug-1798)
Follow-up audit (requested: check other generated sources, specifically
packcc/PEG output) found the identical bug shape in the four PEG-parser
custom_targets: section_parser, rusage_parser, xce_resreq_parser, and
xce_select_parser each produce a .c + a paired .h (section.h, rusage.h,
xce_resreq.h, xce_select_peg.h), but libxce_src only referenced each
parser's [0] (.c) index. lib/resreq.c -- confirmed via a project-wide
grep to be the only consumer of any of these four headers -- had no
declared build-order dependency on any of the four codegen steps.

Fix: pass each of the four custom_targets unindexed into libxce_src,
same pattern as the capnp fix. No libxce_dep change needed here since
nothing outside src/lib/ consumes these headers.

A project-wide search confirms these, plus the capnp custom_target, are
the only multi-output C/H codegen steps in the whole build -- every other
custom_target() (xceadmin, apiserver, xcecli, autoscaler/providers)
produces a single Go-binary/stamp output with no equivalent hazard.

Verified: a third consecutive full from-scratch `./tools/xce-build.sh all
debug` build (1173/1173 targets) succeeded clean; a fresh `lib debug`
build plus the full lib test suite (313/313) passed; a fresh incremental
controller/ASAN rebuild passed 1331/1331 on a quiet re-run (its first,
concurrent-with-the-full-build run hit an unrelated, confirmed-flaky PTY
harness timing failure in test_smoke_launch_send_echo_capture_stdout_and_exit_code,
reproduced as system-load-induced, not caused by this change).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 07:53:51 +00:00
c1c6c9a248
fix(build): close capnp codegen race for controller/worker/scheduler too (bug-1798)
The previous fix (654c6e8c) only closed the missing-dependency-edge race
inside the libxce target itself. A live user report on a second
from-scratch `./tools/xce-build.sh all debug` run showed the same race
still hitting scheduler/src/sim_record.c and core_events.c, which reach
controller.capnp.h directly via a raw -Ilib include path with no
declared dependency on the codegen step at all.

Root cause: libxce_dep = declare_dependency(link_with: libxce) -- the
dependency object controller/worker/scheduler all consume uniformly --
only orders a consumer's LINK step after libxce is built; it never
propagated a build-order dependency on the capnp custom_target to a
consumer's own COMPILE steps.

Fix: add `sources: [gen_srcs]` to libxce_dep's declare_dependency() call.
This kwarg exists specifically for generated files that must be built
before any consumer of a dependency compiles, and since every component
already lists libxce_dep in its own dependencies, this one change
propagates the missing edge everywhere with no per-component changes.

Verified: two consecutive full from-scratch `./tools/xce-build.sh all
debug` builds (1173/1173 targets, the user's own exact repro command)
both succeeded with no retry; a subsequent incremental controller/ASAN
rebuild stayed clean (1331/1331 tests, 0 ASAN diagnostics).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 07:31:06 +00:00
654c6e8c75
fix(build): close capnp codegen missing-dependency-edge race (bug-1798)
libxce_src listed only gen_srcs[0] (controller.capnp.c) as a source of
the static_library('xce', ...) target, never controller.capnp.h -- which
several library files (utils.c and others) reach only via #include.
Ninja had no build edge forcing the capnp custom_target to finish before
those files compiled, so a from-scratch build could schedule them first,
intermittently failing with "controller.capnp.h: No such file or
directory". This is the same symptom recorded across 5+ prior recurrences
in buglog.json since 2026-07-16, previously worked around by retrying the
build rather than root-caused.

Fix: pass the whole gen_srcs custom_target (not gen_srcs[0]) into
libxce_src -- Meson still compiles only its .c output, but now orders the
entire target's build after both outputs are generated. Verified via two
consecutive from-scratch `xce-build.sh lib debug` builds (no retry
needed), the full lib test suite (313/313), and an incremental controller
asan rebuild (1331/1331, 0 ASAN diagnostics) to confirm no regression.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 07:10:44 +00:00
38595099b9
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
2026-09-10 04:36:42 +00:00
31d6606067
docs(xce-test-cli-ux): verify source's interaction with the confirmation gate (task 4.3)
Live-cluster validation, no source changes: independently reproduced
(implementer + reviewer, separate deploys) that a destructive command
inside a sourced file, run within an otherwise-interactive session,
still prompts for confirmation with wording identical to a directly-typed
invocation, is skipped once the session toggle is set, and that decline
does not trip set -e's abort-on-failure (Req 13.7). Structurally confirmed
the gate has no code path capable of distinguishing a sourced line from
a typed one. Bumps bug-1797's occurrence count (recurred via the source
call path, confirmed pre-existing, not new).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 04:00:24 +00:00
f6793a24f1
docs(xce-test-cli-ux): verify the confirmation gate end-to-end (task 4.2)
Live-cluster validation, no source changes: independently reproduced
(implementer + reviewer, separate deploys) that all five destructive
commands prompt by default, treat decline and real-SIGINT identically as
"not run" (not "failed", the deliberate Req 9.9 exception to Req 1.3),
skip the prompt under --yes/non-interactive/session-toggle, and match
Req 9.5's exact enumeration including its reversal-action exclusions.

Logs bug-1796 (misleading perror() text from stale errno in
cmd_qctrl/hostctrl/jobkill) and bug-1797 (cmd_qctrl queue-name leak on
the RPC-error path) as pre-existing, deliberately-deferred findings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 03:37:01 +00:00
18aa736665
docs(xce-test-cli-ux): verify Ctrl-C cancellation end-to-end (task 4.1)
Live-cluster validation, no source changes: independently reproduced
(implementer + reviewer, separate deploys) that an interrupted blocked RPC
abandons in ~0.0003s vs. the ~10s RPC deadline, reports failure, never
exits the session, and leaves the connection fully reusable after two
abandonments on the same connection.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 01:44:41 +00:00
a98fad24da
fix(xce-test-cli-ux): route diagnostic/warning messages to stderr uniformly
Audit every printf() call site in test.c not already covered by the
flagspec-rejection or perror() paths; convert 33 genuine error/warning
messages (expect-jobs, expect-job, wait-primary, help's not-found path,
jobrun/jobsub/jobstart/jobfinish/jobfail validation, resupdate, set) from
stdout to stderr, so a command's successful result data and its
diagnostics never share a stream.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-10 00:59:38 +00:00
96746af3eb
feat(xce-test-cli-ux): generate and consolidate every command's help content
Wire flagspec_render_help() into cmd_help via new command_t fields
(flagspec/flagspec_count/usage_tail), so every flag-accepting command's
help composes description -> generated flag block -> example/related
notes, with hand-written per-flag lines removed as a duplicate source of
truth. Add missing purpose descriptions, examples, and confirmation-gate
related notes across ~20 commands; fix bug-1711's "matchs" grammar
(Req 11.2); confirm join's corrected maxmem default (bug-1557, Req 12.2)
and the --json flag (Req 5.4) now render correctly end-to-end.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 23:55:56 +00:00
0d67f5cbde
feat(xce-test-cli-ux): add JSON output mode to the listing commands
Bring workerlist/joblist/reslist onto the shared flagspec_t library with an
identically-spelled --json flag, wired to the task-2.2 JSON list formatter
via a new pure field-mapping module (listrow_json.c/.h). Default table
output is unchanged; JSON rows carry raw numeric values (flags, timestamps,
memory sizes) rather than their humanized display strings, per Requirement
5.1's "same fields" contract.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 22:42:37 +00:00
a57c04716b
feat(xce-test-cli-ux): wire confirmation gate to the five destructive commands
Gates jobkill and shutdown unconditionally, qctrl only when action is
QUEUE_CLOSE/QUEUE_INACTIVE (not ACTIVE/OPEN), hostctrl only when
HOST_CLOSE (not OPEN), and upgradeconfig unconditionally -- exactly
Requirement 9.5's enumeration, with jstart/jfinish/jfail (worker
context) correctly untouched. Each gains a -y/--yes bypass flag via
flagspec_t; cmd_set gains -y/+y calling confirm_set_skip(). A decline
maps to a plain `return 0` (success-coded, distinct from a negative
failure return) per confirm.h's own documented contract -- this means
a declined destructive command inside a source'd file under `set -e`
won't trip abort-on-failure, a real but narrow interaction only
reachable when a human is actively declining; left for task 4.3 to
test explicitly. 1321/1321 across the full controller suite (+3),
0 regressions.

Task 3.3 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 21:47:55 +00:00
45120af2cc
feat(xce-test-cli-ux): wrap every blocking RPC with the interrupt adapter
Routes all 26 blocking xcecli_* call sites across ~24 commands through
xcetest_run_interruptible(), wires xcetest_set_active_connection() at
execute_line()'s dispatch point (active_ctx->ctx, read fresh per
command), and fixes main()'s REPL loop to distinguish a real EOF from
an EINTR-interrupted readline() so Ctrl-C at an empty prompt discards
the line instead of exiting the session.

Live-discovered and fixed bug-1794: fill_job_alloc() never initializes
xce_job_alloc_t's nres_shared/allocs_shared fields -- harmless as stack
garbage before this task, genuine heap garbage once moved into a
heap-allocated ctx block (a necessary consequence of the adapter's
heap-only precondition). Fixed by switching all ~26 call-context
allocations from malloc to calloc uniformly. Also fixed an argv-aliasing
hazard: cmd_hello/cmd_jobckpt's -m values aliased optarg, which
execute_line() frees immediately after return including on the
abandoned path -- now strdup'd into the heap block.

Also closed a safety-critical gap this task's own design introduced
(bug-1795): before this task the REPL was fully synchronous, so
leave_ctx() (called by up/quit) could never run while an RPC was
outstanding. An abandoned worker can now persist past command
completion, so leave_ctx() tearing down the connection could
use-after-free it. Fixed via xcetest_wait_connection_idle(), which
blocks on the same per-connection semaphore the adapter already
tracks, then releases it, proving no worker is active before teardown.
Proven with a deterministic white-box RED->GREEN test, since the race
itself is too timing-dependent for a black-box test to reliably force.

1361/1361 across the full controller suite (+2), 0 regressions.

Task 3.2 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 1.1, 1.2, 1.3, 1.4, 1.5

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 20:58:18 +00:00
f152c59e75
feat(xce-test-cli-ux): migrate all flag-accepting commands to flagspec
Migrates 17 commands (cmd_hello, cmd_jobinfo, cmd_jobrun, cmd_jobsub,
cmd_resval, cmd_jobkill, cmd_jobckpt, cmd_qctrl, cmd_hostctrl,
cmd_runtasks, cmd_setpend, cmd_jobstart, cmd_jobfinish, cmd_jobfail,
cmd_resupdate, cmd_walcompare, join_worker_parse_attrs) from raw
getopt()/hand-rolled parsing to the shared flagspec_t + getopt_long
mechanism, so every one now uniformly rejects an unrecognized or
malformed flag with a usage summary and, where a close match exists,
a suggestion. cmd_walcompare's hand-rolled parser needed a leading '+'
in its optstring to preserve its pre-migration flags-only-before-
positionals behavior. Also fixes bug-1704: cmd_qctrl's uninitialized
action variable, now sentineled and rejected when unset, mirroring
cmd_hostctrl's existing pattern -- this also makes the destructive-
command gate's -i/-c detection (task 3.3) safe to rely on. Every
existing short flag's letter, value format, and default is unchanged
for a valid invocation. 1357/1357 across the full controller suite
(+4), 0 regressions.

Task 3.1 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 2.1, 2.2, 2.3, 2.4, 6.1, 6.2, 6.3, 6.4, 10.1, 10.2, 10.3

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 17:27:48 +00:00
878a42fb48
fix(xce-test-cli-ux): fix bug-1557's join maxmem default
cmd_join_worker's simulated-worker maxmem default was 64 bytes -- a
leftover from when the field was MB-scale, unfixed when maxmem became
bytes-canonical elsewhere. Now 64 * 1024 * 1024. Extracted the
argument-parsing/defaulting logic into join_worker_parse_attrs()
(join_worker_args.c), since it runs entirely before the function's
network call and is a genuine testable seam -- same precedent as
task 2.5's joblist_display.c. Verified live against a real deployed
cluster (workerlist reports MaxMem: 64.00 MB) plus a permanent 5-test
regression suite. maxswap/maxtmp have the identical stale-default bug
(logged as bug-1793) but are deliberately left unfixed here since
USAGE_JOIN_WORKER's help text currently documents their stale values
accurately -- fixing only the code would create a new docs mismatch;
a locked-in sibling-defaults test documents this for the follow-up.
1353/1353 across the full controller suite (+5), 0 regressions.

Task 2.6 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 12.1

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 16:24:36 +00:00
a8154acb0a
fix(xce-test-cli-ux): fix bug-1711's display and text defects
Eight display/text defects in test.c: worker_status_str's "UNKOWN"
typo, cmd_runtasks's "sequentail" typo (display-only, verified inert
against the real launch_type consumer), cmd_reslist's right-justified
columns and unlabeled hex Flags (now matching workerlist/state_raw's
conventions), joblist's raw-epoch timestamps (now via a format_job_time
helper delegating to the same formatter ctrlstatus already uses) and
combined NTasks column split into MinTasks/MaxTasks, job_state_str's
missing raw-state fallback for ambiguous RUN+EXIT (mirroring
print_jobinfo's existing pattern), and getconf's no-op group/config
list stubs (now genuinely implemented from already-fetched data,
matching the three sibling print functions' convention).

worker_status_str/job_state_str/format_job_time are pure functions with
no networking/REPL/global-state dependency, extracted into a new
joblist_display.c/.h module with a permanent 20-test standalone suite --
following this codebase's own resval_typeresolve.c/misc.c precedent for
testing functions that would otherwise be stranded inside untестable
test.c. cmd_reslist/joblist_query/cmd_getconf's table-printing bodies
inline fetch+print and remain untestable without a live cluster.
1348/1348 across the full controller suite (+20), 0 regressions.

Task 2.5 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 11.1, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 15:34:55 +00:00
c709eba813
feat(xce-test-cli-ux): add in-session source command with cycle detection
cmd_source reuses rcfile_load() unmodified for line execution, adding
an explicit missing-file check (bypassing rcfile_load's silent-missing
policy, which is correct for its one existing startup-rc-file caller
but wrong for an explicit user command) and a realpath()-canonicalized
in-flight path stack that rejects direct or transitive cycles instead
of hanging. Registered in all four command contexts. Translates
rcfile_load's raw positive "aborted" return to -1 so an enclosing
source line correctly sees a transitively-aborted nested source as
failure, not success (preprocess_and_run only treats negative returns
as failure). Proven via real fixture files driven through the black-box
pty harness: a genuine two-file mutual cycle, a missing path, and
ordered execution across a non-cyclic nested source. 1310/1310
controller suite passing (+3).

Task 2.4 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 13.1, 13.2, 13.3, 13.4, 13.5, 13.6

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 14:25:37 +00:00
0ef232a013
feat(xce-test-cli-ux): add command-name tab completion scoped to context
Registers libedit's GNU-readline-compatible rl_attempted_completion_function
under g_interactive only. The candidate generator reads active_ctx->commands[]
live on every call, so completion correctly tracks context switches rather
than freezing at registration time. Single/multi-match UI (auto-complete vs.
double-Tab candidate listing) is entirely libedit's stock behavior once given
a correct context-scoped generator. Proven via a black-box pty test verified
sound against a false-positive risk: xce_test has no fuzzy command-name
matching, so an uncompleted partial token cannot coincidentally trigger the
same effect a real completion would. Also fixes a harness bug (bug-1792):
disabling kernel ECHO for output capture was silently suppressing libedit's
own completion feedback too; added clitest_spawn_ex() with disable_echo as
an explicit parameter, clitest_spawn() unchanged for existing callers.
1307/1307 controller suite passing (+1), re-verified 8/8 for flakiness.

Task 2.3 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 7.1, 7.2, 7.3, 7.4

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 13:38:56 +00:00
07d238eada
feat(xce-test-cli-ux): build JSON list-output helper library
listfmt_json_begin/new_row/add_string/add_number/finish wrap cJSON
(already linked via struct2json_dep) into a minimal array/object
lifecycle library with no generic "record" abstraction -- each command's
own row struct maps its fields directly when wired in later (task 3.4).
Proven via a real stdout-capture-then-reparse round trip, including a
733-character field with no truncation, and stderr staying empty.
1306/1306 controller suite passing (+9).

Task 2.2 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 5.1, 5.3

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 12:13:12 +00:00
a2686516f7
feat(xce-test-cli-ux): build destructive-command confirmation gate
confirm_destructive() prompts on stderr and blocking-reads a y/n answer
via a single, non-looping fgets() call (not libedit) -- the mechanism
that makes a real Ctrl-C during the prompt return EINTR and be treated
as a decline (Requirement 9.9), same as an explicit "n" or EOF.
confirm_set_skip()/confirm_is_skip_set() add a session-scoped toggle
mirroring cmd_set's existing -e/+e style. Auto-skips when input is not
interactive, via a new xcetest_is_interactive() accessor over the
existing g_interactive global. Destructive-command enumeration and
per-command wiring (Requirement 9.5) is task 3.3, not this task.
Proven with a real fork+SIGINT test. 1297/1297 controller suite
passing (+7).

Task 2.1 of .kiro/specs/xce-test-cli-ux/tasks.md.
Requirements: 9.1, 9.2, 9.3, 9.4, 9.6, 9.7, 9.8, 9.9

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 11:41:05 +00:00
7d0ac6f6eb
docs(xce-test-cli-ux): commit requirements/design/tasks spec-phase artifacts
Captures the spec-authoring work from earlier in this session: expanded
requirements.md (Requirements 8-13 added during discussion: detailed
help content, destructive-command confirmation, actionable flag
suggestions, bug-1711/bug-1557 fixes, and the source command), plus
the corresponding spec.json phase/approval updates. design.md and
tasks.md were already committed alongside the first implementation
task (0748f10c); this closes the gap so the full spec-authoring
history is captured in version control, matching the approvals the
user already gave interactively during this session's requirements
review, design review, and task-plan generation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 11:40:26 +00:00
4d1f247674
test(xce-test-cli-ux): build reusable pty-driven black-box CLI harness
clitest_spawn/send_line/send_partial/send_tab/send_signal/wait_for_text/
wait_for_exit/kill_and_reap launch the real compiled xce_test behind a
genuine pty (so isatty/g_interactive/libedit behave as a real terminal),
with stderr routed to a separate pipe for real stream-separation testing.
All waits are poll()-bounded with an explicit timeout so a future
regression can't hang the whole test suite. This is the shared
infrastructure tasks 2.3, 3.5, and all of Validation phase (4.1-4.4)
will build their black-box scenarios on top of. One smoke test proves
launch/send/capture/exit-code/stream-separation end to end.
1290/1290 controller suite passing (+1).

Task 1.7 of .kiro/specs/xce-test-cli-ux/tasks.md.
Foundation phase (1.1-1.7) now complete.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jaMf9QEwpugH2W9KAuc7f
2026-09-09 11:06:31 +00:00