# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.3.1] - 2026-10-06 ### Changed - **Stall failover switches the model before the member.** The injected policy now says it outright: a stalled helper's block goes to another model or another upstream first, and swapping members while keeping the same model is pointless — the observed roots of stalled free-lane work were upstream overload (`[503] Upstream error`, three times) and a model the host had deprecated, neither of which a different member repairs. Both READMEs, the 「卡住改派」 panel hint and `docs/GLOSSARY.md` follow the same wording. - **The checked-helper list is labelled as a probe snapshot, not an admission check.** The injected list and the panel's roster hint now state that 「可用」 only means the model answered when the lane was probed: a probe cannot see a deprecated or throttled model, so a real call that fails means switching models, not re-dispatching to the same one. - **Factory default `helpers` enables `mimo-v2.6-flash-free`** in place of the deprecated `mimo-v2.5-free`, so the shipped configuration no longer points dispatched work at a model the host refuses; the built-in reference row for `mimo-v2.5-free` now carries state `unavailable` with the deprecation note. ### Fixed - `.gitignore` ignores `.agent-teams/`, so Agent Teams state files no longer appear as untracked workspace noise. - `scripts/check-i18n.mjs` and `scripts/check-links.mjs` print `[ok]` / `[fail]` instead of the emoji-presentation marks they printed before (U+2705 / U+274C), keeping every file free of emoji as `AGENTS.md` requires. - Self-test counts in both READMEs refreshed to the measured values after the new assertions landed (self-test 131, host smoke 39, client smoke 34). ## [0.3.0] - 2026-09-29 ### Added - **Pre-flight estimate** (`plan`, config v3): before starting, the main agent answers one line — can this work be split into blocks that do not depend on each other, can each block be written as a self-contained prompt, and would a mistake be obvious at a glance? All three yes → worth dispatching; otherwise it does the work itself, and never splits a task apart just to be parallel. When the estimate passes and at least `plan.minBlocks` independent blocks fall out, the plugin permits building an Agent Teams team on the spot and turning each block into a task — gated on `channels.teams` **and** `plan.autoTeam`, and in `ask` mode still asking the user once before building. - **Stall failover** (`failover`, config v3): a helper that produces nothing for `failover.waitSteps` steps counts as stalled. The agent first asks it one question (long research may simply be quiet), then reassigns that block to another checked helper — preferring lower measured TTFT — up to `failover.maxRetry` times, then hands it to `failover.fallback` (`'main'` = the main agent finishes it, or a named `provider:model`). Handover carries the confirmed constraints and whatever was already produced; an already-dispatched block is never dispatched twice; waiting is never an excuse to idle. With Agent Teams checked the check-and-reassign steps use `agent_teams_status` / `agent_teams_reassign_task`; otherwise `list_agents`, and `interrupt_agent` + `subagent` when the subagent channel is on. - **Two new panel sections**: 「动工前预估」 (on/off, minimum independent blocks, may a passing estimate build the team on the spot — the last control locks while `channels.teams` is unchecked) and 「卡住改派」 (on/off, steps without output, reassignments per unit of work, who finishes afterwards — `main` or a named checked helper). - **`sanitizeConfig` convergence for both blocks**: `plan.minBlocks` clamped to 2–8, `failover.waitSteps` to 1–50, `failover.maxRetry` to 0–3 (`0` is kept, meaning never retry), `failover.fallback` normalised to `'main'` unless it is a valid checked-style `provider:model` key; unknown sub-keys are dropped and a non-object block falls back to the factory default. ### Changed - **`CONFIG_VERSION` 2 → 3**: existing v2 files gain both blocks with default values on load, so an upgrade never changes behaviour until the user opens the panel. - Switching either behaviour off does not remove the injected text but replaces it with an explicit 「本轮不做」 instruction, so the agent never improvises its own estimate or failover. In `off` mode both blocks disappear together with the rest of the policy. - The `teams` channel description no longer claims that an explicit request is the only path: a passing estimate with `plan.autoTeam` on is the second one, and the same hint is rendered in the injected text. - Self-test counts in both READMEs corrected to the measured values (self-test 124, host smoke 37, client smoke 34); the previously documented 「71 / 26 / 20」 had drifted. ## [0.2.3] - 2026-09-28 ### Fixed - **The onboarding step no longer renders the settings panel.** The host mounts `settings.onboarding` inside the sidebar's settings column (~250px wide), where the panel — laid out as flex rows for the wide settings modal — collapsed: the 「派活模式」 label overlapped its segmented control, and the hint text was squeezed to one character per line and overflowed the card. That slot now contributes a compact card of its own (`.ad_ob`) with two exits — 「打开设置去配」 (`openSection('agent-dispatch')`) and 「暂时不用」 (persists `onboarding.seen`) — renders nothing while its fact is still loading, and honours `explicit` for an explicitly requested run. ### Changed - Panel rows wrap rather than overlap in a narrow container: `.ad_row` and `.ad_sechead` wrap, and a hint sharing its row with a fixed-width control (`.ad_sub.ad_grow`) gets a 200px wrap basis, so it moves onto its own line instead of collapsing to one character per line. ## [0.2.2] - 2026-09-28 ### Added - **Community scaffolding that matches the wider DSH plugin ecosystem**: `AGENTS.md` (working notes for AI coding agents), `SECURITY.md`, `CODE_OF_CONDUCT.md`, `INSTALL.md`, `.gitattributes` (LF normalisation) and a GitHub Actions workflow that runs `npm run verify` on Node 22 and 24. ### Changed - **English is now the primary language of the repository**: `README.md` became the English primary and `README.zh-CN.md` the Chinese mirror (replacing `README.en.md`), the language bar and every relative link were repointed, and `docs/GLOSSARY.md`, `docs/market-entry.md`, `docs/publish.md`, `CONTRIBUTING.md` plus the prose comments in `index.js`, `client.js` and `scripts/*.mjs` were translated. User-facing UI strings in `DICT` and the injected policy text keep their Chinese form, because the panel is bilingual by design. - Both READMEs now list every repository document, and `package.json` carries the published description, the `files` allowlist and the repository metadata. ### Fixed - `.github/workflows/verify.yml` no longer asks `actions/setup-node` to cache npm dependencies: this repository has no lockfile, so the cache step failed before any check ran. ## [0.2.1] - 2026-09-28 ### Added - **Bilingual README language switcher**: a pair of buttons at the top of each README (four hand-drawn SVGs under `docs/assets/lang/` — active language in deep ink, alternate language in light outline) that switches language on click; no dependency on external image hosts like shields.io, works offline. - **`docs/GLOSSARY.md` terminology reference**: Chinese–English side-by-side + UI source labels + writing conventions, serving as the single source of truth for repository-wide terminology. - **`CONTRIBUTING.md` contribution guide**: commit message conventions (`type(scope): subject`, ten types, no account name / ID / email in commit messages), branching workflow, documentation and i18n conventions. - **`scripts/check-links.mjs`**: scans all Markdown files for relative links and image targets that actually exist, integrated into `npm run verify` (now six checks). ### Changed - Repository-wide terminology aligned to the glossary: unified 「main agent / helper / roster / dispatch / lane / host half」, removed banned synonyms (export, manifest, system prompt, `lane-probe` mixed usage). - `client.js` UI copy: `lane-probed` / `lane-probe` unified to `lane probe`; `notesPlaceholder` example changed to 「不要派给帮手」. - `index.js` comment changes: 「名单」replaced with 「名册」. - Marketplace entry and `docs/market-entry.md` description unified to inject `systemPrompt` section; hard requirement table updated to actual status (pushed, topic added, repository age still pending 24 hours). ## [0.2.0] - 2026-09-28 ### Added - **Onboarding card** (`settings.onboarding`, order -40): four steps explaining 「select channels → select helpers → set capacity → save to take effect」; hidden after `onboarding.seen` is persisted. - **Host adaptation self-check**: panel displays real-time connection status of `webServer` / `systemPrompt` / `llm` services, whether config paths are writable, where `$DSH_HOME` is, which sibling lanes were discovered, and reasons for any `llm` enumeration failure. - **Roster with three sources + `provider:model` keys**: host `llm` actual enumeration (source `llm`, label「宿主已注册」) / sibling plugin `catalog.json` + `availability.json` (source `peer`, label「车道实测」, with measured first-token latency) / manual panel entry (source `manual`) / built-in reference roster (source `seed`, 11-row snapshot, guarantees non-empty panel on first open). Each row shows source and status badge. - **Manual helper entry**: provider input with `` suggestions, model on a separate line, 「加入名册」with empty and duplicate validation; unsaved entries render immediately. - **`GET /api/agent-dispatch/health`**: returns service connection status, config path, roster source counts. - **`scripts/check-i18n.mjs`**: validates zh/en dictionaries have matching keys, no duplicate keys, and all `t()` references in code exist in the dictionaries. - **`scripts/smoke-client.mjs` (browser-half smoke, 20 checks)**: uses a mini hooks runtime as a stub React and a mini DOM as the host page; feeds the panel the **real `/summary` output from the host half**; asserts the panel renders three times (loading → data loaded → onboarding seen) without throwing, root node is `ad_root`, the render tree contains roster `provider:model` keys, contains the **actual injected policy text** (proving preview matches what is sent to the agent), and the onboarding card disappears after being seen. `node --check` cannot catch 「opens to a blank screen」 crashes; this layer specifically catches them — on its first run it caught the stub runtime not expanding function components and Panel not being executed at all. - **Config v2 + v1 migration**: `CONFIG_VERSION = 2`; v1 bare model keys automatically get `our-free-model:` prefix on load, `primary` migrated in sync. ### Changed - **Division of labor written into the injected policy**: free lane handles 「simple, mechanical, self-contained, no dependency on main session context」 work (batch retrieval, per-item audit, copy-edit-rearrange, list-making, translation, formatting, drafting); main agent retains only the most complex, judgment-heavy, high-consequence parts (architecture and key design, cross-module reasoning, correctness and security judgment, dispute arbitration, final delivery). - Dispatch rules now generated from an array with numbered items (9 total), no more hand-written numbering. - **No dependency on any other plugin**: `inject = []` + nested fiber opportunistic acquisition of `webServer` / `systemPrompt` / `llm`; any missing service only disables the corresponding feature, plugin remains fully functional. - Self-check expanded to **71 checks**, host smoke to **26 checks**, browser-half smoke to **20 checks** (the 19 / 12 checks from 0.1.0 are obsolete); `npm run verify` runs all six checks. ### Fixed - Fixed strategy rule numbering skip when `longTaskOnly = false` (previously output 1,2,3,5,6,7). - `POST /reset` changed from 「merge defaults with current config」 to **true replacement**: manually added helper keys are now also cleared. - Panel added missing style classes `.ad_badge.unknown` and `.ad_status.idle`. - `scripts/check-i18n.mjs` false positive where `document.createElement('style')` was misidentified as `t('style')` (regex now includes left boundary). ## [0.1.0] - 2026-08-25 ### Added - **Host half** (`index.js`): registers `systemPrompt` policy section (`agent-dispatch:policy`, order 180), injecting dispatch rules into every step. - **Same-origin HTTP API** (`/api/agent-dispatch/*`): `GET /summary`, `POST /config`, `POST /reset`, `POST /rescan`; non-loopback requests get 403. - **Browser-half panel** (`client.js`): loaded via hand-written `window.__ModuleLoader__`, settings section configurable for dispatch mode, channels, helper models, concurrency cap and extra requirements. - **Atomic config persistence**: config written to `$DSH_HOME/agent-dispatch/config.json`, tmp + rename. - **Pure-function self-check** (`scripts/selftest.mjs`) and **host smoke test** (`scripts/smoke-host.mjs`): runs real `apply()` under a fake cordis ctx, covering 403, persistence, immediate effect, disposer. - **Install script** (`scripts/install-into-profile.mjs`): automatically modifies profile manifest (dry-run / apply / rollback).