Skip to content

sync: 0.2.2 Task subagent kind, skill inject budget, claude 2.1.236 - #85

Merged
suoak merged 9 commits into
mainfrom
sync/0.2.2-useful
Aug 29, 2026
Merged

sync: 0.2.2 Task subagent kind, skill inject budget, claude 2.1.236#85
suoak merged 9 commits into
mainfrom
sync/0.2.2-useful

Conversation

@suoak

@suoak suoak commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Summary

AionCore 0.2.2 — selected upstream ports onto main (0.2.1). Adapted, not blindly cherry-picked; fork journal / media pairing / input-queue stay intact.

Taken

Skipped

Pins kept

  • aionrs v0.2.22
  • h2 0.4.16
  • crates stay aionui-*; user-visible branding CSBU WorkMate

Test plan

  • cargo fmt --all -- --check
  • cargo check --workspace
  • cargo test -p aionui-session-message --test delivery_semantics --test e2e_cross_session
  • cargo test -p aionui-app --test midturn_e2e
  • cargo test -p aionui-ai-agent --lib terminal
  • cargo test -p aionui-ai-agent --lib claude_flags
  • cargo test -p aionui-extension --lib auto_inject_skill_descriptions_stay_within_injection_budget
  • cargo test -p aionui-session --lib sniff_task
  • cargo test -p aionui-session --lib cli_version
  • cargo test -p aionui-conversation --lib tool_event_pipeline
  • cargo test -p aionui-conversation --lib summary_from_parts_carries_supports_midturn_delivery_through

Do not merge, tag, or gh release create from this PR.

piorpua and others added 9 commits August 29, 2026 01:19
- return the complete terminal snapshot from the bounded output polling
helper
- wait for expected output before asserting after `wait_for_exit`
- apply the same synchronization to all terminal tests with the same
timing assumption
- preserve exact output, truncation, exit-status, and working-directory
assertions

- `cargo test -p aionui-ai-agent --lib
terminal::tests::output_byte_limit_truncates_from_front -- --exact`
- target test repeated 100 times
- `cargo test -p aionui-ai-agent`
- `cargo clippy -p aionui-ai-agent -- -D warnings`
- `just push -u origin fix/terminal-output-test-race` (8,546 passed; 50
skipped)

Co-authored-by: zynx <>
Moves `VERIFIED_CLAUDE_VERSION` from 2.1.235 to 2.1.236, and
**discharges the hold placed on 2026-08-21**.

| Gate | Result |
| --- | --- |
| A — contract | DEGRADED — claude publishes no protocol schema; gate B
carries the weight |
| B — live e2e | **PASS 14/14**, 304.35s |
| C — release notes | **CLEAR** — 33 notes, 0 REVIEW |

## Why this one was stuck

The constant has been sitting **above** the stable channel for eight
days. An earlier version of the detector read npm’s `latest` tag, which
for `@anthropic-ai/claude-code` points at the bleeding edge rather than
the release most users run, so 2.1.235 was qualified off the `next`
channel. Once the detector was corrected to track `stable`, every
nightly run reported `drift: behind`, and the standing decision was to
hold the floor rather than walk it down — walking it down would have
flagged the majority of users (who install via `npm` or the native
installer, both ahead of stable) as `Newer`.

stable has now caught up and passed it, so the normal flow resumes:

```
stable: 2.1.236    next: 2.1.251    latest: 2.1.250
```

## The candidate is proven from the suite log

```
version=2.1.236 (Claude Code)
```

with the drift lines that only appear because the binary disagrees with
the not-yet-bumped constant. Run through an npm PATH shim into a temp
dir; `~/.local/bin/claude` was read before and after and did not move
off 2.1.239.

## Gate C

Both flagged notes are usage-credits UI — a Fable 5 first-run prompt
auto-selecting a fallback model under Remote Control, and a `/usage`
spend row for Team and Enterprise members. Neither is a surface this
repo drives.

## Also checked

The promotion condition this repo does not machine-check:
`THINKING_DISPLAY_MIN_VERSION` is `2.1.191` (`claude_flags.rs:34`),
comfortably below the new constant. So nobody on exactly the verified
release is told they match while thinking display is silently off.

## Tests

The literal verified-release assertion moves with the constant, so a
future bump that forgets to re-verify still breaks the test. `cargo test
-p aionui-session --lib cli_version`: 14/14. `cargo test -p
aionui-ai-agent --lib claude_flags`: 5/5. Clippy clean, fmt clean.

Record: `~/aion/protocols/samples/claude-cli/2.1.236/`

Constants and record only — no source change.

Co-authored-by: zk <>
…ns (iOfficeAI#943)

## Summary

Scheduled ACP Registry version sync. Two npx pins drifted since iOfficeAI#941,
each backed by a fresh serial ACP probe of the exact pinned version. The
diff is the lock file plus the one lock-derived test assertion that
embeds codebuddy's version.

| backend | package | old → new | initialize | session/new |
|---|---|---|---|---|
| codebuddy | `@tencent-ai/codebuddy-code` | 2.140.0 → **2.141.0** | ok
(protocolVersion 1) | auth required (`-32000`, `data.category: auth`) |
| dimcode | `dimcode` | 0.3.21 → **0.3.22** | ok (agentInfo version
0.3.22) | auth required (`-32000`, "Provider credentials are required")
|

Both meet the release-lock criterion: `initialize` succeeds and
`session/new` returns a clearly classified authentication requirement.
Probes ran serially with no inherited HOME or credentials, and both
entrypoints (`--acp` for codebuddy, `acp` for dimcode) are unchanged
from the previous snapshot.

**Derived assertion updated:** `registry_npx_lock.rs` pins codebuddy's
exact version inside a `--package`-form argument list, so it moves with
the lock — `2.140.0` → `2.141.0`. Both outgoing versions were grepped
across `crates/**/*.rs` before staging: codebuddy's was the only real
assertion, and `0.3.21`'s single hit was a false positive (a `"003421"`
string literal in `pairing.rs`, matched because `.` is a regex
wildcard). `npx_cache_repair.rs` keeps its own version literals: those
are cache-path hash fixtures, not lock assertions, and changing them
would break their hash expectations.

The other 9 Registry-pinned packages (autohand, deepagents, dirac,
glm-acp-agent, grok, kilo, nova, pi, sigit) match the snapshot exactly.
Package names and entrypoint args are unchanged for all 11. Drifted but
not upgraded: none. `mimo-code` remains the one non-Registry builtin (no
`registry_json_id`), excluded from drift reconciliation.

dimcode continues to self-report `agentInfo.title` as "DimAgent" against
a public listing that says "DimCode" — a standing observation since
iOfficeAI#814; no metadata change.

## Registry snapshot

- Audit pinned to release tag
[`v2026.08.28-e9b1b2d`](https://cdn.agentclientprotocol.com/registry/v1/v2026.08.28-e9b1b2d/registry.json)
of `agentclientprotocol/registry`, fetched via the versioned CDN path
for reproducibility.
- 39 ids in the raw snapshot: no newly listed and no delisted agents
versus the baseline. (`antigravity-acp` remains listed and deferred as
binary-only since 2026-08-21; `fast-agent` and `minion-code` remain
listed but uvx-only and therefore out of scope.)

## Validation

- `just migration-check` — pass
- `just lint-fix` (`cargo fix` + `clippy --fix --workspace -D warnings`)
— clean
- `just fmt` — clean
- **Local `cargo nextest` intentionally skipped, by standing policy for
lock-only bumps** (established 2026-08-11). The Test check on this PR is
the authority for this change: the merge decision depends on CI rather
than the local run, and this host's load only manufactures
timeout-shaped test failures, which nothing in the local steps above is
subject to.

## Logging

No logging changes: lock version bumps plus one test assertion; existing
startup/session error paths already identify a failing agent by backend.

Co-authored-by: zk <>
WorkMate 0.2.2 pins VERIFIED_CLAUDE_VERSION to 2.1.236; keep the floor-gate fixture on the same release.
…fficeAI#930)

Auto-inject skill descriptions are a per-session resident cost: they are
injected into every conversation's skills index and count toward a
native CLI's always-on catalog, so their length is paid on every
conversation whether or not the skill is used.

`aionui-config` alone was 666 chars — 47% of the entire index — because
its description duplicated the command list that `aioncore config
capabilities` already reports at runtime. This PR brings the three
over-budget descriptions under 200 chars and adds a guard so new ones
cannot regress.

| Skill | description before | after | index entry before | after |
| --- | --- | --- | --- | --- |
| aionui-config | 666 | **194** | 687 | 215 |
| skill-creator | 226 | **186** | 247 | 207 |
| officecli | 222 | **194** | 239 | 211 |
| cron | 121 | unchanged | 133 | 133 |
| session-message | 119 | unchanged | 142 | 142 |
| **index entries total** | | | **1453** | **908** |

Every description keeps the hooks an agent matches user intent against:
what the skill configures or does, which CLI it drives, and when to use
it. What was dropped is the enumeration of operation verbs, the second
restatement of the same trigger inside `Use when ...`, and behavioural
contracts that belong in the skill body and are already documented
there.

All three are now single-line plain scalars instead of `>-` block
scalars, consistent with the other auto-inject skills.

New guard `auto_inject_skill_descriptions_stay_within_injection_budget`
walks the embedded builtin corpus's `auto-inject/` entries and asserts
each parsed description is at most 200 chars. It measures the parsed
frontmatter value — what actually gets injected — rather than the raw
YAML text.

No migration needed: startup sync upserts builtin descriptions into the
`skills` table, so the new text propagates on the first launch after the
corpus fingerprint changes.

Automated:

- `cargo test -p aionui-extension` — all green
- `cargo test -p aionui-app --test config_cli_e2e --test
skills_builtin_e2e` — all green; the static SKILL.md body assertions are
unaffected since only frontmatter changed
- `cargo clippy -p aionui-extension --all-targets -- -D warnings` —
clean
- `cargo fmt --all -- --check` — clean
- Guard test red/green: with the three descriptions reverted it fails
and reports 666 / 222 / 226; with them applied it passes

Dev build run-through, covering both skill delivery modes:

1. The built binary embeds only the new text; the old text is absent.
2. Startup re-materialized the builtin corpus purely because the corpus
fingerprint changed — no version bump was involved.
3. The materialized on-disk tree and the `skills` table rows both report
the new lengths.
4. Native-skills backends, where skills are symlinked into the
conversation workspace: the linked SKILL.md files carry the new
descriptions, and the prompt contains no skills index — the expected
light-mode behaviour for that delivery path.
5. Injected-index backend: the first-message `## Available Skills` block
measures 1004 chars, down from 1544, with all five entries showing the
new text.

- [x] Unit and integration tests for the affected crates
- [x] Lint and format gates
- [x] Guard test fails on an over-budget description
- [x] Dev verification of native-skills delivery
- [x] Dev verification of injected-index delivery
- [ ] Reviewer sanity check: each shortened description still reads
clearly on its own in the skills list UI, which renders the same string

The `aioncore config capabilities` contract is hand-maintained and has
no completeness assertion against the command tree. That is the more
likely source of future drift and is left to a separate change.

Co-authored-by: zynx <>
…turn is in flight (iOfficeAI#836)

Backend half of the mid-turn interjection feature (frontend:
iOfficeAI/AionUi#4012). claude and codex sessions can now receive a user
message while a turn is in flight; other backends (antigravity, ACP,
aionrs) are completely unchanged. Design spec with measured wire data
for every CLI-behavior claim lives in the internal design doc
(2026-08-12 mid-turn interjection design, verified against claude
2.1.226/2.1.227 and codex 0.144.6).

**T1 — capability bit.** New `Capabilities::supports_midturn_delivery`
(default false; claude/codex true; antigravity explicitly false — one
process per turn, ignores stdin mid-turn; ACP false). Exposed on
`ConversationRuntimeSummary` (serde-defaulted). Neither
`accepts_proactive_input` nor `can_queue` goes on the wire — only this
single-semantic derived bit.

**T2 — command_lifecycle.** claude's `command_lifecycle` frames (echoing
the uuid we mint on user frames) parse into
`SessionEvent::MessageLifecycle { client_msg_id, phase }` with phases
queued/started/completed/cancelled. Unknown states degrade to no event.
`MessageLifecyclePhase` never goes on the wire.

**T3 — agent-driven turn claim.** `claim_for_agent_turn`
(None-when-claimed is the normal case, never 409). The background stream
claims an agent-started turn only when a TTL-bounded (30s,
spec-justified) pending `MessageLifecycle{Started}` marks it as serving
a user message; pure background continuations stay unclaimed so iOfficeAI#758's
detached-exec flow keeps the input box usable. `mint_turn_id` moved
inside the claim branch.

**T4 — mid-turn routing (B5).** Active turn + supporting backend → no
claim, no new turn id: codex goes through `turn/steer` (with
`clientUserMessageId`; both `-32600` rejections discriminated by message
text and locked by tests — turn-ended falls back to a new turn,
different-turn retries with the id parsed from the message), claude
through the resident stdin. Response is 200 with the current active
`turn_id` and `delivered_midturn: true`. Pending confirmation
(requires_action) still refuses mid-turn delivery (409).
`message.userCreated` now carries `client_msg_id` + `status`; new WS
event `message.statusChanged` flips pending→finish when the agent
consumes the message. codex `accepts_proactive_input` flipped true (B5
now wired). Skill injection is threaded through the mid-turn path.

- TDD throughout; targeted suites green per crate (session 553,
conversation 399 lib + integration, app midturn e2e), clippy `-D
warnings`, fmt; full pre-push gate green.
- Live e2e against real claude 2.1.227: mid-turn send 200 into the
active turn, real `command_lifecycle` sequence observed, follow-up
serving turn claimed (state stays `running`), pending marker clears,
later background continuation stays unclaimed.
- Live e2e against real codex 0.144.6: steer ack 200 with same turn id,
message consumed mid-turn, status flip observed.
- Rejection-text matrix, TTL expiry, claim gating (incl. the iOfficeAI#758
no-claim guard), requires_action 409, and wire-hygiene invariants are
all locked by tests.

- No migrations; message status reuses existing DB CHECK values
(`pending`/`finish`).
- Logging: routing decision and claim at `info` (ids only), steer
rejection at `warn`; message bodies are never logged.
- Merge together with iOfficeAI/AionUi#4012 (frontend gate + badge). Old
frontend against this backend is unaffected (additive serde-defaulted
fields).

---------

Co-authored-by: zk <>
…iceAI#890)

A Task subagent and a background bash render identically in the step
list. Two changes converged on this:

- iOfficeAI#758 folded `local_agent` and `local_bash` into one
`CardKind::BackgroundTask`, both headlined `bg task <id> · <clock>`.
- iOfficeAI#870/iOfficeAI#872 replaced the bare tool-name column (`Agent` vs `Bash` — the
last visible difference) with description-derived labels.

After that, a 20-minute foreground Task subagent showed as a wall of
flat tool calls under a `bg task` chip, indistinguishable from a
background shell (live 2026-08-19). The subagent's internal calls were
also un-attributable: the adapter reads the frame-level
`parent_tool_use_id` (009 H5), but the pump dropped it at the
`ToolCallEventData` boundary, so neither the wire event nor the
persisted row carried it.

1. **`SubagentTaskKind::AgentContainer`** — `sniff_task` maps
`task_started.task_type: "local_agent"` to it (verified:
`tests/fixtures/claude_2.1.169_single_tool_turn.ndjson`; the wire
declares foreground and background Tasks the same way).
`WorkflowContainer` alone still gates the Finish-suppression roster —
turn-holding semantics are unchanged.
2. **`WorkflowCard::new_subagent`** — same card machinery as
`new_background`, headline word `subagent` instead of `bg task`. The
pump picks it for `AgentContainer` tasks. A Task row now reads `修复
AIONUI-151 桌面 401 恢复 · subagent ae859b22dc5afbdca · 22:25`; a background
bash keeps `bg task`.
3. **`ToolCallEventData.parent_call_id`** — `translate_event` now
carries the frame's `parent_tool_use_id` on ToolCall/ToolResult frames,
and it persists into the `tool_call` row's content. This is the enabler
for the frontend to group/indent a subagent's internal steps under its
launching Task row (frontend change tracked separately). The field is
`skip_serializing_if = None`, so the DB's `json_patch` upsert
(`sqlite_conversation::upsert_message`) never erases stored attribution
when a later parentless frame — the terminal `tool_result`, a card
refresh, a turn-end close — merges into the same row.

Deliberately NOT changed: a subagent-internal background bash still
opens its own card. The card attaches to a real, visible row and is
currently the only liveness signal inside a subagent stretch;
suppressing it would also perturb the `live_background_tasks` count that

- `subagent_card_says_subagent_not_bg_task` (card unit) and
`task_subagent_card_is_labelled_subagent_and_children_carry_parent`
(pump-level, 2.1.169-shaped script) — headline word + parent attribution
on internal calls, `None` on the main-agent launching call.
- `sniff_task_emits_subagent_update_lifecycle` extended with a
`local_agent` frame → `AgentContainer`.
- `parent_call_id` serialization asserted present-when-Some and
absent-when-None (merge-patch safety).
- Existing background-card, workflow, relay, and persistence suites pass
unchanged: `cargo test -p aionui-session --lib sniff_task` (5), `-p
aionui-ai-agent --lib background_/workflow/tool_call_event/subagent`
(42), `-p aionui-conversation --lib background_stream` (13) + `--test
stream_relay_tool_call/thinking_persistence/acp_tool_call_persistence`
(7), `-p aionui-channel --test stream_relay_test` (8). `cargo clippy -p
aionui-session -p aionui-ai-agent -p aionui-conversation -p
aionui-channel --all-targets -- -D warnings` and `cargo fmt --all --
--check` clean.

Co-authored-by: zk <>
Version the workspace to 0.2.2 and fill parent_call_id, attachments, and steer mapping so the iOfficeAI#836+iOfficeAI#890 port compiles under tests.
…rn/steer

Official Codex turn/steer has a single clientUserMessageId (host mid-turn id). The stale input-1 check could not pass alongside cmsg-7.
@suoak
suoak merged commit c600ec1 into main Aug 29, 2026
6 checks passed
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