Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions .ai/skills/hack-repo-verify/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,24 @@ For native setup use root `mise.toml`, the Bun pin in `package.json`, and
`bun install --frozen-lockfile`. Native gates are `bun run typecheck`, `bun run check`,
`bun run test`. Focused CLI checks: `bun run --cwd packages/cli typecheck` and
`bun run --cwd packages/cli check`; lint changed tests/scripts explicitly with
`bunx ultracite check <paths>`. Rust default gates are `bun run check:local` and
`bun run test:local`. Add `--all-features` to equivalent Cargo commands for feature
`bunx ultracite check <paths>`. These entry points first run
`bun run check:bun-version`, which fails when the running Bun differs from the
`packageManager` pin that CI installs. A Bun ahead of mise's shims on `PATH`
(for example mise's `latest` install) bypasses the checkout's `mise.toml`; use
`mise x bun@<pin> -- bun run <script>` instead. `HACK_ALLOW_BUN_VERSION_MISMATCH=1`
proceeds with a warning for a deliberate experiment; such a result is not CI evidence.
Raw `bun test <paths>` does not run the guard.

CI's "Config compiler" job also runs compiled-bundle CLI checks
(`scripts/check-config-compiler-cli.ts`, `scripts/check-native-*-plan-cli.ts`,
`scripts/check-native-config-import-cli.ts`) that `bun run test` does not. For
compiler, native planning or config-import changes, run them locally after
`bun run build` and `bun run build:config-compiler` with
`bun run check:native-plan-cli`. `tests/native-plan-cli-wiring.test.ts` fails when a
new `scripts/check-native-*-plan-cli.ts` is missing from that command or from CI.
CI also lints those scripts and runs their transport tests; lint changed ones explicitly.

Rust default gates are `bun run check:local` and `bun run test:local`. Add `--all-features` to equivalent Cargo commands for feature
changes; the toolchain Rust tasks already enable all features. Keep default coverage.

Before a full CLI suite, explicitly prepare the ignored compiler with
Expand Down
4 changes: 2 additions & 2 deletions .hack/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@
{
"path": "package.json",
"pointer": "/scripts/check",
"sha256": "ae7e24ee743b2aa230c6a492da63a0e7b6a0db925e691a24a7a8f1c97d3ee7fb"
"sha256": "c8dad6241a07d0de512741c0bc88b302f627b822b442de7d640490eaf239ce1f"
},
{
"path": "package.json",
"pointer": "/scripts/typecheck",
"sha256": "4209d96797d84dcd31f559acfde1395b9969d025ef6fc11f4684567a3009ef6f"
"sha256": "dce86c009756c167434b90e06ffa8ba3dbcfc01047abbae2a2803a4d5ecea01a"
}
],
"review": "HACK-1157"
Expand Down
8 changes: 7 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,13 @@ or unresolved concern. Do not skip a required gate or weaken an assertion to get
unrelated installed version. Use `bun index.ts` for a source invocation.
- CLI typecheck/lint: `bun run --cwd packages/cli typecheck` and
`bun run --cwd packages/cli check`. Lint changed scripts/tests explicitly as well.
- Full gates: `bun run typecheck`, `bun run check`, `bun run test`.
- Full gates: `bun run typecheck`, `bun run check`, `bun run test`. They fail when
the running Bun differs from the `packageManager` pin CI uses; run the pinned Bun
(`mise x bun@<pin> -- bun run <script>`), or set
`HACK_ALLOW_BUN_VERSION_MISMATCH=1` only for a deliberate mismatch.
- Config compiler, native plan or config-import changes: after `bun run build` and
`bun run build:config-compiler`, run `bun run check:native-plan-cli`. It runs the
compiled-bundle CLI checks from CI's macOS "Config compiler" job.
- CLI interface changes: regenerate `docs/reference/cli.md` with
`bun run docs:cli-reference`.
- Consumer agent guidance changes: regenerate the affected repository examples and plugin
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@
"turbo:typecheck": "bunx turbo run typecheck",
"turbo:test": "bun run test:preflight && bunx --no-install turbo run test",
"turbo:check": "bunx turbo run check",
"check": "bun run privacy:check && bun run turbo:check",
"check": "bun run check:bun-version && bun run privacy:check && bun run turbo:check",
"check:bun-version": "bun scripts/check-bun-version.ts",
"check:native-plan-cli": "bun run check:bun-version && bun scripts/check-native-plan-clis.ts",
"prepare": "husky",
"release:prepare": "bunx semantic-release --no-ci",
"typecheck": "bun run turbo:typecheck",
"typecheck": "bun run check:bun-version && bun run turbo:typecheck",
"uninstall:local": "bun run --cwd packages/cli uninstall:local",
"test": "bun run turbo:test",
"test": "bun run check:bun-version && bun run turbo:test",
"test:preflight": "bun --no-env-file scripts/check-test-config-compiler.ts",
"test:models": "bun run scripts/check-tla-models.ts",
"test:e2e:local": "bun tests/e2e/run.ts",
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
"macos:release": "cd ../.. && ./scripts/build-macos-release.sh",
"macos:ghostty:setup": "cd ../.. && bun run scripts/macos-ghostty-setup.ts",
"macos:ghostty:bundle": "cd ../.. && bun run scripts/macos-ghostty-bundle.ts",
"typecheck": "bunx tsc -p tsconfig.json --noEmit",
"test": "cd ../.. && bun run test:preflight && bun test",
"check": "cd ../.. && bunx ultracite check src packages/cli/index.ts index.ts scripts/build-release.ts scripts/build-node-runtime-image.ts scripts/install-cli.ts scripts/install-status.ts scripts/uninstall-cli.ts scripts/macos-ghostty-bundle.ts scripts/macos-ghostty-setup.ts",
"typecheck": "bun ../../scripts/check-bun-version.ts && bunx tsc -p tsconfig.json --noEmit",
"test": "cd ../.. && bun run check:bun-version && bun run test:preflight && bun test",
"check": "cd ../.. && bun run check:bun-version && bunx ultracite check src packages/cli/index.ts index.ts scripts/build-release.ts scripts/build-node-runtime-image.ts scripts/install-cli.ts scripts/install-status.ts scripts/uninstall-cli.ts scripts/macos-ghostty-bundle.ts scripts/macos-ghostty-setup.ts",
"lint": "bun run check"
}
}
27 changes: 24 additions & 3 deletions packages/runtime-core/guest/stream-relay.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,22 @@ static int stop_owned(long pid, long start) {
return 78;
#endif
}
/*
* Publisher readiness contract: after the frontend and optional control socket
* are bound, the publisher writes exactly one readiness line to stdout and keeps
* serving. A Unix frontend or an explicit TCP port (1-65535) writes "ready\n",
* unchanged for existing callers. `--publish 0` (exactly "0") asks the kernel for
* an ephemeral loopback port while the listener is bound, closing the window in
* which a caller-probed free port can be taken by another process; that form
* writes "ready <port>\n" with the bound decimal port. Port 0 is accepted only by
* `--publish`; the relay and `--publish-unix` forms keep rejecting it with 64.
* Exit 73 still means the frontend could not be bound (or a bound Unix frontend
* path could not be verified), and no readiness line is written for any refused
* startup.
*/
int main(int argc, char **argv) {
char *publish_args[8];
int ephemeral_port = 0;
struct sockaddr_un control = {0};
struct stat control_owned, receipt_owned, frontend_receipt_owned;
char receipt_path[PATH_MAX] = {0};
Expand Down Expand Up @@ -263,7 +277,9 @@ int main(int argc, char **argv) {
}
/* Both publishers share upstream parsing; the Unix frontend has no TCP port. */
publish_args[0] = argv[0]; publish_args[1] = argv[3];
publish_args[2] = "127.0.0.1"; publish_args[3] = publish_unix ? "1" : argv[2];
ephemeral_port = !publish_unix && !strcmp(argv[2], "0");
publish_args[2] = "127.0.0.1";
publish_args[3] = publish_unix || ephemeral_port ? "1" : argv[2];
publish_args[4] = argv[5]; publish_args[5] = "--reservation";
publish_args[6] = argv[4]; publish_args[7] = NULL;
argv = publish_args; argc = 7; publish_mode = 1;
Expand Down Expand Up @@ -297,7 +313,7 @@ int main(int argc, char **argv) {
}
if (argc != option) return 64;
target.sin_family = AF_INET;
target.sin_port = htons((uint16_t)port);
target.sin_port = ephemeral_port ? 0 : htons((uint16_t)port);
local.sun_family = AF_UNIX;
memcpy(local.sun_path, argv[1], strlen(argv[1]) + 1);
if (publish_mode) { upstream = local; if (private_upstream(&current)) return 78; }
Expand Down Expand Up @@ -338,7 +354,12 @@ int main(int argc, char **argv) {
receipt_path, &receipt_owned, &receipt_bound)) failed = 1;
}
}
if (!failed) { puts("ready"); fflush(stdout); }
struct sockaddr_in bound = {0};
socklen_t bound_size = sizeof(bound);
if (!failed && ephemeral_port && (getsockname(listener, (struct sockaddr *)&bound, &bound_size) ||
bound_size != sizeof(bound) || bound.sin_family != AF_INET || !bound.sin_port)) failed = 1;
if (!failed && ephemeral_port) { printf("ready %u\n", (unsigned)ntohs(bound.sin_port)); fflush(stdout); }
else if (!failed) { puts("ready"); fflush(stdout); }
while (!stopping && !failed) {
struct pollfd descriptors[4 + 2 * CONNECTIONS];
descriptors[3 + 2 * CONNECTIONS] = (struct pollfd){control_fd, POLLIN, 0};
Expand Down
Loading
Loading