Skip to content

Smoke the gateway health probe on Intel Mac - #395

Draft
SashaMIT wants to merge 18 commits into
cursor/launcher-contract-1297from
cursor/intel-mac-gateway-smoke-1297
Draft

SashaMIT wants to merge 18 commits into
cursor/launcher-contract-1297from
cursor/intel-mac-gateway-smoke-1297

Conversation

@SashaMIT

@SashaMIT SashaMIT commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Stack: this PR sits on #394 (cursor/launcher-contract-1297). #397 sits on this branch. Head: e50fe79a. It carries six merges of #394 (028c6137 brings in the zip 9 fix that #394 already merges; 3ab6cb82 brings in the held-lock journal test fix; ed21329f brings in #394's 36720070, which proves gateway lock ownership from the held flock, not the lock record; 12fc78b2 brings in #394's 4bb19dcf: the ownership proof is one step (each registry entry keeps a second descriptor of the locked open file, and the registry mutex is held from the lookup to the end of the probe; 85f3142e); the managed-runtime subordinate lane uses the same proof as /healthz, and a Home terminal gets an inherited lock descriptor, ELASTOS_GATEWAY_HOST_LOCK_FD (eed83a72); a held lock whose record cannot be read still counts as held (4bb19dcf); 0bf525a7 brings in #394's 13cdcad0: the contract states that the lock proves possession, not that the holder is the gateway, with two process tests; docs and tests only; e50fe79a brings in #394's head d30027ed, #394's merge of develop). None of these merges changes this PR's diff against #394. 3ab6cb82 also brings in #394's ce5d187b (listen on every localhost address). On top: 630efc6d keeps test_default_is_the_contract_command off the real port 8090, ac97a4aa changes "owns" to "holds" in the smoke script header and the Intel CI comment, as the contract says, and 914acb9a makes every smoke test end on an event, not on a 3 s deadline (below; test only). On e50fe79a, scripts/gateway-healthz-smoke-test.py: Ran 26 tests ... OK (skipped=3), and scripts/ci-release-policy-test.py: Ran 110 tests ... OK.

scripts/gateway-healthz-smoke.sh checks the readiness that the launcher contract defines in "Readiness and Home URL". It starts the contract command elastos gateway --addr localhost:8090 (the script default, ELASTOS_GATEWAY_ADDR-localhost:8090) and polls GET http://localhost:8090/healthz. It passes only when all of these are true:

  • the answer is HTTP 200 with the two bytes OK (curl --noproxy '*' --proto =http),
  • the address curl connected to (%{remote_ip}) is a listen socket of the gateway pid (lsof -iTCP@<ip>:<port>),
  • host-process.lock in the data directory names that pid, role gateway or gateway-public, and the same addr.

HTTP 503 (the contract's not-ready answer) is polled until the deadline. Any other status fails. An empty Home can pass. That is not proof of providers, capsules, sign-in, or a signed install. elastos serve reports operator status at GET /api/health.

After the readiness check the script prints facts, not pass or fail: the localhost lookup order, the addresses the gateway listens on, and what GET /healthz returns at localhost:8090, 127.0.0.1:8090 and [::1]:8090, with the process that answered. For --addr localhost:8090 the gateway listens on every localhost address. This comes from #394 (ce5d187b), not from this PR: gateway_server.rs:102 calls bind_gateway_listeners (:296-309), which for the host localhost resolves the name and binds each result plus 127.0.0.1 and ::1 on one port (localhost_bind_addresses, :313-338; bind_localhost_listeners, :343-383). It refuses to start when an address is held by another program or localhost points off this computer. It leaves out only an address family the computer does not have. Any other host binds exactly as given (:298). The contract text is docs/LAUNCHER_CONTRACT.md:19-22.

Cleanup signals the gateway process group and the pid, waits until neither is alive, and then sends SIGKILL. It runs on success, failure and INT/TERM/HUP. The deadline must be a whole number from 1 to 9999. The address must be localhost, 127.0.0.1 or [::1] with a port from 1 to 65535. An unknown host OS or a missing curl, lsof or python3 stops before the gateway starts.

docs/MAC.md cites the installer message macOS release lookup requires Apple silicon, which is what scripts/install.sh:331 prints on this branch. A person with an Intel Mac has no signed download. The next step is the signed installer on an Apple silicon Mac. The source-home section is a developer build, not that next step.

Candidate: e50fe79a. Draft. Do not merge.

No test depends on stub start time (round 5 review: "still timing-flaky (2 of 3 local runs fail)")

Cause: every test gave the smoke ELASTOS_GATEWAY_HEALTH_DEADLINE=3 (old gateway-healthz-smoke-test.py:173,182). The smoke checks its deadline after each probe (gateway-healthz-smoke.sh:121,142-145) and then stops the stub. The stub is two python3 starts (the setsid wrapper at gateway-healthz-smoke.sh:116 and the stub itself). When python3 starts slowly (the macOS /usr/bin/python3 shim, a cold cache, a busy host), the stub has not written args.json (or bound, or forked) when 3 s pass. The smoke then exits 1 with GET http://localhost:8090/healthz was not ready within 3s (last: no answer). That message also names the URL, so only the args.json read failed. Port 8090 was not the cause after 630efc6d: the test's curl never connects.

Reproduced on Linux with a python3 on PATH that sleeps 1.0 to 2.0 s before it starts the real one, at ac97a4aa, test_default_is_the_contract_command 30 runs each:

B-jitter-free: 18 failures out of 30 (8090 probe before: HTTP 000, load=idle, python3=jitter)
B-jitter-busy: 19 failures out of 30 (8090 probe before: HTTP 200, load=idle, python3=jitter)
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmplkhficb2/args.json'

CPU load alone (8 busy loops on 4 cores, 8090 busy) did not reproduce it here: 0 of 30. With each python3 start delayed 1.5 s, the whole file at ac97a4aa gave FAILED (failures=20, errors=1, skipped=3). Every test that waits for the stub depended on the 3 s deadline.

914acb9a (test only, the smoke script is unchanged):

  • Tests that end on an event (an answer, a refusal, the stub's exit) give the smoke its largest deadline, 9999 (NO_DEADLINE). The deadline cannot end them. HANG_GUARD (600 s) only stops a hung run. In CI the step's timeout-minutes: 5 is the backstop.
  • test_default_is_the_contract_command uses a stub mode exit-after-probe: it writes its arguments, stays alive until the smoke has run curl once, then exits. The smoke always ends on gateway exited before GET http://localhost:8090/healthz was ready, which the test now checks exactly. The check that curl was given only http://localhost:8090/healthz is no longer optional (before, it was skipped when curl never ran). Curl still never connects, so port 8090 does not matter.
  • The tests that need the deadline to pass (test_503_until_deadline_is_not_ready, test_group_is_stopped_after_timeout, test_child_ignoring_term_is_killed) put a curl on PATH (gated_curl_path) that waits until the stub listens (SMOKE_READY) or its child has written its pid, then runs the real curl. The smoke checks the deadline only after a probe returns, so the first probe always sees that state. They now use a 1 s deadline and check the "not ready within 1s" message. c3812551's 3 s deadline for the two cleanup tests is replaced by this.
  • test_facts_name_another_process_on_the_other_family waits the same way for the stub to listen on [::1], so curl cannot fall back to the other process on 127.0.0.1 before the stub binds (that skipped the test, it did not fail it).
  • test_group_is_stopped_when_the_smoke_is_interrupted waits for the child pid without the old 10 s cap. test_early_exit_is_not_ready and test_503_then_200_is_ready drop their 5 s and 10 s deadlines.

After 914acb9a, test_default_is_the_contract_command, 50 runs each:

A-load-busy: 0 failures out of 50 (8090 probe before: HTTP 200, load=load, python3=real)
A-load-free: 0 failures out of 50 (8090 probe before: HTTP 000, load=load, python3=real)
A-jitter-busy: 0 failures out of 50 (8090 probe before: HTTP 200, load=idle, python3=jitter)
A-jitter-free: 0 failures out of 50 (8090 probe before: HTTP 000, load=idle, python3=jitter)

The whole file: with each python3 start delayed 2 s, Ran 26 tests in 167.540s OK (skipped=3); 3 runs under load with 8090 busy, each Ran 26 tests ... OK (skipped=3). With a 5 s delay, the default-command test passes (Ran 1 test in 11.099s OK).

Negative check: with the smoke default changed to ELASTOS_GATEWAY_ADDR-127.0.0.1:8090, the test fails: AssertionError: '["gateway", "--addr", "127.0.0.1:8090"]' != '["gateway", "--addr", "localhost:8090"]'. Restored after.

No test in the file uses a fixed port: the others take a free port from the OS (free_port()), and the contract test only reads files.

Hermetic default-command test (round 4 review: "fails when port 8090 is busy")

test_default_is_the_contract_command runs the smoke without ELASTOS_GATEWAY_ADDR, so the smoke polls the real http://localhost:8090/healthz. With another program on 8090 (python3 -m http.server 8090 --bind 127.0.0.1), the smoke got that program's answer and stopped before the stub wrote its arguments, and the test failed at head 12fc78b2:

FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpghl2hopy/args.json'
Ran 1 test in 0.044s
FAILED (errors=1)

630efc6d (test only): the test puts a curl on PATH (no_network_path) that records its arguments, prints 000 and exits 7, so it never connects. The test checks that the stub got ["gateway", "--addr", "localhost:8090"] and that every URL curl was given is http://localhost:8090/healthz. This removed the port 8090 dependency but kept the 3 s deadline; 914acb9a (above) removes that.

macOS portability of the tests (review: "15 tests fail on macOS")

The smoke script itself already ran on a Mac: CI job gateway-smoke-macos-intel (run 39018361478, job 117356202520, 028c6137) passed against the real Intel binary. That binary predates ce5d187b (not an ancestor of 028c6137), so it still bound one address, which is why 127.0.0.1:8090 got no answer:

ready: GET http://localhost:8090/healthz returned HTTP 200 and OK from gateway pid 59142 on [::1]:8090
ready: host-process.lock names pid 59142 with role gateway and addr localhost:8090
fact: gateway pid 59142 listens on: [::1]:8090
fact: this host resolves localhost to (in order): ::1 127.0.0.1
fact: GET http://127.0.0.1:8090/healthz: no answer

The failures were in the test stub, not the script. The stub always wrote host-process.lock under $XDG_DATA_HOME/elastos. On macOS the script (gateway-healthz-smoke.sh:49-50) reads $HOME/Library/Application Support/elastos, which is where the real binary keeps it: sources.rs:13-17 uses dirs::data_dir(), and dirs 5.0.1 src/mac.rs:7,12 gives $HOME/Library/Application Support and does not read XDG_DATA_HOME. So every test that needs a matching lock failed on a Mac.

  • 0c8d6c72 (test only): the stub picks the lock directory from uname -s, as the script does. It also skips the socket.getfqdn reverse lookup in HTTPServer.server_bind, which can take seconds on macOS. Two new tests run the macOS path on Linux with a uname shim: test_macos_lock_is_read_from_application_support and test_macos_lock_under_xdg_is_refused.
  • 02dcf5b1 (CI): the existing gateway-smoke-macos-intel job runs python3 scripts/gateway-healthz-smoke-test.py -v before it builds. No new job.
  • c3812551 (test only): test_group_is_stopped_after_timeout and test_child_ignoring_term_is_killed used a 3 second deadline, not 1. 914acb9a replaces this with a wait for the stub's child (above).
  • 3cffaad4 (docs only): docs/MAC.md no longer says --addr localhost:8090 binds one address. It cites the launcher contract for the listen rule.

No test is marked Linux-only: after the stub fix none of them needs Linux. The three IPv6 tests still skip, with a message, on a host with no ::1.

The script uses no GNU-only flags (no stat -c, date -d, timeout, sed -i, readlink -f, ss, /proc, mapfile, ${var,,} or associative arrays). mktemp -d, seq, sleep 0.2, paste -sd ' ' -, cmp -s and awk '$(NF - 1)' behave the same on macOS. The lsof NAME column is 127.0.0.1:8090 (LISTEN) or [::1]:8090 (LISTEN) on both, as the Intel log shows. The test's curl shims are /bin/sh and use sleep 0.05, which macOS sleep accepts.

Tests

python3 scripts/gateway-healthz-smoke-test.py -v on Linux x86_64 (no IPv6 loopback on this host), at e50fe79a:

test_default_is_the_contract_command ... ok
test_group_is_stopped_after_timeout ... ok
test_child_ignoring_term_is_killed ... ok
test_503_until_deadline_is_not_ready ... ok
test_group_is_stopped_when_the_smoke_is_interrupted ... ok
test_ipv6_loopback_ok ... skipped 'this host has no IPv6 loopback'
test_localhost_answer_on_another_family_is_refused ... skipped 'this host has no IPv6 loopback'
test_facts_name_another_process_on_the_other_family ... skipped 'this host has no IPv6 loopback'
Ran 26 tests in 42.434s
OK (skipped=3)

Simulated macOS on Linux (at 02dcf5b1): GNU bash 3.2.57 (the macOS /bin/bash version, built from source) first in PATH, and a uname shim that prints Darwin:

  • the old stub (3ab6cb82): FAILED (failures=7, skipped=3): test_ok_with_owned_lock_is_ready, test_503_then_200_is_ready, test_localhost_name_is_probed_as_given, test_group_is_stopped_after_success, and test_lock_that_is_not_this_gateway_is_refused for other-pid, bad-role and bad-addr. On a Mac with ::1, test_ipv6_loopback_ok and test_facts_name_another_process_on_the_other_family fail the same way.
  • the new stub: Ran 26 tests ... OK (skipped=3).
  • bash 3.2 alone (no shim) passes with both stubs, so bash 3.2 was not a cause.

Negative check: with gateway-healthz-smoke.sh:50 changed to read .local/share/elastos on Darwin, both macOS tests fail (host-process.lock is missing or is not JSON: ... home/.local/share/elastos/host-process.lock, and 0 != 1 for the XDG lock). Restored after.

scripts/ci-release-policy-test.py: Ran 110 tests ... OK. It checks that the probe step does not set ELASTOS_GATEWAY_ADDR, so CI keeps the contract address.

Real Mac: run 39090852848 (ac97a4aa, job 117568269225) passed "smoke script tests on macOS" and the smoke against the real Intel binary. 914acb9a has not run on a Mac yet; the gateway-smoke-macos-intel job on this head is its first Mac run. The three IPv6 tests, including the changed test_facts_name_another_process_on_the_other_family, run only there.

Disputed finding

/healthz is the lock-holder check in gateway_site.rs (healthz, which since #394 36720070 calls host_lock::holds_gateway_host_lock: this process holds the flock on the file the lock path names now; the JSON record is not read). It is not GET /api/health. The smoke also reads the host-process.lock record itself, so a pass does not rely only on the handler. That record is a hint, not proof (docs/LAUNCHER_CONTRACT.md, "Readiness and Home URL"). The lock itself proves possession, not that the holder is the gateway, so a smoke pass shows that the gateway pid answered, listens on the address curl used, and is named by the record; it does not prove more. It does not stage components.json, because the handler does not read that file.

The uploaded log can contain a planted attach_secret line. The test checks that the script does not print it. The Home in this job is an empty temporary directory, so the line is the stub's own output.

Branch names stay on the cursor/<name>-1297 line this agent uses.

CI notes

Principles check

  • P10. The smoke uses the contract command and URL. Other spellings are reported as facts, not checked as alternates.
  • P11. Unknown input, a non-contract status, a body that is not OK, an answer from another process, or a lock for another pid fails with a plain message.
  • P12. docs/MAC.md, the script header and the CI comment cite docs/LAUNCHER_CONTRACT.md for the readiness rule. The stub follows the same data directory rule as the binary. The tests do not depend on what listens on the host's port 8090 or on how fast the stub starts.

Intel stays C. No grade here is a merge approval.

Team issues

None. The Home origin is decided: localhost everywhere (docs/LAUNCHER_CONTRACT.md). The bind on every localhost address is implemented in #394 (ce5d187b), and run 39049051156 showed it on a real Intel Mac (both 127.0.0.1:8090 and [::1]:8090 answered from the gateway pid).

@cursor
cursor Bot force-pushed the cursor/intel-mac-gateway-smoke-1297 branch from de366cc to d35e72e Compare October 16, 2026 05:37
@cursor
cursor Bot changed the base branch from develop to cursor/launcher-contract-1297 October 16, 2026 05:39
@cursor
cursor Bot force-pushed the cursor/intel-mac-gateway-smoke-1297 branch from 8c2f9d8 to 471310d Compare October 16, 2026 11:53
cursoragent and others added 3 commits October 16, 2026 12:20
Build the native elastos binary on macos-15-intel and require GET /healthz
to return OK. Record why that smoke is not yet a signed x86_64-darwin release.

Co-authored-by: Sash <SashaMIT@users.noreply.github.com>
GITHUB_ENV applies on the next step, so the release build wrote elastos
into the workspace target dir and the /healthz probe looked in an empty
runner directory. The build step now exports that directory and checks
the binary is executable before the probe runs.

Co-authored-by: Sash <SashaMIT@users.noreply.github.com>
The smoke picks a free numeric loopback port, rejects any other address,
and accepts the two bytes OK only from the pid that owns the listen socket.
It signals that process group on the way out and keeps the gateway log
off stdout. MAC.md no longer tells a launcher to run another platform's build.

Co-authored-by: Sash <SashaMIT@users.noreply.github.com>
@cursor
cursor Bot force-pushed the cursor/intel-mac-gateway-smoke-1297 branch from 471310d to 18a2a66 Compare October 16, 2026 12:20
cursoragent and others added 2 commits October 17, 2026 05:42
The smoke requires HTTP 200 and the two bytes OK from the process that owns
the host lock. It says an empty Home is not provider readiness, and it leaves
localhost:8090 as a stated gap. Cleanup signals the whole process group,
including a child that ignores SIGTERM.

Co-authored-by: Sash <SashaMIT@users.noreply.github.com>
The smoke now runs the contract command `elastos gateway --addr
localhost:8090` and polls GET http://localhost:8090/healthz. It passes only
when the answer is HTTP 200 and the two bytes OK, the address curl reached is
a listen socket of the gateway pid, and host-process.lock names that pid, a
gateway role and the same addr. HTTP 503 is polled until the deadline; any
other status fails.

After that check it prints facts, not pass or fail: the localhost lookup
order, the addresses the gateway listens on, and what /healthz returns at
localhost, 127.0.0.1 and [::1]. `--addr localhost:8090` binds only the
first address that resolves and binds (tokio TcpListener::bind), so on a
host where localhost gives ::1 first, 127.0.0.1:8090 misses the gateway.

A smoke stopped by SIGTERM exited 0. Each signal now has its own exit
status, and cleanup signals both the group and the pid and waits until
neither is alive. An unknown host OS, a missing tool, an out-of-range port
and a deadline that is not 1 to 9999 seconds stop before the gateway starts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
…ke-1297

zip 9 for RUSTSEC-2026-0367/0368/0369 so cargo-audit passes. The base
already merges fix/zip-9-rustsec; merging the base keeps this PR's diff
against it unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
…ke-1297

Brings in the ported held-lock journal test fix (develop 5051505) so test-capsules stops flaking.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
The stub always wrote host-process.lock under $XDG_DATA_HOME, but on macOS
the smoke reads $HOME/Library/Application Support/elastos, as the real
binary does (the dirs crate ignores XDG_DATA_HOME there). So every test that
needs a matching lock failed on a Mac. The stub now picks the directory
from `uname -s`, as the smoke does, and skips the HTTPServer reverse lookup
that can be slow on macOS.

Two new tests run the macOS path on Linux with a uname shim: the lock under
Library/Application Support is accepted, and a lock under XDG_DATA_HOME is
refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
source-gate runs them on Linux only. The Intel job now runs them before it
builds, so the macOS lock path, lsof and localhost order are tested on a Mac.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K

SashaMIT commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor Author

0c8d6c72: the test stub wrote host-process.lock under XDG_DATA_HOME, but on macOS the smoke and the real binary use ~/Library/Application Support/elastos, so the lock tests failed on a Mac. The stub now follows uname -s. test_macos_lock_is_read_from_application_support and test_macos_lock_under_xdg_is_refused cover this on Linux, and both fail if the script's Darwin path is reverted.
02dcf5b1: the existing gateway-smoke-macos-intel job now runs scripts/gateway-healthz-smoke-test.py on the Mac. c3812551: the two cleanup tests get a 3 s deadline, not 1 s, so a busy host does not time out before the stub forks.
Simulated macOS run (bash 3.2 + Darwin uname): 7 failures before the fix, 26 tests OK after.


Generated by Claude Code

test_group_is_stopped_after_timeout and test_child_ignoring_term_is_killed
used a 1 second deadline. On a busy host the smoke timed out before the
stub had forked its child, so the test failed with no child pid file. It
failed 1 of 12 runs here under CPU load, and hosted Intel Macs are slower.
A 3 second deadline failed 0 of 12.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
…ddress

MAC.md still said --addr localhost:8090 binds only the first address that
localhost resolves to. Since ce5d187 (merged from the base) the gateway
listens on every loopback address the launcher contract names for
localhost. The doc now cites the contract instead of restating the old rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
…ke-1297

Brings in #394's proof of gateway lock ownership from the held flock (3672007).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
SashaMIT pushed a commit that referenced this pull request Oct 17, 2026
…ame-1297

Brings in #394's proof of gateway lock ownership from the held flock (3672007), through #395.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
SashaMIT pushed a commit that referenced this pull request Oct 17, 2026
Brings in #394's flock ownership proof (3672007) and #395's macOS smoke test fixes (3cffaad), through #397.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
SashaMIT pushed a commit that referenced this pull request Oct 17, 2026
Brings in #394's flock ownership proof (3672007) and #395's macOS smoke test fixes, through #397 and #398.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
@SashaMIT

Copy link
Copy Markdown
Contributor Author

Round 3 review: PASS (B). Waiting on the #398 decision.

…ke-1297

Brings in #394's one-step flock ownership proof, the subordinate lane on the same proof, and a held lock with an unreadable record counting as held (4bb19dc).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
SashaMIT pushed a commit that referenced this pull request Oct 17, 2026
…ame-1297

Brings in #394's one-step flock ownership proof, the subordinate lane on the same proof, and a held lock with an unreadable record counting as held (4bb19dc), through #395.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
SashaMIT pushed a commit that referenced this pull request Oct 17, 2026
Brings in #394's one-step flock ownership proof, the subordinate lane on the same proof, and a held lock with an unreadable record counting as held (4bb19dc), through #395 and #397.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K

Copy link
Copy Markdown
Contributor Author

CI red at 12fc78b: source-home-linux (ubuntu-24.04) job 117514231178, "finite installed UI journey failed". In the 4 GiB journey, finite_memory.actions holds only engine_running, with no engine_stopped. The 1 GiB and engine-absent journeys passed.
Why it is not this PR's: develop 9be009b failed the same way (run 39022710033), and #394 4bb19dc, which this PR carries, passed this job in run 39048794073. Tracked in #433, and no fix exists yet. I can't re-run (403), so it needs one manual re-run of run 39049051156.


Generated by Claude Code

@SashaMIT

Copy link
Copy Markdown
Contributor Author

Round 4 at 12fc78b: B. Genuine merge of #394. Red job is the #433 finite journey: re-run.
Test: test_default_is_the_contract_command fails when port 8090 is busy; make it hermetic.

…ke-1297

Brings in #394's statement that the host lock proves possession, not that
the holder is the gateway, with its two process tests (13cdcad).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
test_default_is_the_contract_command runs the smoke without
ELASTOS_GATEWAY_ADDR, so the smoke probes the contract URL
http://localhost:8090/healthz. When another program on the test host
listened on 8090, curl got its answer before the stub had written its
arguments, the smoke stopped early, and the test failed reading
args.json. The test now puts a curl on PATH that records its arguments
and never connects. It checks the gateway command and that the smoke
probed only http://localhost:8090/healthz. It passes with 8090 busy and
free.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
The smoke script header and the Intel Mac CI comment said the gateway
pid "owns" host-process.lock. The launcher contract says the gateway
holds the lock and that the lock proves possession, not identity. Use
the contract's word.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K

Copy link
Copy Markdown
Contributor Author

630efc6d: test_default_is_the_contract_command now uses a curl on PATH that never connects, so it no longer depends on port 8090; it failed before with python3 -m http.server 8090 running (FileNotFoundError ... args.json) and passes with 8090 busy (5/5) and free (3/3); whole file Ran 26 tests ... OK (skipped=3).
Head ac97a4aa also merges #394 13cdcad0. The red job on 12fc78b2 was the finite journey (#433), ci-installed-journeys.py:1261.


Generated by Claude Code

SashaMIT pushed a commit that referenced this pull request Oct 18, 2026
…ame-1297

Brings in, through #395, #394's statement that the host lock proves
possession, not that the holder is the gateway (13cdcad), and #395's
hermetic default-command smoke test (630efc6) and "holds" wording
(ac97a4a).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
SashaMIT pushed a commit that referenced this pull request Oct 18, 2026
Brings in, through #397 and #395, #394's statement that the host lock
proves possession, not that the holder is the gateway (13cdcad), and
#395's hermetic default-command smoke test (630efc6).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
SashaMIT pushed a commit that referenced this pull request Oct 18, 2026
Brings in #398's portable swapped-Runtime test (da63c23: the Linux case
mocks a GNU-like mktemp instead of using the host's), and, through #397
and #395, #394's statement that the host lock proves possession, not
that the holder is the gateway (13cdcad).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
SashaMIT pushed a commit that referenced this pull request Oct 18, 2026
…-root

Brings in #398's portable swapped-Runtime test (da63c23: the Linux case
mocks a GNU-like mktemp instead of using the host's), and, through #397
and #395, #394's statement that the host lock proves possession, not
that the holder is the gateway (13cdcad).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
@SashaMIT

Copy link
Copy Markdown
Contributor Author

Round 5 at ac97a4a: FAIL (C). test_default_is_the_contract_command is still timing-flaky (2 of 3 local runs fail).
Fix: remove the 3 s startup deadline and do not depend on port 8090 being free.

The smoke tests gave the stub a 3 s ELASTOS_GATEWAY_HEALTH_DEADLINE. When
python3 starts slowly (the macOS /usr/bin/python3 shim, a cold cache, a
busy host), the stub needs more than 3 s to write args.json or to bind,
the smoke stops it at the deadline, and the test fails. With each python3
start delayed by 1 to 2 s, test_default_is_the_contract_command failed 18
of 30 runs with port 8090 free and 19 of 30 with it busy
(FileNotFoundError on args.json).

Tests that end on an answer, a refusal or the stub's exit now give the
smoke its largest deadline (9999 s), so the deadline cannot end them. The
default-command test uses a stub that stays alive until the smoke has run
curl once and then exits, so the smoke always ends on "gateway exited
before GET http://localhost:8090/healthz was ready", and the test always
checks the probed URL. Its curl never connects, so port 8090 does not
matter.

The four tests that need the deadline to pass (always 503, the two
timeout cleanups) put a curl on PATH that waits until the stub listens
or has forked, so the first probe always sees that state before the
deadline is checked. The interrupt test waits for the child without a
10 s cap. The smoke script is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K
…ke-1297

Brings in #394's merge of develop (d30027e).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6Qn9RX7LDqrwiAfNC2F2K

Copy link
Copy Markdown
Contributor Author

914acb9a (test only): the cause was the 3 s smoke deadline that every test used. When python3 starts slowly, the smoke stopped the stub before it wrote args.json. With each start delayed 1-2 s: 18/30 failed (8090 free), 19/30 failed (8090 busy).
Tests now end on an event: the stub exits after the first probe, or a curl shim waits until the stub listens or forks. After the fix: 0/50 under CPU load with 8090 busy, 0/50 with it free, 0/50 with slow python3 for each. Head e50fe79a (merges #394 d30027ed).


Generated by Claude Code

@SashaMIT

Copy link
Copy Markdown
Contributor Author

Independent review (GPT) at e50fe79: PASS (A). Default-command test passed 20/20 with port 8090 busy and 10/10 with a 2 s Python start delay; restoring the old deadline and port probe fails as intended.
CI green, including the Intel Mac smoke.

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.

3 participants