Skip to content

chore: merge-train b19 integration check (do not merge) - #361

Closed
roodboi wants to merge 20 commits into
nextfrom
train/b19
Closed

roodboi wants to merge 20 commits into
nextfrom
train/b19

Conversation

@roodboi

@roodboi roodboi commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Integration check only — do not merge this PR. CI runs here on the combined result of merge train b19 before each PR is squashed into next individually.

train/b19 = next b431f0e plus these PR heads, merged in order:
#355 6530b26 (G4, HACK-1272), #352 fd345e7 (G7, HACK-1275), #341 eee8fdf (F13), #342 64e9228 (F15), #346 8395b34 (F17).

Each PR passed its independent verifier and its own CI. Local checks on the combined branch: typecheck clean, check 0 errors, 125 source-check tests pass (Bun 1.4.2).

When this is green, the PRs are squashed in that order with --match-head-commit, and next's final tree is checked against this branch's tree (f77392b4). Then this PR is closed.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

roodboi and others added 20 commits October 19, 2026 11:50
…ompose

HACK-1134 (unit F13), HACK-1155 (P11).

Add the docker-tier `mcp-logs-compose` scenario. It drives `hack mcp serve`
over stdio against a real Compose project and checks the logs contract:
complete, time cutoff (quiet and live), event cutoff, byte cutoff with a
UTF-8-safe partial result, closed backend_error with an unreachable engine,
a tail across a container restart, and no replay after reconnect. On the same
stack it checks that `hack run <svc> -- false` / `exit 7` and the MCP
`hack.project.run` envelope report the child's exit status.

Add tests/run-child-exit-status.test.ts: the source CLI against a recording
docker stub proves the exit status, argv after `--`, the pipe-filter negative
control and the MCP envelope without a Docker engine.

Update the HACK-P11 pattern card to cite the agent-surface-freeze negative
control (#296) and narrow the missing contract; regenerate the plugin bundle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Extend the portable bootstrap fixture (#146/#147) with a hosted
docker-e2e scenario, `portable-bootstrap-negatives`, for HACK-1143. On
the slim path it drives `hack up --detach app` through eleven ordered
stages against a locked-v1 dependency cache with a frozen installer and
an app-scoped encrypted synthetic token:

- missing key, wrong key and an overlay sealed under another key refuse
  before any owned container, network or volume exists;
- two identical bootstraps keep the same consumer, cache and index,
  initialize once and leave no worktree diff;
- a wrong key, a stale pinned image, a lockfile that no longer matches
  its manifest and a corrupted ready marker each refuse without touching
  the running consumer, pulling, rewriting the lockfile or reinstalling;
- a changed lockfile and a new cache generation select new caches and
  keep the previous ones.

Each stage records a value-free receipt (duration, output bytes, tracked
bytes, mounted-cache bytes, cache-volume count, consumer transition).
Pure stage expectations and receipt validation live in
tests/e2e/portable-bootstrap-controls.ts with unit tests. A local test
runs the source CLI on the same fixture against a recording Docker stub
to show the env refusals precede any Compose mutation.

WU12 storage admission, retention and archives remain out of scope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nspector

Add a provisional target/result decision record and a read-only target
inspector with CLI and MCP parity (HACK-1144, WU31).

- `hack project target [--json]` resolves the exact project, checkout,
  runtime instance, optional service, env overlay selection and a Hack
  config generation from local files only. It performs no registry write,
  engine call or Git mutation, and reports runtime as not probed.
- `hack.project.target` (read-only MCP tool) spawns the same command and
  passes selection through unresolved, so every resolution refusal is the
  CLI's. Its data is the CLI envelope re-validated against the contract.
- Refusals are a closed, value-free catalogue (reason, stage, retry) that
  reuses existing error codes. `--expect-generation` refuses stale config;
  a config change during the read is refused instead of snapshotted.
- Extract the Compose project name resolver from commands/project.ts so
  the inspector and commands share one implementation.
- Paired CLI/MCP fixtures: two projects, a linked-worktree branch and an
  explicit instance, conflicting selectors, stale generation, ambiguous
  equal names, a moved checkout, detached worktree and no-write checks.

Names, fields and reasons are provisional pending compatibility review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n gaps

The read-only target inspector now refuses a Compose file that is not YAML,
whose top level is not a mapping, or whose services key is not a mapping, as
compose_parse_failed, instead of reporting a target with no services.

Paired CLI/MCP fixtures now cover env selection (project default, explicit
overlay, base), explicit instance slugging (Feature/X -> <base>--feature-x),
two registrations owning one checkout, config_parse_failed,
compose_parse_failed and generation_input_too_large. A stubbed CLI proves the
MCP tool re-validates the envelope, and the validator's code/message
consistency check has direct tests. Restores the buildEnvExplainArgs JSDoc.

Refs HACK-1144

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first hosted run replayed 50 lines, which included the older boot
marker, so only 4 of the 5 counted log events were ticks. Replay 3 ticks
and let 2 live ones reach the bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docker ps -q prints 12-character IDs, so the exact-ID check refused the
ticker container before the restart step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hack-next (the channel manager) and the bundled hack-v5 entrypoint exported
HACK_RUNTIME_BACKEND=native unconditionally, and hack-next also forced the
version's private HACK_HOME. Testers could not run the supported Compose
backend through the channel; the M3 HACK-1124 rerun had to call the bundled
hack-cli directly with a private HACK_HOME, which also hid the global
Caddy/CoreDNS services and local CA.

Unset or empty HACK_RUNTIME_BACKEND still selects native with the private
homes. An explicit HACK_RUNTIME_BACKEND=compose now runs the verified bundle's
hack-cli on Compose with the caller's own HACK_HOME and
HACK_GLOBAL_CONFIG_PATH, and removes native selectors. Any other value refuses
before verification or spawn. The manager runs hack-cli directly for Compose
because retained bundles' hack-v5 always selects native.

Both launchers set HACK_CANDIDATE_ENTRYPOINT, and `update` refuses when it is
set, so a Compose launch keeps the candidate self-update refusal that the
native backend marker used to provide.

The released next.3-next.5 manager (e2e2bcba) is added as a reviewed
predecessor with its fixture, so existing channels get backend selection
through upgrade-manager.

Refs HACK-1275

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new read-only target inspector accepts --env and --service, so the env
matrix source check requires a row for it. It reports only the overlay
selection and never reads env files or values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A native consumer that refuses before reserving its runtime journal (for
example native_graph_admission for a repository@sha256 image, the M3 next.5
repro) leaves no receipt, so Removed retirement could never succeed and the
start intent stayed pending with no supported recovery.

graph native inspect now refuses the distinct native_graph_unreserved on macOS
only when the run's journal directory is exactly absent under private state
directories and no foreground owner is published. Startup retires the exact
start intent and source for that refusal after its consumer settled, reporting
outcome `unreserved` with the original native code. `down --recover` retires a
pending start the same way under fresh startup admission. Every other
inspection result keeps all evidence; receipt and ownership checks are
unchanged.

Refs HACK-1272

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…state

The hosted macOS test job printed CoreDNS/Caddy reachability warnings on
hack run stdout, which the exact stdout assertion rejected. Turn internal
DNS/TLS off in the fixture so no probe runs, and call /bin/bash directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A filesystem fault while reading target inputs (a mode-000 or directory
Compose file) escaped as E_UNEXPECTED with the raw OS message and absolute
path. Map errno errors to the closed input_permission_denied and
input_unreadable refusals, and let the adapter validator pass a detail-less
error only for parser E_USAGE refusals.

Strengthen the no-registry-write proof by comparing against the registry
bytes written in beforeAll, and cover the validator's authority and
runtime.observed checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve plugins/hack/skills/hack-cli/references/patterns.md by
regenerating it (bun run generate:agent-plugins) from the merged
src/agents/pattern-catalogue.ts, which carries both this branch's
HACK-P11 wording and the pattern changes from #336.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve tests/e2e/run.ts and tests/e2e/README.md by keeping both sides:
the portable-bootstrap-negatives scenario from this branch and the
P01/P02/P07 pattern scenarios merged into next in #336.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve a comment-only conflict in scripts/install-prerelease.py above
MANAGER_PREDECESSORS by keeping next's wording (same meaning, names the
fixture). The allowlist and the new BACKENDS constant merge unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@roodboi

roodboi commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Integration check done: all 5 PRs were squashed into next in order. next 8c79000 has the same tree as train/b19 (f77392b4). Closing; this PR was never meant to be merged.

@roodboi roodboi closed this Oct 20, 2026
@roodboi
roodboi deleted the train/b19 branch October 20, 2026 17:59
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.

1 participant