# v1.4.0 — 2026-06-28

Stable release of the v1.4.0 series. Closes a 6-day beta cycle (beta.1 →
beta.2 → beta.3) plus three critical post-beta cherry-picks merged into
stable: a `Send` goroutine race, a Feishu recall-probe quota burn, and
an alignment follow-up.

This page is the consolidated stable changelog. For per-beta detail, see
[`v1.4.0-beta.1.md`](v1.4.0-beta.1.md), [`v1.4.0-beta.2.md`](v1.4.0-beta.2.md),
and [`v1.4.0-beta.3.md`](v1.4.0-beta.3.md).

---

## 🚨 Critical fixes shipped late in the cycle

These three landed after beta.3's QA PASS and are part of why v1.4.0 stable
is being cut now rather than as a clean re-spin of beta.3:

- **core: `Send` goroutine nil-pointer panic race** (#1436,
  [@gotang](https://github.com/gotang); follow-up alignment of the third
  call site in `drainPendingMessages` by cc-connect/qa-cursor) —
  `cleanupInteractiveState` could nil `state.agentSession` while three
  `Send` goroutines were still reading it without holding the lock. When
  an agent process exited just before its `Send` was scheduled, the whole
  cc-connect process would panic and drop every platform connection.
  **100% reproducible in production**. Fix captures `state.agentSession`
  under `state.mu` before launching `Send` goroutines and adds a
  nil-check fallback inside each goroutine.
- **Feishu: recall-probe quota burn** (#1321,
  [@qvictl](https://github.com/qvictl)) — `MessageRecallDetector`
  fallback path was polling `GET /im/v1/messages/{message_id}` every 2 s
  for the same active message, burning **~1.3M Feishu OpenAPI calls/month
  per stuck session** and exhausting the 1M/month free quota. Probe
  interval now 1 minute; per-message dedup + in-flight guard inside
  `interactiveState`. Reset on each new active message so recall
  detection still works for normal turns.
- **claudecode: `run_as_user` EACCES regression** (#1433,
  [@chenhg5](https://github.com/chenhg5); reported by
  [@vuyiv](https://github.com/vuyiv) #1429) — chmod `0o644` on per-spawn
  system-prompt temp file so non-root child processes can read it after
  dropping privileges. Fixes a regression introduced by v1.3.4 (#1376):
  `run_as_user` users on beta.1/beta.2 were 100% blocked at agent
  startup with `EACCES` errors.

---

## New platforms

- **Cisco Webex** — first-class Webex Teams adapter with bot identity,
  message routing, and reply support
  (#1402, [@bryantbarzola](https://github.com/bryantbarzola)).
- **Matrix (with E2EE)** — first-class Matrix adapter including
  end-to-end encrypted room support (#834).

---

## Features

### Agents
- **Codex `system_prompt` / `append_system_prompt`** config: codex
  agent now honours per-config prompts the same way claudecode does (#1345).
- **Codex `model_catalog_json`** preferred as highest-priority model
  source (#1074, [@happyTonakai](https://github.com/happyTonakai)).
- **Claude Code `plugin_dir`** — claudecode agent supports loading
  plugins via `--plugin-dir`, exposed as a new `plugin_dir` config
  option (#1325).
- **agent option parsing refactor** — centralize cmd/env option parsing
  into core with a unified `cmd` field across all agent adapters
  (39 files, +863/-419) (#1297,
  [@happyTonakai](https://github.com/happyTonakai)).
  `cli_path` is deprecated in favour of `cmd`. Existing configs continue
  to work with a deprecation warning.

### Platforms
- **Slack streaming preview + aggregated turn card** — live streaming
  preview while the agent is thinking, collapses into a single
  aggregated turn card on completion (#1333).
- **Feishu after_click card replacement for `cmd:` actions** — rich
  cards can now replace their content after a button click for `cmd:`
  action handlers (#1299).

### Send / cc-connect CLI
- **`cc-connect send --cwd`** — specify the working directory for send
  commands (#1380, [@MMMarcinho](https://github.com/MMMarcinho)).
- **`max_attachment_size_mb` for `cc-connect send`** — configurable
  upper bound for outbound attachment size; default preserved
  (#1392, [@rablwupei](https://github.com/rablwupei)).

### Provider presets
- **Zhipu GLM**: `z.ai` and `bigmodel` (CN) presets added to embedded
  `provider-presets.json` (#1412, [@clingnet](https://github.com/clingnet)).

### Web admin / i18n
- **Korean (ko) i18n** — Web admin UI now ships Korean translations
  alongside zh/en/ja (#1343).
- **`nav.cron`** translated for ko/ja/es (was leaking raw "Cron" string
  in the sidebar).

### Daemon / observability
- **`CC_LOG_MAX_BACKUPS` env var** — control daemon log rotation backup
  count via env (#1260).
- **Configurable `/history` truncation** length (#1291,
  [@AaronZ345](https://github.com/AaronZ345)).

---

## Fixes

### Core engine
- **Send goroutine race** (#1436, see Critical above).
- **Feishu recall-probe quota burn** (#1321, see Critical above).
- **`/restart` notification race** — queue the `/restart` success
  notification on the engine and dispatch it when the target platform
  reaches `OnPlatformReady` (with bounded retry + 10 s safety timeout)
  instead of firing immediately after engine startup. Closes the race
  where notifications were silently dropped on platforms with async
  connect (Telegram ~2.6 s, Discord, Weixin, Matrix)
  (#1388 closing #1383).
- **FIFO drain** — queued messages now drain strictly in FIFO order,
  preventing earlier queued messages from being dropped as stale when a
  later one has a higher `create_time` (#1286).
- **Skill discovery depth-1 only** — skill scanning no longer recurses
  into subdirectories. Only `<skill_dir>/<name>/SKILL.md` is registered;
  nested `SKILL.md` files are treated as skill assets and ignored,
  matching Claude Code CLI conventions. Previously, nested `SKILL.md`
  leaked into platform command menus as phantom slash commands (101
  leaked commands from `frontend-design` skill alone)
  (#1317 carrying #1304).
- **acp graceful `/stop`** — new `AgentSessionCanceller` interface lets
  `/stop` shut a session down gracefully via ACP (#1275).

### Run-as-user
- **`run_as_user` EACCES regression** (#1433, see Critical above).
- **Engine workspace binding under `run_as_user`** — keep workspace
  binding even when the supervisor cannot stat it under `run_as_user`
  (#1316).
- **Runas workspace** — run the agent in its own workspace under
  `run_as_user` (#1315).

### claudecode
- **Windows cmdline limit** — file-based system prompt delivery via
  `--append-system-prompt-file` lands on main (port of the v1.3.4
  hotfix). Windows users on claudecode are no longer affected by the
  cmd.exe 8192-byte cmdline limit (#1378 porting #1376).
- **Mid-turn compaction** — keep the turn running when a compaction
  event arrives mid-turn (fixes #481) (#1272).
- **Progress card tool result** — emit `EventToolResult` so tool output
  reaches the progress card (#1407,
  [@coolrockin](https://github.com/coolrockin)).

### Feishu
- **Batch images dropped** — coalesce consecutive image messages from
  the same session into a single multi-image dispatch (configurable
  quiet window, default bumped from 150 ms to 500 ms) so first-image-of-N
  is no longer dropped by the `create_time` watermark from PR #1168
  (#1408 carrying #1395; default tuning by cc-connect/qa-cursor).
- **Markdown `text_color`** — keep `text_color` on `plain_text` elements
  only; removing it from `markdown` elements fixes rendering glitches
  (#1278).

### Slack
- **Streaming card `msg_too_long`** — stop `chat.update` once payload
  exceeds Slack's size limit; deliver full reply via fresh `postMessage`
  instead of crashing (QA hotfix, cc-connect/qa-cursor).

### DingTalk
- **Stream loop panic** — recover panic in DingTalk `StreamClient`
  `processLoop` to prevent process crash on closed channel
  (#1390, fix for issue reported by [@gd0094](https://github.com/gd0094)).

### Workspace / state
- **Workspace model persistence** — workspace-level model selections
  now persist across restarts instead of resetting to default (#1372).

### Cron
- **Permission lookup with composite keys** — pending permission lookup
  for cron sessions now resolves correctly when the key is composite
  (#1067).

---

## Tests
- Regression test for issue #814 — verifies queued messages use their
  own `replyCtx` via the outer drain (#1261).
- `TestWriteTempAppendPromptFile_ReadableByOtherUser` covers the
  `run_as_user` EACCES regression (#1433).
- Several `-race` regression tests around `interactiveState` mutation
  paths (#1436 / #1321 cycle).

---

## Chore / dev experience
- `.gitignore`: add `.worktrees/` for local-only multi-agent scratch
  dirs (#1443). Does not affect the binary.
- Sponsor list refresh — remove four lapsed sponsor entries (#1404).

---

## Upgrade notes

- **`cli_path` deprecation** — switch to the unified `cmd` field at
  your convenience. Old configs continue to work with a deprecation
  warning. The deprecation will not be removed in v1.4.x.
- **Feishu `imageBatchWindow`** default changed from 150 ms → 500 ms.
  Override in config if you preferred the older value.
- **Feishu `MessageRecallDetector`** fallback probe interval changed
  from 2 s → 60 s. If you relied on the old aggressive polling for
  custom integrations, the new behaviour is deduped and gated.

---

## Contributors

External contributors (community PRs landed in v1.4.0):

- [@bryantbarzola](https://github.com/bryantbarzola) — Cisco Webex
  platform (#1402)
- [@happyTonakai](https://github.com/happyTonakai) — Codex
  `model_catalog_json` (#1074); agent option parsing refactor (#1297)
- [@AaronZ345](https://github.com/AaronZ345) — `/history` truncation
  configurable (#1291)
- [@MMMarcinho](https://github.com/MMMarcinho) — `cc-connect send --cwd`
  (#1380)
- [@coolrockin](https://github.com/coolrockin) — claudecode
  `EventToolResult` progress card (#1407)
- [@rablwupei](https://github.com/rablwupei) — `max_attachment_size_mb`
  (#1392)
- [@clingnet](https://github.com/clingnet) — Zhipu GLM presets (#1412)
- [@gotang](https://github.com/gotang) — `Send` goroutine race (#1436)
- [@qvictl](https://github.com/qvictl) — Feishu recall-probe throttling
  (#1321)
- [@vuyiv](https://github.com/vuyiv) — reported #1429 (run_as_user
  EACCES) with a clean repro
- [@gd0094](https://github.com/gd0094) — reported the DingTalk stream
  panic (#1390)

Internal team:

- [@chenhg5](https://github.com/chenhg5) (cg33) — maintainer; many fixes
  and the v1.4.0 cycle ownership
- cc-connect/dev-claudecode, cc-connect/dev-codex, cc-connect/dev-cursor
  — implementation across the cycle
- cc-connect/qa-cursor — full QA cycle across beta.1 → beta.2 → beta.3
  plus three post-beta cherry-picks, including the `drainPendingMessages`
  follow-up alignment

---

## Reference

- Previous stable: [v1.3.4](https://github.com/chenhg5/cc-connect/releases/tag/v1.3.4) (2026-06-16, Windows cmdline hotfix)
- Full diff: [v1.3.4...v1.4.0](https://github.com/chenhg5/cc-connect/compare/v1.3.4...v1.4.0)
- Beta cycle:
  [v1.4.0-beta.1](https://github.com/chenhg5/cc-connect/releases/tag/v1.4.0-beta.1) (2026-06-22),
  [v1.4.0-beta.2](https://github.com/chenhg5/cc-connect/releases/tag/v1.4.0-beta.2) (2026-06-23),
  [v1.4.0-beta.3](https://github.com/chenhg5/cc-connect/releases/tag/v1.4.0-beta.3) (2026-06-28)
