Skip to content

feat(process): implement the persistent-process tier registry#867

Merged
joshuajbouw merged 7 commits into
mainfrom
feat/process-persistent-tier
Jun 6, 2026
Merged

feat(process): implement the persistent-process tier registry#867
joshuajbouw merged 7 commits into
mainfrom
feat/process-persistent-tier

Conversation

@joshuajbouw

@joshuajbouw joshuajbouw commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Linked Issue

Closes #866

Summary

Implements the persistent-process tier of astrid:[email protected] (merged contract: astrid-runtime/wit#12; design: astrid-runtime/rfcs#22). A capsule can now spawn a background child that outlives the pooled, stateless WASM instance that started it — previously an ephemeral process-handle is reaped when its instance resets on return to the dynamic pool, so the split spawn → read → stop pattern across tool invocations was impossible.

The core is a host-owned PersistentProcessRegistry, cloned into every pooled HostState exactly like the cancellation ProcessTracker, so a process-id survives instance churn. It owns the child (spawned on the daemon runtime under the same bwrap/Seatbelt sandbox as the ephemeral tier), its per-stream log rings, and its stdin pipe.

Changes

  • wit submodule → merged main (8946e98); committed wit-staging/ ships the contract on the published-crate path (zero drift; host/ byte-identical).
  • PersistentProcessRegistry (engine/wasm/host/process/persistent/, split into mod/ring/entry/ids/config + tests):
    • spawn-persistent — 256-bit host-minted CSPRNG process-id, lowercase base32 (doubles as an IPC topic suffix); registry stores only a keyed BLAKE3 hash, never the raw token. Refuses the owner-fallback principal (persist-unsupported).
    • status / status-many / list-processes (non-draining), read-logs (drain) + read-since (non-draining, cursor-addressed, byte-faithful list<u8>), signal (incl. stop/cont), bounded wait, stop (SIGTERM→grace→SIGKILL, frees the slot), release-process, write-stdin / close-stdin (via keep-stdin-open capture).
    • Security: every id-keyed call re-resolves the live (principal, capsule) vs the recorded creator; unknown / wrong-owner / wrong-capsule / reaped all collapse to no-such-process (no oracle).
    • Lifecycle: per-principal concurrent + retained-id caps; idle / max-lifetime / exit-retention TTLs (guest values clamped DOWN to host ceilings); per-capsule reaper task; kill-all on capsule unload / daemon graceful shutdown. A per-process monitor task owns the Child (kill_on_drop backstop); reaping happens outside the registry lock.
  • HostState gains persistent_processes, wired through the engine (one registry per WasmEngine, cloned into the pool + the lifecycle/hooks construction sites).
  • macOS works by default — the only weaker property is orphan-on-daemon-hard-crash (Seatbelt has no die-with-parent); a graceful shutdown / unload reaps. Documented, not gated behind persist-unsupported.

Deferred (honest)

  • attach (resource-handle materialisation — needs dual-typed resource-table dispatch; the id-keyed ops ARE its documented equivalent).
  • watch / unwatch — host-published lifecycle events raise an OPEN publish-authority question in RFC host_abi; status + bounded wait is the working polling alternative.
  • WIT (NOT YET …) items: resource-limit enforcement, cpu-ms / mem-bytes-peak, instance-local pollables.

Test Plan

Automated

  • cargo test --workspace passes — 1990 passed, 0 failed, incl. 3 new integration tests that spawn real processes through the registry (spawn/status/wait/read + owner-isolation; concurrent-cap reject + stop-reaps + slot-free; non-draining cursor read-since) and pure-logic unit tests for the log ring, cursor, and id minting.
  • No new clippy warnings — the diff is astrid-capsule + astrid-hooks, both clean; the pre-existing sys.rs:365 / astrid-workspace lints are untouched.

Manual

  • cargo build --workspace green; cargo fmt --all --check clean.

Checklist

  • Linked to an issue
  • CHANGELOG.md updated under [Unreleased]

Bumps the core/wit submodule to the astrid:[email protected] persistent-tier WIT
(astrid-runtime/wit#12) and regenerates the host bindings, so the kernel now
speaks the full contract. Implements:

- SIGSTOP / SIGCONT mapping in ProcessHandle.signal.
- The 15 new persistent Host fns as fail-secure stubs matching the WIT's
  (NOT YET IMPLEMENTED) notes: spawn-persistent -> persist-unsupported;
  every id-keyed op -> no-such-process (no registry => no id resolves, which
  also denies a cross-principal existence oracle); list-processes /
  status-many -> empty. Nothing here can leak or escape.

This is the contract-wiring increment: the surface is fixed and the SDK can
generate against it. The host-owned PersistentProcessRegistry that makes
spawn-persistent / read-logs / stop / status / list actually work (Tier 1,
which unblocks the shell capsule's background-process tools) lands next.
Workspace builds; clippy clean.
Bumps core/wit to wit@46704fd (review fixes) and updates the stop stub's
return type to exit-info; drops the now-unused KillResult import.
Re-point the wit submodule from the pre-merge feature-branch commit (46704fd) to merged origin/main (8946e98). host/ content is byte-identical between the two, so the committed wit-staging/ stays in lockstep — only the gitlink moves. This puts any release on a real, pushed main ref rather than a feature branch that gets GC'd post-merge.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces the astrid:[email protected] persistent-process tier, enabling background child processes to persist beyond the lifecycle of the stateless WASM instances that spawn them. The changes include updating the WIT contract and providing a stubbed host implementation, ensuring the API surface is available for SDKs while the underlying registry logic is developed in a follow-up.

Highlights

  • Contract Integration: Updated the wit submodule to include the astrid:[email protected] persistent-process tier contract.
  • Host Wiring: Implemented stubbed host methods in astrid-capsule to support the new persistent process lifecycle, allowing guests to link against the full API surface.
  • Signal Support: Added support for SIGSTOP and SIGCONT signals in the process handle logic.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.


A process lives beyond the pool, Persistence is the golden rule. Though stubs are all we have today, The future path is paved this way.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request wires up the host ABI for the persistent-process tier under the astrid:[email protected] package. It updates the WIT contract to define the persistent tier types and functions, maps the new Stop and Cont process signals to their corresponding OS signals, and implements fail-secure stub methods in the host state. There are no review comments provided, and the changes look clean and well-documented, so I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the astrid:[email protected] WIT contract to include the new persistent-process tier and wires the corresponding host-side API surface in astrid-capsule as an explicit stub implementation (plus live SIGSTOP/SIGCONT signal mapping), allowing guests/SDKs to compile against the full interface before the real persistent registry lands.

Changes:

  • Updated the staged WIT contract for astrid:[email protected] to include persistent-tier types/functions and new error/signal variants.
  • Added stub host implementations for the new persistent-tier methods in astrid-capsule (returning persist-unsupported / no-such-process / empty).
  • Implemented SIGSTOP/SIGCONT mapping in ProcessHandle.signal and added a changelog entry.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

File Description
crates/astrid-capsule/wit-staging/deps/astrid-process/[email protected] Expands the process WIT contract to include the persistent tier and supporting types/errors.
crates/astrid-capsule/src/engine/wasm/host/process/mod.rs Wires the new persistent-tier host functions as stubs in the WASM host implementation.
crates/astrid-capsule/src/engine/wasm/host/process/handle.rs Adds SIGSTOP/SIGCONT support to the existing signal mapping.
CHANGELOG.md Documents the new (stubbed) persistent-tier host ABI surface under Unreleased.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/astrid-capsule/src/engine/wasm/host/process/mod.rs Outdated
Comment thread crates/astrid-capsule/src/engine/wasm/host/process/mod.rs Outdated
Replace the spawn-persistent / id-keyed stubs with a real host-owned PersistentProcessRegistry, shared across a capsule's pooled instances (cloned into every HostState like ProcessTracker) so a process-id survives instance reset.

Implements: spawn-persistent (256-bit base32 id, keyed-BLAKE3-hashed, owner-fallback refused), status/status-many/list-processes, read-logs (drain) + read-since (non-draining cursor), signal/wait/stop/release-process, write-stdin/close-stdin. Per-call (principal,capsule) re-check vs creator; concurrent + retained caps; idle/lifetime/exit-retention reaper; kill-all on unload/shutdown. Linux + macOS (daemon-hard-crash orphan caveat documented). attach + watch remain deferred.
@joshuajbouw joshuajbouw changed the title feat(process): wire the merged astrid:process persistent-tier contract into the host (stubbed) feat(process): implement the persistent-process tier registry Jun 6, 2026
@joshuajbouw joshuajbouw requested a review from Copilot June 6, 2026 22:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Comment thread crates/astrid-capsule/src/engine/wasm/host/process/mod.rs Outdated
Comment thread crates/astrid-capsule/src/engine/wasm/host/process/mod.rs
Comment thread crates/astrid-capsule/src/engine/wasm/host/process/mod.rs Outdated
Comment thread crates/astrid-capsule/src/engine/wasm/host/process/persistent/entry.rs Outdated
Comment thread crates/astrid-capsule/src/engine/wasm/host/process/persistent/ring.rs Outdated
…keyed ops

Copilot review on #867: (1) spawn-persistent runs the host_process capability gate BEFORE the owner-fallback / persistence checks, so an ungranted capsule always sees capability-denied (consistent with spawn/spawn-background + the WIT Security-gated header) not persist-unsupported. (2) Every id-keyed persistent op now audits via a new audit_process_id helper logging a non-reversible 8-byte BLAKE3 prefix of the process-id (never the raw token, per the WIT) + op/principal/capsule.
Copilot review on #867 (second pass, on the registry impl):

1. os_pid==0: child.id() can be None (reaped) → killpg(0)/kill(0) would hit the daemon's OWN process group. spawn-persistent now rejects a missing/zero pid (drops the child, kill_on_drop reaps), and send_signal guards pid==0 as defense-in-depth.

2. stdin prelude: enforce the WIT 4 MiB per-spawn cap (too-large) and surface write failures (kill the orphan + fail) instead of swallowing them.

3. concurrent cap is now genuinely SHARED across tiers: spawn-background counts live persistent processes; spawn-persistent subtracts live ephemeral handles — mixing the two can no longer exceed the cap.

4. ProcessInfo.id was always empty, breaking list-processes reattach. The entry now stores the raw id and status/list return it (map still keyed by the BLAKE3 hash; audit still logs only the hash).

5. LogRing backpressure is now all-or-nothing — it never evicts (a crossing push is rejected whole), so framed streams aren't corrupted. Reader reads <= min ring cap so an over-cap chunk can't deadlock.

6. clamp_label caps by BYTES (char-boundary-safe), not chars, so non-ASCII labels can't exceed 128 bytes. Tests added for 4/5/6.
@joshuajbouw joshuajbouw merged commit 0ceaff5 into main Jun 6, 2026
13 checks passed
@joshuajbouw joshuajbouw deleted the feat/process-persistent-tier branch June 6, 2026 22:42
joshuajbouw added a commit to astrid-runtime/sdk-rust that referenced this pull request Jun 7, 2026
## Summary

Adds the ergonomic SDK surface for the **persistent-process tier** of
`astrid:[email protected]` (host side: astrid-runtime/astrid#867; contract:
astrid-runtime/wit#12), so capsule authors can spawn a background child
that **outlives the pooled, stateless instance** that started it —
unlike `process::Process`, whose kernel resource is reaped on instance
reset.

## Changes

- **`contracts` submodule → the merged `astrid:[email protected]` persistent
tier** (wit commit `1a06cf4`, the #12 squash). Scoped deliberately to
the process package: `1a06cf4` predates #11, so the `interfaces/` bundle
(`astrid-sdk/wit/astrid-contracts.wit`) is untouched and the open
hook-event-request PR #50 is unaffected (`sync-contracts-wit.sh --check`
stays green). `astrid-sys/build.rs` restages
`wit-staging/deps/astrid-process/`; the raw `wit_process::*` bindings
regenerate.
- **`astrid-sdk/src/process.rs` ergonomic layer:**
- `Command` gains the persistent-only builder knobs (`label`,
`keep_stdin_open`, `overflow`, `log_ring_bytes`, `max_lifetime`,
`idle_timeout`, `exit_retention`, `limits`) and a `spawn_persistent()`
terminal → `PersistentProcess`.
- `PersistentProcess` (keyed by an opaque `ProcessId`): `status`,
`read_logs` (drain), `read_since` (non-draining cursor, byte-faithful
`LogChunk`), `write_stdin`, `close_stdin`, `signal`, `wait` (bounded),
`stop` (consumes), `release` (consumes).
- Module fns: `attach(id)` — an id-wrapper so reattach from a later
invocation works **without** the host's deferred `attach` resource fn
(the first id-keyed call validates ownership) — plus `list` and
`status_many`.
- New types: `ProcessId`, `ProcessInfo`, `ProcessPhase`, `LogStream`,
`LogCursor`, `LogChunk`, `OverflowPolicy`, `ResourceLimits`. `Signal`
gains `Stop` / `Cont`.
- **`Command::into_wit` updated** for the new `SpawnRequest` fields (a
required fix — the WIT bump added 8 fields).

## Not exposed (host-deferred)

`watch` / `unwatch` (open publish-authority RFC question — poll via
`status` + bounded `wait`) and resource-limit enforcement (`limits` is
plumbed through but the host does not enforce it yet).

## Test Plan

- [x] `cargo build --workspace` + `cargo test --workspace` green
- [x] No new clippy warnings — my diff is `astrid-sdk` (clean); the 2
`astrid-sdk-macros` backtick warnings are pre-existing and untouched
- [x] `cargo fmt --all --check` clean
- [x] `scripts/sync-contracts-wit.sh --check` passes (interfaces bundle
untouched — #50 unaffected)
joshuajbouw added a commit to astrid-runtime/sdk-js that referenced this pull request Jun 7, 2026
## Summary

Mirrors the Rust SDK and the host `astrid:[email protected]`
**persistent-process tier** (host: astrid-runtime/astrid#867; Rust SDK:
astrid-runtime/sdk-rust#53; contract: astrid-runtime/wit#12), so JS/TS
capsule authors can spawn a background child that **outlives the pooled,
stateless instance** that started it — unlike
`process.BackgroundProcessHandle`, whose kernel resource is reaped on
instance reset.

## Changes

- **`contracts` submodule → the merged `astrid:[email protected]` persistent
tier** (wit commit `1a06cf4`, the #12 squash). Deliberately the
**#12-only** commit (predates #11), so the `astrid:contracts` events
bundle (`astrid-contracts.wit` / generated `contracts.ts`) is untouched
(`sync-contracts-wit.sh --check` stays green) and unrelated open SDK PRs
are unaffected. On `main`, `astrid-build` reads the host WIT **live from
`contracts/host/`** (`CANONICAL_WIT_DIR`), so the bump is all
ComponentizeJS needs.
- **`wit-imports.d.ts`** (hand-written host ABI types): persistent types
+ free-function declarations on `astrid:process/[email protected]` —
`spawnPersistent`, `attach`, `listProcesses`, `status`, `statusMany`,
`readLogs`, `readSince`, `writeStdin`, `closeStdin`, `signal`, `wait`,
`stop`, `releaseProcess`, `watch`, `unwatch`; `ProcessInfo`,
`ProcessPhase`, `LogStream`, `LogCursor`, `LogChunk`, `OverflowPolicy`,
`ResourceLimits`; `ErrorCode` gains `no-such-process` / `registry-full`
/ `persist-unsupported`; `ProcessSignal` gains `stop` / `cont`;
`SpawnRequest` gains the 8 persistent fields.
- **`process.ts`** ergonomic layer: `spawnPersistent(cmd, args,
options)` + the persistent `SpawnPersistentOptions` knobs;
`PersistentProcess` class (`status` / `readLogs` (drain) / `readSince`
(non-draining cursor → byte-faithful `LogChunkResult`;
`logCursorStart()`) / `writeStdin` / `closeStdin` / `signal` / `wait`
(bounded) / `stop` (consumes — SIGTERM→grace→SIGKILL) / `release`);
module fns `attach(id)` (id-wrapper reattach — works without the host's
deferred `attach` resource fn), `listProcesses`, `statusMany`; ergonomic
types. `buildSpawnRequest` updated for the new `SpawnRequest` fields
(required).
- **`index.ts`**: top-level re-exports for the new public types.

## Not exposed (host-deferred)

`watch` / `unwatch` (open publish-authority RFC question — poll via
`status` + bounded `wait`) and resource-limit enforcement (`limits` is
plumbed through but the host doesn't enforce it yet).

## Test Plan

- [x] `npm run build` (tsc) green across the workspace
- [x] **End-to-end:** the `examples/test-capsule` **componentizes**
against the persistent WIT — ComponentizeJS produced a 12.96 MB WASM
with **169 host imports**, proving the new host functions wire through
the JS build path
- [x] `scripts/sync-contracts-wit.sh --check` passes (events bundle
untouched)
- [x] Git diff scoped to 5 files (contracts pointer + 3 SDK sources +
CHANGELOG); no `contracts.ts` drift
joshuajbouw added a commit that referenced this pull request Jun 8, 2026
…e-stdin WIT

The id-keyed persistent write-stdin/close-stdin landed implemented in #867 but
were never test-locked and the WIT still tagged them (NOT YET IMPLEMENTED).

- Adds a registry test proving the acceptance: write-stdin delivers bytes to a
  persistent child, a second by-id write (needing only the registry + id, i.e.
  what a post-reset instance has) still reaches the same child, close-stdin
  yields a clean EOF exit, over-cap -> too-large, wrong-owner -> no-such-process,
  post-close -> closed.
- Bumps the wit submodule to drop the stale (NOT YET IMPLEMENTED) tags on the
  id-keyed forms and correct the two persistent-tier banners (registry has
  landed). Restages wit-staging. The ProcessHandle (ephemeral) form, attach,
  and watch/unwatch stay deferred and keep their tags.
joshuajbouw added a commit that referenced this pull request Jun 8, 2026
…e-stdin WIT (#871)

## Linked Issue

Closes #870

## Summary

The id-keyed persistent `write-stdin` / `close-stdin` were implemented
in #867 (the registry retains the child's stdin pipe host-side, survives
pooled-instance reset, 1 MiB-capped, backpressured, ownership-checked,
audited) but had **no test**, and the WIT still tagged them `(NOT YET
IMPLEMENTED)`. This adds the acceptance test and un-stubs the
now-accurate WIT docs. Doc-only on the contract — no signature change.

## Changes

- **Test** (`registry_tests.rs`): write-stdin delivers bytes to a
persistent child; a second by-id write (needing only registry + id —
exactly what a post-reset instance holds) still reaches the same child;
`close-stdin` → clean EOF exit; over-cap → `too-large`; wrong-owner →
`no-such-process`; post-close → `closed`.
- **WIT** (submodule bump → astrid-runtime/wit#14): drops the stale
`(NOT YET IMPLEMENTED)` tags on the id-keyed forms and corrects the two
`PERSISTENT TIER` "stubbed until the registry lands" banners. Restages
`wit-staging`. Signatures unchanged.
- The ephemeral `ProcessHandle` form, `attach`, and `watch` / `unwatch`
stay genuinely deferred and tagged.
- CHANGELOG updated under `[Unreleased]`.

## Test Plan

### Automated

- [x] `cargo test --workspace` passes
- [x] No new clippy warnings

Specifically: `cargo test -p astrid-capsule registry_tests` (the new
acceptance test + existing registry tests pass); build green (WIT parses
via bindgen).

## Checklist

- [x] Linked to an issue
- [x] CHANGELOG.md updated under `[Unreleased]`
joshuajbouw added a commit to astrid-runtime/wit that referenced this pull request Jun 8, 2026
)

The persistent-tier registry landed in astrid-runtime/astrid#867 — the
id-keyed write-stdin/close-stdin are implemented (pipe retained
host-side, survives pooled-instance reset, 1 MiB cap, backpressure,
ownership-checked, audited). Drops the stale (NOT YET IMPLEMENTED) tags
on those two funcs and corrects the two PERSISTENT TIER banners that
claimed the whole tier was stubbed until the registry lands. Doc-only:
signatures unchanged, no wire/binding impact. The ProcessHandle
(ephemeral) write-stdin/close-stdin, attach, and watch/unwatch remain
genuinely deferred and keep their notes.
@joshuajbouw joshuajbouw mentioned this pull request Jun 10, 2026
joshuajbouw added a commit that referenced this pull request Jun 10, 2026
## Linked Issue

Closes #853

## Summary

`chore: release` — bumps all workspace crates **0.7.0 → 0.8.0** and
rolls `CHANGELOG [Unreleased]` into `[0.8.0] - 2026-06-10`. Consolidates
the ~50 PRs landed since v0.7.0:

- **HTTP admin gateway** (#756 + follow-ups) — `astrid-gateway`:
principals/caps/quotas/groups/invites/env over HTTP, audit SSE +
historical queries, agent-prompt SSE, OpenAPI emission, bus-direct admin
path (285× throughput), rustls TLS, CORS, metrics, invite + keypair CLI
verbs.
- **Runtime concurrency overhaul** (#813/#816/#819/#820) — routed
per-(capsule, topic, principal) IPC with DRR fairness, async Wasmtime,
dynamic instance pools, split blocking/IO semaphores, per-principal fuel
+ memory ledgers with enforcement and usage reporting.
- **Host process + introspection surface** — `astrid:process` persistent
tier (#866/#867/#871/#873), capability introspection (#868/#869),
`astrid mcp serve` (#879/#880), `astrid-emit` (#814/#842).
- **Security** — macOS 15+ sandbox no longer silently disabled
(#855/#857), audit-feed principal scoping (#850/#851), failed-redeem
audit rows (#846), `self:agent:list` roster leak (#848), pair-device
redeem rate-limit (#844), bearer revocation + wire format v2 (#772).

Breaking: `Capsule.toml` `[publish]`/`[subscribe]`-only IPC surface
(#858/#864/#865, `[[interceptor]]` / `ipc_*` arrays / `[[topic]]`
removed), bearer v2, MSRV 1.95, `astrid-openclaw` removed (#833).

## Changes

- `[workspace.package].version` `0.7.0` → `0.8.0` + the 23 in-workspace
path-dependency pins (now including `astrid-emit`; `axum`/`axum-server`
stay on their external 0.7).
- CHANGELOG: `[Unreleased]` → `[0.8.0] - 2026-06-10` with a release
**synopsis** (extracted into the GitHub release body by release.yml on
tag). Keeps the earlier roll's curation (canonical section order,
bullets verbatim) and merges the 13 entries added to `[Unreleased]` by
the 12 PRs that landed after the branch was first cut (#851#885) —
verified both directions that no bullet was lost.

Branch history note: rebuilt on current `main` (was `CONFLICTING` and 12
commits behind); previous tip was `54c7294`.

## Release steps (maintainer)

1. Merge this PR.
2. Tag `v0.8.0` on the merge commit → release.yml creates the GitHub
release from the CHANGELOG block.
3. Publish/distribute the new `astrid` binaries as usual.

## Test Plan

Release PR — no code changes. `cargo check --workspace` passes on the
rebuilt branch; full test/clippy/MSRV matrix runs in CI. The changelog
merge was verified bullet-by-bullet in both directions: every
`[Unreleased]` bullet on `main` appears in the rolled `[0.8.0]` section,
and every bullet from the earlier curated roll is preserved verbatim.
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.

feat(process): implement the persistent-process tier (registry + host ops)

2 participants