Skip to content
This repository was archived by the owner on Aug 5, 2026. It is now read-only.

v0.0.31 β€” front-half delegation + pre-release audit

Choose a tag to compare

@GrokBuildMJW GrokBuildMJW released this 25 Jul 11:20

Added

  • Installer efficiency and Ink dependency hygiene (#1832): unchanged dependency payloads are reusable, the client replaces the deprecated license-checker chain with licensee, the reviewed install-script allowlist covers esbuild and optional macOS fsevents for flows that permit lifecycle scripts, and the high-severity audit finding is resolved.

  • Push-visible front-half review lifecycle (#1836): background design/plan review and convergence progress is now visible live in the Ink client β€” review-job launches, outcomes, and converge rounds surface as they happen (via the guarded GET /events feed) instead of only at the end of a turn.

  • Phase-aware automation (#1827): /auto now drives planning only up to the current approved plan, saves a boundary marker, and hard-exits with an operator notice to re-run /auto for execution; a re-plan creates a fresh boundary, and the staging/launch gate refuses an armed, un-exited boundary.

  • The planning-to-execution hard-stop applies when design/decomposition review is enabled (the default); with review off, no approved-plan boundary forms and /auto runs end-to-end.

  • Watcher-driven front-half convergence (#1821-c/d): /design and /plan now run their review rounds as board-visible background jobs and return PENDING while the watcher resumes reviewer, meta-reviewer, and reviser work independently for every design variant. Retries and restarts are safe (no duplicated rounds or lost feedback), and design_review.async_converge=false keeps the synchronous fallback.

  • Durable front-half convergence state (#1821-a): design and decomposition review loops now persist their resumable round, cost, verdict, and artifact history under .work/converge/ so review work survives restarts.

  • Decomposition confirmation: /approve plan [--anyway] confirms a review-clean current R-B result, reports disabled review as stageable, and re-invalidates stale design/unit bindings without adding a manual staging gate or overriding HARD findings.

  • Escalated front-half review: /escalate review gives a HARD-blocked design or decomposition a fresh, default-four-round strong-coder convergence run without weakening approval or staging gates.

  • Engine-owned lifecycle finding categories, fail-closed HARD/SOFT classification, deterministic artifact HARD checks, and idempotent accepted-review notes on design proposals and decomposition epics.

  • Front-half lifecycle convergence: /design and /plan now review, strongly revise, and re-review drafts before returning, with model-distinct reviewers, engine-owned persistence, bounded TERMINAL findings, and loud DEGRADED failures.

  • Per-invocation lifecycle cost envelope: /design and /plan now estimate configured coder spend across review, meta-review, and revision calls against the default-$100 design_review.cost_envelope_usd backstop.

  • Model-distinct lifecycle meta-review: R-A and R-B APPROVE verdicts now require a different-model reviewer-of-review, with authoritative blindspot findings and loud fail-closed meta unavailability.

  • Guided approved-design decomposition (#1794): /plan triggers the one-epic-plus-all-units turn, fail-closed until scope+design are approved.

  • Durable turn/action observability (#1790): every tool dispatch appends a redacted JSONL record to turns.jsonl; new /turns and /session HTTP readers expose it.

  • Panel-led approvable designs (#1779): design_review.mode can make the MPR decision panel an automatic pre-/design architecture/language gate.

  • Front-half armed continuation (#1777, #1827): armed /auto drives planning autonomously to the approved plan, hard-exits there, and drains implementation only after the operator re-runs /auto.

  • Per-project live config overlays (#1778): /config set values apply immediately and persist as a project-scoped overlay surviving /switch and restart.

  • Durable direct-continuation forensics (#1745): silent continuation-tick exits, deferrals, and authoring-turn outcomes now write structured, deduplicated audit records.

  • Durable run observability (#1750, #1781): headless server retains a sanitized, size-rotated console log and archives bounded coder logs per run.

  • ACE learning-loop quality (#1748, #1751): near-duplicate lessons fold honestly by identifier/polarity, and retrieval keeps a reserved slot for proven lessons.

  • Engine-derived handover run records (#1752): handovers get an idempotent ## Run record with runtime facts and a precision-first tool-availability evidence gate.

  • Active-initiative control-plane write jail (#1742 trust surface, #1743): a fail-closed guard refuses model file-tool mutation of the active initiative's control-plane directories.

  • Durable epic completion report and real poll transport (#1749, #1754; Slice 2): epic auto-close assembles an atomic, engine-stamped completion report with a durable /health pointer.

  • Retroactive P2 notice activation (#1749, #1758, #1753): design-review-unavailable and code-review-skip notices now reach the real /health poll transport, best-effort.

  • Engine-stamped epic reconciliation records (#1754, #1749; Slice 1): epic auto-close writes a bounded, atomic reconciliation record of unreferenced required scope ids.

  • Handover internal-consistency gate (#1744): staging refuses a handover whose file is both forbidden-to-modify and required-to-modify by the same task.

  • Default-on, premise-free automatic code review (#1753, #1648): code_review.mode now defaults to simple, running one bounded reviewer pass per advanced unit.

  • Design and decomposition review stages (#1758, slices 1–3): adds default-on, fail-closed R-A/R-B lifecycle review with engine-stamped, per-target evidence artifacts.

  • Design/decomposition review final remediation (#1758): closes gate gaps across create/claim/next-task launch seams and binds R-B approval to the unit-content hash.

  • Product-scope foundations (#1755): record_scope//approve scope add a validated, versioned scope.md artifact gating epics on approved, closed scope.

  • Configurable automatic code-review stage in the dev-loop (#1614): an optional per-unit reviewer gate (code_review.mode) blocks non-approved units until they pass or exhaust rounds.

Changed

  • Board-visible front-half coder work (#1821-b): lifecycle reviewers, model-distinct meta-reviewers,
    and strong-coder revisers now run as detached review-job tasks through the shared handover/feedback
    machinery while the convergence loop still waits synchronously. Review jobs remain board-visible but
    are excluded from implementation-unit selection, continuation, and reconciliation; every synchronous
    dispatch terminates even when its feedback is blocked or times out.
  • UTF-8 external-coder stdio (#1822): the synchronous CLI runner now decodes coder stdout and stderr
    explicitly as UTF-8 with replacement for malformed bytes, independent of the host platform locale.
  • Canonical planning command (#1810): /plan is now the advertised decomposition verb; operator guidance names exact scope, design, planning, automation, and handover commands.
  • Design/decomposition convergence now stops when no HARD findings remain; SOFT findings are surfaced without revision, capped HARD findings are blocked, and /approve design --anyway cannot override them.
  • Bounded front-half spend: reaching the lifecycle USD envelope after a reviewed round stops with the last residual findings as TERMINAL; exhaustion before any verdict is loud DEGRADED, and results plus durable evidence expose estimated spend and the envelope.
  • Strong-coder front-half authoring: qwen remains the initial design/decomposition drafter, but an unscored MPR design is re-authored once and all HARD review findings are revised by an architecture-tier coder; qwen never reviews or revises.
  • Canonical project command (#1800): /initiative is retired from the visible surface, kept only as a silent alias for /project.

Removed

  • Obsolete weak front-half revise stage: full automation now waits at /approve design after internal strong-coder convergence instead of enqueueing a second qwen revision; /plan_units remains a silent back-compat alias.

Fixed

  • Reviser stream-output normalization (#1852): design/plan revisions produced by streaming coders
    (Kimi message streams, Claude stream-json) are now correctly extracted into the saved artifact instead of
    occasionally persisting empty or transcript-polluted output. Stream-shaped output with no extractable answer
    logs a warning and falls back to the cleaned raw response instead of a silent empty artifact.

  • Durable, fail-closed front-half convergence (#1840): asynchronous design/decomposition reviews now
    survive restarts β€” interrupted review work resumes from its last consistent checkpoint or restarts cleanly
    rather than re-running the whole loop (a narrow crash window may repay at most one already-finished review)
    and never promotes unreviewed work. Unreadable or inconsistent review state ends in a
    loud DEGRADED refusal rather than silently proceeding.

  • Public export and release-prep correctness: public docs now use repository-root paths and match the
    server's guarded route surface; export rewriting also handles top-level paths without a trailing slash
    without collapsing historical move descriptions. The README's deterministic current-version marker is
    restored so the README, docs/status.md, and pyproject.toml version stamps stay mutually consistent
    across a release cut.

  • Workspace-scoped project listing (#1838): /project list now shows only the projects in your current
    workspace instead of every project ever registered; /project list --all still exposes the complete
    installation-global registry with workspace labels. Unresolvable project roots fail safe (they can narrow the
    scoped view, never wrongly widen it), and /project use across workspaces names the bound-root change only
    when the target actually leaves the current workspace.

  • Safe local-installer dependency reuse (#1832): Ink source and TypeScript-config changes invalidate the client cache; reuse additionally requires an exact completed-copy marker, a whole-tree match for built output, and successful resolution of every declared production dependency. Pip reuse requires both a pre-existing venv and successful imports of every installed runtime dependency. Cache writes remain strictly post-success and cache I/O or integrity failures still force a full install.

  • Detached review-job stdout transport (#1839): review jobs now return their verdict or revised body
    through stdout without receiving a project file-write channel. After the logfile drainer finishes, the
    engine publishes clean non-empty output as status: done feedback, preserves failed or empty runs as
    status: blocked with their exit/tail reason, and never overwrites a coder-authored feedback file.

  • Refusal-aware Ink tool results (#1834): returned ERROR:/failure markers now replace optimistic tool completion summaries; refused write_file/edit_file calls render the refusal text and can no longer claim that a file was written.

  • Desktop front-half review-job launches (#1833): detached reviewer, meta-reviewer, and reviser jobs now authorize and render the configured agent's canonical launch tuple, with synchronous-runner permission-bypass gating and Memory MCP injection, instead of presenting a synthesized Claude autopilot argv that a pool-derived tooling envelope correctly refuses.

  • Active-initiative artifact-path self-correction (#1823): wrong-slug vault write-jail refusals now name the sanctioned engine tool and teach the engine-derived active artifact root, while steering forbids deriving vault paths from the working directory or project name and reserves trusted scope, design, and unit artifacts for their engine tools.

  • Full-auto front-half notices now direct terminal HARD-blocked designs to /escalate review instead of /approve design, and no longer carry the dead review-path field in continuation state.

  • Lifecycle hard checks now match only real MPR transport residue and exclude engine-authored accepted-review notes; common cosmetic reviewer labels normalize to SOFT while genuinely unknown categories remain fail-closed HARD.

  • Production-shaped MPR convergence: wrapped unscored decision reports now reach strong-coder re-authoring, transport/confidence sentinels are removed from reviewed trade-offs, and an unmapped architecture reviser tier can no longer fail open to routine coders.

  • Breaker-aware lifecycle reviewers: budget- or quota-exhausted R-A/R-B reviewers now trip the shared availability breaker and fail over once, including generic HTTP 402/payment-required failures even when a failed CLI writes stray stdout; exhausted pins and empty independent pools stay loudly unavailable.

  • Control-plane decoy-forgery jail (#1805): model file tools now refuse code-root-relative decoy vault shapes, explicitly canonicalize every active-root and target segment against Win32 trailing-dot/space aliases, and reject forged trusted frontmatter including BOM-prefixed, quoted, and case-varied declarations.

  • Consistent design command surface (#1793): bare /design and /approve design now behave consistently across single- and multi-proposal cases.

  • System-first rolling-summary requests (#1796): merges multiple system messages into one leading copy so vLLM chat templates stop rejecting long conversations with HTTP 400.

  • Guided advisory-override continuation (#1795): an --anyway-approved design now satisfies the design gate so guided mode proceeds to plan_units.

  • Self-correcting product-scope row refusals (#1789): malformed scope rows now show a concrete corrected example, with a loop notice after three repeated refusals.

  • Schema-directed runtime string coercion (#1776): /config set no longer coerces boolean-word tokens like off before checking whether the leaf is string-typed.

  • Aborted client connections handled cleanly (#1782): aborted client connections no longer surface as 500 tracebacks in the durable engine console.

  • Trusted terminal delivery footprint at epic close (#1747): only an engine-stamped completion report can confer the vault's delivery stage, closing a forge path.

  • Language-aware code-root handovers (#1746, #1780): the staged code-root note names the right manifest file per approved design language instead of guessing.

  • Hermetic sibling-test environmental retries (#1769): the nested pytest gate retries kernel crashes, interruptions, and spawn errors up to three times.

  • Product-scope refusal completeness (#1755): the scope parser now handles bad UTF-8, trust metadata, and bounded proposal numbering with a negative test per refusal.

  • Pre-release public-export audit cleanup: fixes public metadata, contributor/demo guidance, roadmap wording, exporter caches, and adds a standard .gitignore.

  • Done-unit redispatch is closed at every dispatch seam (#1738): clients only launch coders after /claim durably returns in_progress, closing a re-dispatch race.

  • Client-launch autopilot slot accounting (#1733): the server now releases its autopilot concurrency reservation once execution is deferred to the client's pool.

  • Fail-closed public Windows engine installation (#1725): the desktop installer now checks venv creation, pip upgrade, and engine import before declaring success.

  • Uniform autopilot value-slot refusal (#1715): the tooling-envelope recognizer refuses any ---prefixed value in a model-authored slot, not just one denylisted flag.

  • Honest reflection-worker shutdown (#1708): ReflectionWorker.stop() now joins the in-flight reflection to completion instead of abandoning a running daemon.

  • Incomplete local-install runtime guard (#1690): a partially written runtime install is marked incomplete and the launcher refuses to start it.

  • Fail-closed public Windows ink-client build (#1691): the installer uses lockfile-exact npm ci, checks exit codes, and only wires the client when the build exists.

  • Accurate task-class names in the code-agent guide (#1684): documents the live complex/standard/routine/analysis classes instead of ones the schema never defined.

  • Memory MCP environment for persistently registered CLIs (#1683): memory env vars are now set independently of a per-CLI mcp_template for persistently registered CLIs.

  • In-engine Memory MCP wiring (#1682): the engine-native autopilot launch path now resolves the same read-only Memory MCP args as the thin client.

  • Live running-unit board state (#1674): BOARD.md republishes when a task transitions to in_progress, not only when the pipeline is idle.

  • Python streamed-turn retry parity (#1670): the Python client now visibly retries a pre-stream 5xx on /chat/stream with the same backoff as Ink.

  • Hermetic sibling-test assertion stability (#1665): the generation gate's nested pytest child now runs with plain assertions, avoiding assertion-rewrite corruption.

  • Runtime config survives a project switch (#1657): a /config set override is now session-global and re-applied above the project overlay on every /switch.

  • ACE adaptation durability (#1660): PlaybookStore.adapt retries transient Windows file-lock failures and reports explicit quarantined/promoted outcomes.

  • Test-report count narrative (#1655): the report header now points to the generated summary instead of unguarded historical count arithmetic.

  • Authoritative feedback-agent completion events (#1673): post_feedback.agent now carries the filename-derived agent instead of the potentially stale requested agent.

  • Code-agent configuration example (#1695): the public BYO-agent guide uses deployment-owned placeholders and shows complete {mcp} wiring for read-only Memory MCP.

  • Multi-agent client override isolation (#1675): legacy single-agent BYO overrides now apply only to a server-resolved Claude spec, not non-Claude registry agents.

  • Terminal tooling-envelope refusal handling (#1676): clients now report a pre-spawn envelope refusal without spending a run, and retain the claim instead of re-firing it.

  • Authoritative handover task labels and bounded validation visibility (#1622): staged handovers reconcile stale Task ID: labels safely, and results carry a bounded validation excerpt.

  • Self-healing FULL continuation (#1651): the reconciler heartbeat re-queues an idle armed continuation's turn, capped at three recovery attempts per unit.

  • Visible, bounded streamed-turn retries (#1650): the TypeScript client preserves error detail and visibly retries pre-stream 5xx responses on /chat/stream with abortable backoff.

  • Automation-aware steering advice (#1649): steering now recommends advance_pipeline/stage_handover only for legs the watcher/continuation doesn't already own.

  • English-only terminal input chrome (#1646): the Ink input box now shows an English placeholder instead of German, and unused localized chrome strings were removed.

  • Source and published client links (#1642): the three clients/ink/ doc links now resolve in both the monorepo and the generated public export.

  • Standalone ACK test imports (#1641): steering-state and command-spec parity tests now bootstrap the engine path directly instead of relying on import order.

  • MPR degradation formatter seam parity (#1640): the documented degrade_format seam is now actually bound to the engine's renderer, pinned by a parity test.

  • Deployment-wide generation settings protected from project overlays (#1639): the generation config prefix is now locked so a project overlay can't override it.

  • Reference-environment-safe documented test counts (#1638): gen_test_counts.py now refuses local runs outside Linux/3.14 and accepts an authoritative CI summary instead.

  • Fail-closed documented test-count generation (#1637): the count check now accepts only a clean pytest exit and retries transient failures instead of trusting a red suite.

  • Tight multiline client blocks regression fix (#1645): fixes a vertical-spacing regression from #1621 across the banner, guided input, listings, and coder status blocks.

  • Authoritative artifact-root steering (#1643): the steering block now shows the active unit's real resolved artifact root instead of a project-relative guess.

  • Visible pipeline routing corrections and bridge-safe shell offers (#1622): advance_pipeline warns on agent mismatch, and execute_command is hidden on Windows without a bridge.

  • Flagship client and board display polish (#1621): /board hides internal managed-block markers from output, and the TS client tightens tool-call block rendering.

  • Deterministic config-key suggestions (#1623): /config set unknown-key refusals now resolve exact/ambiguous leaf names before falling back to edit-distance suggestion.

  • MPR project routing and guidance (#1617): legacy /project new --type now warns it's ignored, and plugin workers inherit the invoking request's active-project context.

  • Live reply-language config updates the active system prompt (#1620): /config set generation.language now rewrites the live system prompt's response-language block in place.

  • Completed coder feedback is surfaced before any next-unit nudge (#1619): steering now detects live in_progress feedback and warns against re-launching the coder.

  • Design promotion provenance and typed vault edge (#1618): /approve design now stamps the proposal as promoted with a typed supersedes edge in GRAPH.json.

  • Empty parallel_reason branches are reported honestly (#1616): a fan-out branch only counts as success when its content is actually non-empty.

  • Orchestrator read-only vault introspection from a split code root (#1615): read-only file tools now fall back to the project root when using a split code root.

  • Implementation handovers preserve the epic-units dev-loop structure (#1613): ad-hoc stage_handover calls carrying implementation work are refused; plan_units is required.

  • English-only /auto toggle + public-export doc/comment polish (#1609): the client's /auto status now prints ON/OFF instead of German, plus assorted export-doc fixes.

  • Terminal client retries a tool result on a recoverable 401 (#1573): the TS client now buffers and retries a 401/403 tool-result POST instead of dropping it.

  • Provider dispatch no longer head-of-line-blocks across providers (#1562): dispatch now runs one executor per provider so a saturated provider can't starve an idle one.

  • German MPR runs resolve every role's German lens (#1557): the German lens overlay is re-keyed to current role labels so all 23 roles resolve correctly.

  • Cancel wakes a bridged tool wait so a dead client can't pin the agent lock (#1553): ToolBridge.request now polls the cancel event instead of blocking the full 180s.

  • ACE rollback surfaces a persistence failure instead of a false success (#1551): PlaybookStore.rollback now checks its writes and reports failure instead of a false success.

  • Engine-native coder launches are hardened to parity (#1548): in-engine coder launches now get process-group kill, a real timeout, and a capped log, matching other paths.

  • Session reload keeps the rolling summary (#1547): load_session now preserves the rolling-summary system message instead of deleting it on reload.

  • Session persistence is atomic (#1546): save_session now writes via fsync'd temp file + atomic rename so a failed write can't truncate the checkpoint.

  • Idle watchdog can abort a blocking synchronous plugin tool (#1545): plugin handlers now run in a daemon worker so a hung tool can no longer wedge the turn forever.

  • LLM requests honour a hard whole-request wall-clock cap (#1544): streaming generation now enforces a monotonic total deadline, closing a slow-drip evasion of existing timeouts.

  • Status poller no longer starts overlapping polls on a slow server (#1542): the health/tasks poller is now self-scheduling instead of firing on a fixed interval.

  • Exiting during /work or /auto reaps in-flight coders before closing the session (#1541): exit now kills and awaits in-flight coder children before closing the session.

  • Bridged execute_command no longer false-timeouts or buffers unbounded output (#1540): the timeout guard now checks exit/signal codes and output uses a bounded rolling tail.

  • Sealed-session shutdown is promptly bounded (#1539): SessionHandle.stop() now aborts in-flight requests via an AbortSignal instead of waiting up to ~20 minutes.

  • Signal-terminated coder is no longer misclassified as timed out (#1538): the timeout race guard now also checks signalCode, not just exitCode.

  • Skill scaffold refuses to overwrite atomically (#1537): write_scaffold now preflights the whole target set so a later conflict can't leave a half-written scaffold.

  • Skill spec rejects param sets that can't form a valid signature (#1536): the validator now rejects Python keywords and duplicate parameter names.

  • Tool-schema requiredness follows the signature, not the annotation (#1535): requiredness now derives from param.default, fixing crashes and invalid null-arm schemas from Optional types.

  • Lodestar resolves cross-domain capability dependencies (#1534): build_backlog now computes implemented capabilities across every domain, not just the current one.

  • Generator escapes descriptions per serialization context (#1533): the paved-road generator now escapes --description per template sink instead of substituting it raw.

  • Doctor fails closed when a requested Lodestar plugin can't load (#1532): a Lodestar load failure now surfaces as a visible ERROR instead of silently running zero checks.

  • --validate-tasks no longer skips capability records (#1531): the doctor gate now validates capability-tagged task records against their full schema too.

  • Busy /chat/stream returns a retryable 503 (#1563): the agent lock is now acquired before streaming headers commit, so a busy engine returns a retryable 503.

  • /auto guidance matches the runtime cap (#1561): the /auto//autoplan flag summaries now describe the actual default task cap instead of claiming "unbounded".

  • Tool-call parser is type-safe (#1558): malformed tool_calls elements are now skipped instead of raising an AttributeError that escaped the retry loop.

  • Roadmap drift check fails on API errors (#1560): gen_roadmap.py --check now fail-closes on gh auth/permission and other API errors instead of soft-skipping.

  • Boundary guard catches dynamic private imports (#1559): the public-boundary AST guard now also flags constant-string dynamic imports of private packages.

  • Scope forget purges ACE side files (#1552): PlaybookStore.forget now removes the history and quarantine side files too, not just the active playbook.

  • Stable boot-only memory and warm config overlays (#1549): memory.json/warm.json now resolve from the boot cwd instead of being cleared by later cwd changes.

  • Bounded coder feedback-file reads (#1543): both clients now cap feedback/capture file reads at 1 MiB instead of reading unbounded coder-controlled files.

  • Bounded chunk-overlap expansion (#1550): MemoryManager._chunks now caps overlap at half the chunk size, preventing unbounded O(len) chunk-memory blowup.

  • Warm tier recovers after a transient first-connect failure (#1556): a failed initial Valkey connect no longer permanently latches the warm tier off.

  • /fanout prompt count is bounded (#1555): the endpoint now refuses more than a configured max prompt count before allocating any fan-out work.

  • Bounded /update subprocess teardown (#1522): timeout/output-limit failures now force-kill the whole build process tree with a bounded drain.

  • Renewable client-run claim leases (#1525): POST /claim now stamps and renews a runtime-configurable lease so a dead client's claim can be reclaimed.

  • Reliable Python tool-result delivery (#1523): the Python client now resends completed tool results through transient/5xx failures with capped backoff.

  • Per-connection slowloris deadline (#1528): the HTTP handler now applies a configurable socket timeout to request-line/header/body reads.

  • Corrupt project registry preservation (#1526): an invalid registry is now atomically quarantined to a sidecar with a warning instead of being silently replaced.

  • Display text cannot forge client control frames (#1524): the capture sink now strips NUL bytes from display text so tool output can't forge control frames.

  • Feedback task-ID path hardening (#1527): POST /feedback now accepts only canonical task IDs and verifies the resolved path stays inside the feedback inbox.

  • Scope guard on memory listing (#1530): GET /memories now enforces the mandatory partition guard, matching every other Mem0 route.

  • Memory service binds loopback by default (#1529): the memory compose profile now binds 127.0.0.1:8800 instead of exposing the unauthenticated Mem0 API on the LAN.

  • Python egress policy namespace enforcement (#1521): Python dependency analysis now canonicalizes py: allow/deny entries so a namespaced deny can't be bypassed.

  • Transactional runtime config cleanup (#1481): removes ~405 unreachable legacy-config lines and routes remaining switches through the clone/validate/derive/commit path.

  • F9 switch-parity guard and schema-owned external seams (#1484): the AST switch-parity guard resolves more dict-access patterns, and external seam config moves into the typed schema.

  • Honest firejail teardown semantics (#1500): firejail is now documented as best-effort-only for descendant teardown, with a one-time operator advisory.

  • Bounded Ink post-kill exit wait (#1500): timeout/cancellation now wait up to two seconds for a killed child to exit, mirroring the Python client's drain.

  • Real-bwrap setsid-reap proof (#1500): an opt-in test verifies real bubblewrap namespace teardown reaps a detached descendant via fork()/setsid().

  • Bounded Python coder stderr and Windows tree-kill proof (#1502): the Python handover client now drains stderr into a bounded 256 KiB rolling tail, matching Ink.

Security

  • Auth gate enforced on operator routes: /events, /metrics, and /alert are now actually covered by
    the deployment-secret (and, under sealed, live-session) gate the docs always described β€” previously their
    guard was a silent no-op, so the review feed, runtime telemetry, and the alert/pager trigger answered
    without the secret. The Ink client's authenticated /events poll is unaffected.
  • DNS-rebinding-safe fetch_url: each redirect hop resolves its host once, fails closed if resolution
    fails or any resolved address is non-public, and pins the validated IP for the connection while retaining
    the original Host header and HTTPS SNI. Redirect targets are independently resolved and re-validated,
    closing the resolver-to-connect DNS-rebinding window.