Skip to content

chore(fork): rebuild develop_base with latest upstream and full #1720 - #249

Merged
mindfn merged 61 commits into
develop_basefrom
integration/develop-base-1720-20261026
Oct 26, 2026
Merged

mindfn merged 61 commits into
develop_basefrom
integration/develop-base-1720-20261026

Conversation

@mindfn

@mindfn mindfn commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

结果

将 fork develop_base 一次更新到最新 upstream,并接入完整 上游 #1720 的重复插件权限清理。旧插件可继续使用;不依赖插件仓 #118 清理完成、发布或安装。

精确组成

  • 当前 HEAD:f517b82d31b0fd1a4b5a6577cd629b9a0da45a12。
  • 最新 upstream:fa1dc90fa9704691121cd90a2aa6be6422c954eb。
  • 完整 fix(plugins): remove duplicate Host SDK permission state zts212653/clowder-ai#1720(含全部 CI 修复):40f83e1193c86445832e320071dd0e79fb25fe73。
  • 既有 fork 专属补丁:origin/fork/optimizations@8a90e1423eb4d6d38578edbdaeaafd8f2c2cd3e3。
  • 原 develop_base:70ab66783a9bbc9571e91671dfad16fb959bec9c,保留为祖先。重建完成后使用 ours ancestry merge 记录旧分支已被完整替换,不重新重放旧插件止血实现;最终内容为 upstream + 完整1720 + fork专属层。

本 PR 以原 develop_base 为祖先,因此可普通 merge,无需 force push,也未改写运行工位。运行进程/配置/库存均未修改。

改动与保留

删除 Host 的逐插件 API 权限表、重复裁剪/资格检查、废弃 grant 运行状态与 native MCP 方法白名单。保留当前实例 token、caller/thread/owner、package/lifecycle/currentness、实际 handler 和 Task CAS。历史回执保持不可变,同 operationId 正确重放。

保留 fork 已有治理规则和 MCP verdict 的长请求单次发送行为。fork 层的唯一合并冲突是 MCP 生成快照,已由原生成器重建。packages/api/src、packages/shared/src、packages/web/src、packages/api/vendor 和 pnpm-lock.yaml 与完整 zts212653#1720 source 逐 blob 相同,没有另造 Host 实现。

最新 upstream 相对 zts212653#1720 基点只新增 DMG 发布配置、来源元数据和导出摘要。未接入其他在飞 fork PR。

验证与审查来源

  • 完整 fix(plugins): remove duplicate Host SDK permission state zts212653/clowder-ai#1720 的 source40f83 已通过 Linux CI/build/public、Windows(含 installed layout)、macOS 工作流。生产源非作者批准绑定06b0f475,后续 CI 测试/生成物修正有连续性记录,见上游 PR 正文与 typed fact0001792998584780-004187-309e1b26。
  • 本重建候选:MCP build、canonical governance PASS;201tools、零 surface difference。
  • fork callback/retry/verdict 定向测试:168 pass / 0 fail / 0 skip,使用既有隔离 HOME/outbox。
  • Host API/shared/Web source、vendor 和锁文件与40f83相同;四个组成提交均为祖先;diff check及工位clean。
  • check:skills 总命令在本工位因本地挂载缺失退出1,未报绿;其中59份manifest与73条共享引用检查PASS。没有为了挂载检查改全局/运行配置。

非作者仍需核对重建的内容组成与门禁,批准后普通 merge。不能将这次 PR 当作已运行加载或体验通过。

已明确的产品边界

operator source thread_mvhuoaw19i6uri8v#0001793005239122-004593-c4f5c582 已明确:客户端不要求旧Host直接读取新版写出的格式,撤销降级-only阻断,不加迁移/备份框架或旧权限writer。正常升级读旧数据、历史receipt/幂等仍保留。

本次 fork 接入授权 source:thread_mvhuoaw19i6uri8v#0001793006119814-004642-e28017df。本 PR 只更新分支代码;运行 checkout 更新、构建及重启按运行边界执行,当前均未操作。

合入后按 operator 要求精简历史

operator source thread_mvhuoaw19i6uri8v#0001793007289751-004726-390c42dd 明确授权 force push。已使用一次 atomic push、两条精确 --force-with-lease 更新 canonical fork 分支:

  • upstream/main:fa1dc90fa9704691121cd90a2aa6be6422c954eb
  • fork/optimizations:730852826280327339b4783da47abba02fc63b19,只比 upstream 多1笔 fork专属提交。
  • develop_base:a67d587377ce5fca53d5a47292e66e443bfc85c0,只比 upstream 多2笔:fork专属 + 完整1720。

最终tree f9e3711fc23ef0e4b20f30e59f6260a6c5ae1669 与本PR原merge 51cca01fadb3e0a84b59c15dd9d217280f8ca82f 完全一致,包含此前非作者审查和已成功115s完整workspace构建的同一份源码;这是纯Git历史精简,无新实现,不需要重复审批/构建。原PR249 merge与原source1720记录保留作来源。运行工位只做相同tree的soft reset同步Git HEAD,源码/index未变;旧API PID83342未重启。

zts212653 and others added 30 commits October 20, 2026 02:01
Why: Codex CLI splits dotted override keys even inside quoted server names, preventing installed plugins from launching. Share literal root-table encoding between ordinary and native launch without changing server identity or admitted capabilities. Production regression tests and the installed CLI cover both paths.

Co-authored-by: Codex61Sol-GPT-6.1-sol <glm52@cat-cafe.local>
…12653#1637)

* feat(xiangqi): grant installed chess its bounded conversation access

Why: the playable F170 module needs to verify the direct human source and selected cat, then notify that same conversation after confirmed moves. Without a Host policy, installation silently has no native action authority. Reconcile existing instances while retaining their identity and data.

Thread-Context: thread_muj7u295taln61l7#0001792481821510-000899-01469f6f

[小太阳·砚砚/gpt-6.1-sol🐾]

* style(xiangqi): format the Host grant regression fixture

Why: satisfy the repository formatter for the new admission and reconciliation tests; authority behavior is unchanged.

[小太阳·砚砚/gpt-6.1-sol🐾]

* fix(codex): preserve literal installed MCP server names

Why: Codex CLI splits dotted override keys even inside quoted server names, preventing installed plugins from launching. Share literal root-table encoding between ordinary and native launch without changing server identity or admitted capabilities. Production regression tests and the installed CLI cover both paths.

---------

Co-authored-by: Codex61Sol-GPT-6.1-sol <26771442+zts212653@users.noreply.github.com>
Co-authored-by: Codex61Sol-GPT-6.1-sol <glm52@cat-cafe.local>
Why: Supplementary read-only turns in directory-based projects omitted the
existing non-Git startup flag and exited before invoking the model. Preserve
that compatibility path without changing sandbox, approval, or tool policy.

Cover fresh and resumed read-only turns in both Git and non-Git workspaces,
including restrictions against member capability overrides.

[砚砚/gpt-6-astra🐾]
Thread-Context: threadId=thread_mv7thmm728ww9o5i catId=cat-xooblf7l

Co-authored-by: CatXooblf7l-GPT-6-astra <yuki@YukideMacBook-Pro.local>
Co-authored-by: Lysander Su <773678591@qq.com>
* Fix finalized ACP input history and member actions after main sync

* Scope finalized tool inputs to their execution in replay and trajectory

* fix: verify native partner login and correct member availability

* fix: honor Windows shell plan in native Claude login check

* test: cover forced native login refresh in onboarding mocks

* fix: resolve shell before first paint and preserve onboarding navigation

* fix: retain shell preference when browser storage rejects writes

* docs: record production onboarding performance verification

* test: align native runtime discovery with authenticated readiness

* Persist owned member creation receipts and simplify the member list

* Correct the complete existing-member fixture

* Type-check inactive member fixture without assertions

* Document closure contracts and capture native lease identity evidence

* Restore detached startup identity capture and extend native witness

* Preserve exact launchd identity with single-line child command transport

* Keep ACP descriptor ownership collision-free and validate restored members

* Align cleanup fixtures with the launcher drain contract

* Retain native exit-wait liveness and publish member UI evidence

* fix(onboarding): preserve bounded ACP creation request identity

* fix(onboarding): validate legacy goal receipts and canonical stop identity

* feat(desktop): support isolated installer acceptance without production access

* fix(desktop): isolate inherited storage and authentication environment

* fix(desktop): exclude owned ports from packaged origin redirects

* test(desktop): cover preload argv and Windows PowerShell encoding

* fix(onboarding): recover pending collisions and freeze installer dependencies

* fix(desktop): make locked artifacts portable on Windows tar

* fix(onboarding): prove legacy request ownership and scope installer shutdown

* fix(desktop): isolate shutdown from legacy receivers and path aliases

* test(desktop): compare persisted root by filesystem identity

* fix(installer): use supported uninstaller execution flags

* test(windows): bound temporary directory release after CLI shutdown

* fix(onboarding): preserve shell and manual creation, pace demo and persist admission

* fix(desktop): report startup failure without blocking and bind persistent workspace

* fix(onboarding): route existing teams to readiness and retain zero-start recovery

* fix(onboarding): serialize guide receipts and validate fresh installer entries

* fix(onboarding): retain unconfirmed completion through roster reads

* fix(desktop): initialize only new teams empty and preserve existing templates

* fix(ci): register OpenCode configuration and split startup prompt

* test(api): retain listening gate contract with startup diagnostics

* fix(onboarding): preserve unknown preferences and desktop upgrade identity

* test(desktop): use host-native path for upgrade identity witness

* docs(onboarding): record installed Windows journey and review evidence

* fix(desktop): reject unresolved instance directory aliases

* test(desktop): compare canonical Windows data directory identity

* fix(desktop): share frozen Windows dependencies and report archive progress

* fix(desktop): carry generated web assets and require archive manifests

* fix(desktop): lower archive worker CPU priority and record resource limits

* perf(desktop): avoid recompressing runtime archives

* test(desktop): normalize archive regression imports

* test(api): isolate native callback wiring capability policy

* fix(desktop): omit compiler cache from packaged web runtime

* perf(desktop): verify native extraction and bundle API startup graph

* fix(desktop): contain snapshot aliases and preserve admission failures

* style(desktop): satisfy DSH snapshot import ordering

* fix(onboarding): refresh default responder and isolate optional DSH credentials

* fix(settings): fence stale default responder refreshes

* fix(installer): latch extraction failures before setup actions and launch

* test(installer): assert the fatal extraction latch

* fix(review): canonicalize API bundles and fence confirmed member preferences

* fix(desktop): isolate preview gateway and record recovery evidence

* fix(members): migrate draft baselines with canonical carrier

* fix(web): avoid unused retired draft bindings

* test(codex): select app server in collaboration fixtures

* docs(onboarding): record merged carrier validation and build sources

* docs(onboarding): record native verification and reminder exemption

* fix(desktop): preserve workspace identity in shared runtime dependencies

* fix(desktop): limit runtime hoisting to registered workspace roots

* test(desktop): run workspace peer identity regressions in Windows CI

* fix(desktop): verify the shared workspace runtime location after install

* test(windows): bound fixture cleanup retries and record clean install evidence

* fix(onboarding): admit native clients and settle installation processes

* fix(kimi): preserve explicit native model aliases

* test(onboarding): own native Codex login fixture in batch creation

* fix(onboarding): explain Codex login admission before creation

* fix(onboarding): label native clients and surface OpenCode workspace prerequisite

* fix(desktop): bound dependency bundling and trace production Web dependencies

* test(windows): keep detached identity fixture alive during CIM probes

* docs(windows): record trimmed runtime first-install and upgrade evidence

* perf(desktop): overlap service startup and defer optional clients

* fix(onboarding): diagnose Kimi grants and support default OpenCode threads

* fix(opencode): normalize v2 provider errors and terminate permanent failures

* test(desktop): follow extracted renderer navigation contracts

* fix(desktop): defer heavy startup imports and isolate OpenCode service transport

* fix(desktop): align Kimi native homes and bundle installer hook setup

* fix(mcp): report configured startup timeout within remaining budget

* test(kimi): align native home fixtures and register code home

* perf(desktop): split canonical runtime package entry graphs

* test(memory): diagnose index rebuild writer latency without weakening limits

* fix(onboarding): bind browser API origin and distinguish native partners

* feat(onboarding): discover Pi through a scoped native RPC bridge

* perf(startup): add performance analysis and optimization infrastructure

- Add comprehensive performance analysis identifying 112s cold start bottleneck
- Create lazy telemetry loader (conditional OpenTelemetry, ~10-15s savings)
- Create conditional validation utilities (skip Zod in production, ~5-8s savings)
- Document optimization strategy and implementation plan

Key findings:
- Module loading: 60.7s (3,275 modules, 50.9s read time)
- Archive extraction: 70.1s (82,919 files)
- OpenTelemetry: 24 file imports on startup
- Zod validation: 317 imports across codebase

Optimization tools ready for integration:
- packages/api/src/telemetry/lazy-telemetry.ts
- packages/api/src/config/lazy-validation.ts

Expected improvements after integration:
- Cold start: 112s → 80-95s (15-29% faster)
- First install: 117s → 90-100s (15-23% faster)

Refs zts212653#1519

* perf(desktop): enable ASAR and document root cause of slow startup

ROOT CAUSE IDENTIFIED:
- asar: false = 107,000 small files (24,606 app + 82,919 archive)
- Each file = 1-2ms I/O = 107-214s theoretical minimum
- Windows Defender scans each file individually

CHANGES:
1. Enable ASAR in desktop/package.json (asar: true)
2. Add asarUnpack for native modules (*.node files)
3. Document complete analysis and implementation strategies

CURRENT IMPACT:
- Main process files now in app.asar (~100 files → 1 file)
- Minor improvement: 2-3s faster main process startup

LIMITATION:
- API/Web/MCP still in extraResources (14,162 files unpacked)
- Need Phase 2 to move these into ASAR for full benefit

DOCUMENTED SOLUTIONS:
- docs/design/asar-optimization-root-cause.md (problem analysis)
- docs/design/asar-implementation-strategy.md (3 implementation options)

Phase 2 Options:
A) Move packages to app.asar (90%+ improvement, high complexity)
B) Pre-bundle packages.asar (70-80% improvement, medium complexity)
C) Optimize compression (30-40% improvement, low complexity)

Expected after full implementation:
- Install: 117s → 3-10s (97% faster)
- Cold start: 112s → 8-20s (82-93% faster)

Refs zts212653#1519

* perf(desktop): add ASAR optimization analysis and realistic implementation path

FINDINGS:
1. ✅ Main process ASAR enabled and tested (working)
2. ❌ Pre-bundling packages.asar takes >180s (2GB of data)
3. ❌ Node.js spawn() cannot execute scripts inside ASAR
4. Reality: Full ASAR approach has fundamental limitations

ADDED FILES:
- desktop/scripts/pre-bundle-packages.mjs (experimental, too slow)
- docs/design/asar-implementation-reality-check.md (analysis)

RECOMMENDATION: Pivot to practical optimizations
- Keep main process ASAR (already done, 2-3s improvement)
- Focus on compression optimization (zstd, multi-threading)
- Implement lazy loading (telemetry, validation)
- Bundle more dependencies to reduce file count

Expected with practical approach:
- Install: 117s → 60-80s (32-49% faster)
- Cold start: 112s → 70-85s (24-37% faster)
- Low risk, verifiable improvements

Next steps: Implement compression optimization + lazy loading

Refs zts212653#1519

* docs: create upstream issue zts212653#1606 for installation and startup performance

Issue created at: zts212653#1606

Summary:
- Install: 117s (6-12x slower than industry standard)
- Cold start: 112s (22-37x slower than industry standard)
- Root cause: asar: false + 107,525 small files
- Proposed solutions: Enable ASAR, lazy loading, compression optimization
- Expected improvement: 60-75s cold start (33-46% faster)

Complete analysis and optimization utilities available in this branch.

Refs zts212653#1519, zts212653#1466

* fix(ci): remove unintegrated startup prototypes and format helpers

* chore(desktop): remove abandoned ASAR prebundle experiment

* fix(desktop): unpack external Node dependencies to resolve startup crash

Root cause: runtime-web-config.js and startup-timing.js were not unpacked
from app.asar, causing Web subprocess to exit with code 1 before HTTP ready.
External Node processes cannot resolve dependencies through Electron's ASAR
virtual filesystem.

Changes:
- Add subprocess-entry.js: resolves external Node entry paths, mapping
  app.asar paths to app.asar.unpacked for packaged apps
- Update service-manager.js: use resolveExternalNodeEntry for API preload
  and Web server subprocess entry points
- Update package.json: add asarUnpack patterns for api-startup-probe.mjs,
  runtime-web-server.js, runtime-web-config.js, startup-timing.js
- Add subprocess-entry.test.js: protect path resolution contract and
  ensure all external Node dependencies are in unpack list

Verification:
- subprocess-entry.test.js: 2/2 pass
- Validates development and packaged path resolution
- Asserts all four external Node scripts are in asarUnpack

Fixes user-reported startup failure in PR zts212653#1519 where Web process could
not find './runtime-web-config' module.

Next: rebuild Electron candidate, verify ASAR contents, and perform
clean install acceptance test.

* docs: add build verification and progress reports for PR zts212653#1519

- build-verification-ad68f62.md: ASAR content validation report
  * Verified all 4 external Node dependencies correctly unpacked
  * Recorded build artifacts SHA-256 hashes
  * Confirmed subprocess-entry.js path resolution contract

- progress-2026-10-16.md: Implementation progress summary
  * Work Unit #1 complete: code changes committed and pushed
  * Work Unit #2 partial: ASAR verified, full build pending
  * Work Units #3-4 blocked: need complete runtime bundle

Status: Core fix verified in ASAR structure. Full end-to-end validation
requires completing frozen runtime export and clean install acceptance test.

* fix(ci): use platform-native desktop path fixtures

* fix(desktop): report the installer produced by this build

* fix(desktop): reject stale API artifacts in revision-bound exports

* fix(desktop): stamp API only after a consistent production build

* fix(desktop): verify exported release identity before archiving

* fix(desktop): isolate frozen dependency resolution from source ancestors

* fix(desktop): exclude development dependency junctions from installers

* chore(desktop): use 1.14.0 for PR1519 validation builds

* docs: trace PR1519 installed UI and historical fork sync

* docs: record confirmed shell preference and isolated restart

* feat(desktop): default new profiles to v2 without overriding shell choice

* docs: record v2 desktop validation and clean-user handoff

* fix(onboarding): reuse explicit native client homes and identify creation failures

* test(onboarding): exercise selection and recovery in the browser and isolate installer hooks

* fix(onboarding): inspect API configuration before Claude login probes

* test(onboarding): gate setup acceptance on recovery and real client tasks

* perf(api): load Claude SDK only when its carrier is invoked

* test(onboarding): prove real A2A causality and settle owned test executions

* fix(onboarding): initialize collaboration tools before first-run plugins

* perf(api): defer Claude SDK in catalog and local session readers

* test(onboarding): observe native journeys and require natural terminal completion

* test(onboarding): cover installed startup faults and complete configuration journeys

* perf(desktop): bound program read-ahead using frozen startup traces

* fix(desktop): share startup hint policy and verify installed consumption

* test(onboarding): bind rendered replies to persisted message identity

* perf(desktop): size read-ahead budget from cold IO evidence

* test(onboarding): verify assistant body and retain cold-install failure

* test(desktop): retain frozen startup failures and all history outcomes

* test(e2e): observe native renderer faults and await complete startup traces

* fix(web): avoid nonexistent avatars while member data hydrates

* fix(web): end preference reads with document lifecycle

* test(web): keep cached current-document failures visible

* test(onboarding): trace caller cancellation and preserve real faults

* test(onboarding): prove A2A reads from complete native journals

* test(onboarding): prove visible routes for fulfilled RSC cancellations

* docs(onboarding): reconcile reviews and original Claude protocol evidence

* test(onboarding): validate restored Markdown and preserve real Claude failure

* test(onboarding): verify installed replay retains existing state

* fix(test): guard shared Codex history and record verified cleanup

* fix(onboarding): connect first-team creation to F155 reminders

* docs(onboarding): record accepted external Claude API limitation

* fix(onboarding): recover entry reminders and protect newer guide requests

* fix(onboarding): avoid duplicate receipts and transient empty roster inference

* fix(desktop): recognize packed lifecycle handlers before scoped shutdown

* fix(installer): honor no-icon installs and record native journey blocker

* fix(onboarding): acknowledge personal reminders through their preference owner

* fix(onboarding): keep reminder dismissal personal and isolate browser sockets

* test(onboarding): isolate production setup contracts from live runtimes

* fix(installer): retain identity preparation diagnostics

* test(onboarding): leave retired thread before cleanup

* docs(onboarding): record verified high-label install journey

* test(onboarding): allow natural A2A acknowledgements

* fix(pr1519): close A2A proof and desktop recovery gaps

* fix(desktop): keep main process within size gate

* docs(pr1519): reanchor closure plan to current head

* fix(installer): run identity helper without output capture

* fix(installer): omit empty identity arguments

* fix(installer): record identity helper command

* fix(members): preserve native identities and separate detection entry

* fix(desktop): ignore non-target sharp optional traces

* fix(desktop): tolerate missing sharp optional packages

* docs: hand off PR1519 packaging and acceptance

* docs: incorporate PR1519 review gates

* fix(pr1519): close review P1/P2 gaps

- desktop: include startup-failure-handler/shutdown-controller in build.files; extract shutdown chain; behavior tests for startup failure and installer-requested quit; win32 app.asar closure assertion in afterPack
- a2a: require proof-explained inputs, immutable result set, no new dispatch and real completedAt for extra invocations; add RED fixtures
- installer: restore ExecAndLogOutput diagnostics, per-parameter args with fail-closed ports-without-root, native installer tests in PR Windows smoke, build manifest in dist
- web: restore first-run/onboarding/A2A test scripts dropped by merge; add CI missing-script guard; refresh stale wizard tests
- kimi: observe native config model for identity/capabilities without injecting --model
- docs: acceptance checklist for remaining local/CI/real-install verification

* fix(pr1519): unblock frozen export and record build evidence

- desktop: treat non-target @emnapi optional trace inputs like missing sharp optionals so frozen runtime export succeeds
- desktop: verify installed Electron against package-lock before electron-builder and reinstall from lock on drift
- docs: record local test/build evidence, acceptance checklist and remaining No-Go items

* fix(desktop): enforce clean release evidence

* chore: ignore local desktop resource cache

* fix(desktop): raise restrictive installer integrity to High

Two distinct launch failures came from the build root's inherited mandatory integrity label:
- Low label: Inno Setup runs at Low integrity and cannot create %TEMP%\\is-*.tmp (error 5).
- Explicit Medium label: the elevated Setup is capped at Medium, so the PrepareToInstall identity helper's Add-Type fails with Win32 1314.

- installer-integrity.mjs: treat no-label or explicit High as releasable; raise Low/explicit-Medium/other labels to High and fail closed when still blocking; --check and --copy-to delivery modes
- build-desktop.ps1: warn when the build root carries a restrictive label, raise the Setup to High after Inno compilation, fail the release build if it stays unlaunchable, and record integrity in build-manifest.json
- Windows-only desktop/installer-integrity.test.mjs (7 cases) runs in windows-smoke
- document both failure layers, the High fix, immediate repair and verification

* fix(pr1519): close shutdown reentry and first-run fixture gaps

* fix(codex): keep native inherited model schema-valid

* fix(desktop): diagnose tray lifecycle and preserve close behavior

* fix(desktop): trace startup stages before tray creation

* fix(desktop): preserve tray and mac close contracts

* fix: keep Codex discovery out of native history initialization

Why: short-lived login and catalog App Server probes interrupted native SQLite history backfill, leaving subsequent Mac replies unable to start. Use native inspection commands, project only model metadata, and let the actual host complete bounded cold initialization. Authorized as an incremental fix to PR zts212653#1519 by CVO source 0001792311053164-002327-1d31e676.

* fix: preserve native third-party provider login readiness

Why: native login status reports the absence of OpenAI credentials even when the configured provider explicitly uses its own authentication. Preserve the prior no-OpenAI-login behavior through the existing bounded provider configuration projection, including selected profiles, without starting App Server.

* fix: preserve native Claude print model inheritance

Why: native-tool members deliberately inherit an empty model selection from the CLI. The print carrier passed that empty selection into non-empty MCP capability modelFamily validation and failed before spawn. Use provider-default only for capability identity, keep the actual request model omitted, and cover the known-host-version print launch path.

* refactor(kimi): sunset legacy CLI integration

Why: the retired kimi-cli shim can shadow Kimi Code and exit successfully without a reply. Support only the native kimi program and its configuration, identity and capability directories; remove obsolete flags, Python installation and temporary MCP config generation. Keep user accounts and histories untouched and surface empty replies as errors.

* test(kimi): align remaining skill fixtures with native directories

Why: public CI exposed test fixtures that still derived .kimi from the provider id after Kimi Code defaults moved to .kimi-code. Update the scoped sync, conflict/rollback and drift fixtures without changing production code, safety assertions or performance thresholds.

* test(kimi): expect the native Windows installer label

Why: the remaining public CI assertion still expected the retired Kimi label after the installer switched to Kimi Code. Align the exact label expectation without changing runtime code or relaxing installer checks.

* fix(desktop): diagnose tray and process lifecycle

* fix(build): prefer Windows tar for runtime archives

* fix(installer): materialize shared skill refs on Windows

* fix(build): reject inconsistent Web artifacts before packaging

* fix(installer): guard shared refs and document release gates

* fix(desktop): reuse host client homes for isolated detection

* fix(build): enforce clean runtime archives and client detection

* build: declare approved native dependency scripts

* fix(web): declare runtime asset dependency

* fix(collective): declare zod runtime dependency

* fix(web): declare zod runtime dependency

* fix(api): declare direct runtime dependencies

* fix(web): declare markdown type dependency

* fix(build): resolve runtime bundlers from api workspace

* fix(build): validate frozen web with explicit resolver

* fix(build): align archive gate with sidecar schema

* fix(installer): resolve runtime junctions during instance setup

* fix(desktop): resolve junctions before instance boundary checks

* fix(api): resolve runtime scripts from installed root

* fix(desktop): gate API startup on project mirror readiness

* fix(onboarding): recognize Claude API settings credentials

* fix(desktop): bind host client homes for ordinary installs

* fix(onboarding): bind native clients to usable host homes

* fix(onboarding): stabilize demo playback and Pi lifecycle dispatch

* fix desktop API bundle admission and startup fallback

* correct deploy API archive entry gate

* fix(onboarding): close native readiness and Windows release regressions

* test(onboarding): verify readiness before recommended team creation

* test(windows): normalize temporary fixture path aliases

* fix(onboarding): distinguish installed clients from login readiness

Why: a failed or unknown default login check hid installed-client model metadata and displayed installation help. Keep physical availability separate from identity-scoped selection while retaining the existing login admission gate.

Build on the author fixes in dd28b77 without duplicating their client-home, Pi, identity-restoration or test-wiring changes. Point alternate connections to the existing manual entry, update the obsolete create-before-login assertion, and add red-to-green coverage for both login_required and unknown.

Validation: first-run web 262 passed; desktop regression 104 passed / 11 platform skips; web typecheck and Biome passed; real settings page with isolated HTTP/socket/draft fixtures passed default gating, installed model metadata, adjustment and alternate-account rediscovery/create. API build passed; no real account or model requests.

[小太阳·砚砚/gpt-6.1-sol🐾]

* fix(onboarding): skip thread preferences on empty landing page

* fix(onboarding): remove redundant demo team strip

* fix(onboarding): detect DSH before first ACP initialization

* fix(onboarding): keep retained runtime option explicitly enabled

* test(onboarding): isolate DSH fixtures from host Node lookup

Why: on macOS the discovery assertion compared a Homebrew symlink with the physical Node path, while the catalog fixture removed which from PATH and falsely reported not_installed. Own the Node lookup in each fixture instead of depending on host PATH tools or aliases.

Keep production discovery, first-connection initialization, invalid-profile rejection, idempotent replay and process-boundary assertions unchanged. Native discovery restores mocked builtin exports after the test; catalog discovery still rejects unexpected synchronous process launches.

Validation: the same isolated API collection changed from 7 pass / 2 fail to 9 pass / 0 fail; full first-run web collection 271 pass. Biome and git diff --check pass. No real credentials, model calls, or service launches.

[小太阳·砚砚/gpt-6.1-sol🐾]

* fix(onboarding): restore native cat identities and serialize lifecycle dispatch

- add shared Kimi/DSH/Pi identities; DSH is 小鲸鱼/鲸鲸 with new avatar

- remove hardcoded DSH/Pi names; repair legacy drafts and catalog members

- merge shipped roleTemplates into the project template on desktop

- serialize dispatchRef writes with a Redis lock and retry transient contention

* fix(onboarding): repair legacy detection drafts before identity review

A stale native-team draft whose members are no longer in the roster is a fresh recommendation, not a pending creation replay. Repair its legacy Kimi/DSH/Pi defaults so the one-click detection card shows the cat identity.

* style: format onboarding identity lifecycle changes

Apply the repository formatter to the new native identity migration, lifecycle retry, and regression tests so the PR lint job sees the committed LF content exactly.

* test(onboarding): observe runtime configs and settled append delivery

Why: the production browser oracle identified Pi by its retired nickname and reported valid Pi creations as DSH. Match the submitted discovered launch configuration instead, treating omitted stdio as its documented default. Append delivery now persists acceptance through an async retry boundary, so six assertions raced its completion; wait for the existing source-retirement condition before asserting final dispatch counts and whisper isolation.

Keep production behavior and all existing assertions unchanged. Observed the CI browser failures and reproduced Append RED (68 pass / 6 fail), then verified the Append suite and adjacent Queue coverage GREEN (146 pass). Production-browser validation follows on the clean candidate required by the build identity guard.

[小太阳·砚砚/gpt-6.1-sol🐾]

* fix(queue): keep append admission on the direct lifecycle dispatch path

Only enter the contended retry helper after a transient conflict. The unconditional wrapper added an async boundary to every append acceptance, which let timing-sensitive append settlement assertions observe the source row before it was retired.

* style: format lifecycle admission fast path

Apply the repository formatter to the direct dispatch call so the PR Lint job sees the committed LF content.

* fix(desktop): use a native menu bar image on macOS

Why: macOS cannot decode the Windows ICO passed to Tray, so every packaged launch reports that the system tray is unavailable. Select the packaged PNG and resize its native image to 18 pixels while retaining the Windows ICO path and legacy tray callers.

* refactor(desktop): keep native tray wiring in its module

Why: the native tray fix expanded main.js beyond its existing 350-line boundary. Keep platform asset selection beside tray creation, preserve the validated PNG/nativeImage behavior and Windows ICO path, and cover both native entry paths with a regression test.

* test(onboarding): reuse production draft revision handling

Why: autosave may replay a stale draft revision while the page reloads. The browser fixture asserted instead of returning the production HTTP 409 response, causing an unhandled rejection after otherwise passing journeys. Route draft requests through the real in-memory API handlers so the client exercises its existing conflict recovery.

* fix(desktop): fail closed when Redis is unavailable

Why: an ordinary install silently switched the API to its in-memory store
whenever Redis was missing, could not start, or had its port taken by a
non-Redis process. The launcher then injected MEMORY_STORE=1 and
CAT_CAFE_INVOCATION_REGISTRY=memory, satisfying the explicit-degradation
guards in storage-guard.ts and InvocationRegistry.ts on the user's behalf, so
history and queued work silently stopped being durable.

Now every Redis failure throws a typed RedisUnavailableError with a user-facing
recovery hint, and memory mode is reachable only through an explicit
single-launch consent: the startup failure dialog writes it, the relaunch
consumes it once, and the following launch fails closed again. Isolated
instances stay fail-closed even with consent, the API-failure retry follows the
same consent, and a healthy Redis still never degrades on a slow API start.

Tests: desktop/service-manager-memory-fallback.test.js (9),
desktop/startup-state.test.js (8), desktop/service-manager.test.js (5). The
spawn-dependent service-startup case keeps its original invariant by opting in
explicitly.

* fix(desktop): keep one-launch consent fail-closed

Why: consumeMemoryFallbackConsent removed the consent file with a swallowed
error and still returned true, so a consent that could not be deleted (EACCES,
AV lock) authorized every later Redis failure instead of asking again. The
Redis failure error also advertised the memory option unconditionally, which
offered an isolated instance a choice it can never honor and looped back into
the same error after the relaunch.

Now a consent that cannot be removed is neutralized and never authorizes a
launch, an isolated instance discards stale consent instead of inheriting it,
and recovery.allowMemoryOnce mirrors what the launcher can actually do.

* fix(build): regenerate the lockfile with pnpm 9 to keep the overrides contract

The pnpm 11 install used while syncing main ignored package.json's pnpm.overrides and dropped the lockfile overrides section, so pnpm 9 --frozen-lockfile failed with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH on every CI job.

* fix(web): restore merged settings and API client contracts

F202 removed the IM connector settings section and its install button, so the merged Settings header must not reference them. api-client keeps upstream's inline ApiFetchOptions (with mutationTimeoutMs) together with the branch's save-trace transport; the unused api-client-types split is no longer imported.

* fix(api): align SDK lazy fixture with streaming idle and drop stale staging harness

The merged SDK carrier closes a streaming query only after session_state_changed idle, so the lazy-load fixture now emits running/idle around its result instead of ending on a bare result. F202 rewrote package staging: preflight requires a genuine gzip archive and extraction is a third tar child, so the old two-child concurrency harness no longer describes the implementation; its Promise.allAllSettled wait stays in the source and the obsolete test is removed rather than left red.

* fix(governance): refresh the MCP surface baseline for the cross_post_message description

The branch's callback_tools description change (+323 characters) and the resulting module digest were never regenerated, so governance:check reported a canonical-registry mismatch. Regenerated with governance:write against upstream/main: 0 tools added or removed, descriptions and implementation digests updated.

* fix(desktop): assert the branch's runtime extractor and drop retired plugin roots

F202 replaced passive tar extraction with extract-runtime-archive.cjs (integrity + progress), so the packaging contract now checks that link instead of a literal tar Parameters line. The retired Host plugin source root is no longer part of the packaged-input census.

* fix(acp): keep one member's bootstrap failure from aborting API startup

The installed API exited before port 3004 when the dsh member's Windows ACP bootstrap privacy check rejected the profile temp ancestors: a sandbox group and several sibling SIDs hold Modify on %TEMP%, so the private bootstrap root could be replaced. The check is correct, but the throw escaped syncAgentRegistry, so the whole API never listened.

- Degrade only the affected member: catch ACP construction failures, mark the cat unavailable with ACP_BOOTSTRAP_UNAVAILABLE and continue startup.
- Relocate the Windows bootstrap root to %ProgramData%\\ClowderAI\\acp-bootstrap only when the temp ancestors are rejected for unsafe replacement; the fallback keeps the same protected owner-only DACL, and a reparse point at the cwd still fails closed.
- Name the offending parent, identity and rights in the privacy error, and silence the PowerShell progress CLIXML noise.

* fix(ci): align queue, alpha and env fixtures with the merged contracts

- queue-processor: getById must stay synchronous; the reserved-id guard calls it without awaiting, so an async mock was always truthy and every admission looked like a collision.
- ACP bootstrap: only the production default root may relocate to ProgramData; injected roots (tests, isolated fixtures) keep the fail-closed reparse/unsafe-parent contract.
- env-registry: ProgramData and ALLUSERSPROFILE are OS-provided inputs for that fallback, not app settings.
- macOS alpha cleanup: F202 removed the fifth (service) port role; the fixture now allocates the four remaining roles and uses redis=ports[3].

* fix(ci): restore the audited first-run coverage and web direct deps

The main sync dropped the reviewed first-run CI surface and three direct dependencies.

- ci.yml: restore the Build-job script preflight, production first-run pages, member creation HTTP contracts and the preserved browser-evidence upload; restore the whole Test (Web First-run Onboarding) job (onboarding suite, avatar identity vitest set, rendered-reply/observer/cancellation/history/a2a browser evidence) and wire it into the Test (Public) aggregate.
- packages/web: restore zod, @types/mdast and playwright, which the merged source and browser suites still import.
- pnpm-lock.yaml: regenerate with pnpm 9.15.4; frozen install, web build, first-run onboarding (277), avatar identity (34) and first-run entry API (8) pass locally.

---------

Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
Co-authored-by: Codex61Sol-GPT-6.1-sol <codex61-sol@cat-cafe.local>
Co-authored-by: Codex61Sol-GPT-6.1-sol <glm52@cat-cafe.local>
Co-authored-by: Lysander Su <773678591@qq.com>
…s212653#1631)

* fix(codex): inject custom-model catalog to silence fallback metadata warning

Why: codex CLI logs "Model metadata for <model> not found. Defaulting to
fallback metadata" for any model missing from its built-in context-window
catalog (e.g. deepseek-flash). Setting model_context_window does NOT address
this — it only feeds compaction math. The supported silence path is
--config model_catalog_json=<file>, which has REPLACE semantics, so the
injection must be per-model gated to avoid killing builtin catalog entries.

- materializes a content-addressed catalog (/tmp cache, atomic rename)
  only for models without a builtin entry; degrades to [] on any failure
- catalog instructions copied verbatim from the CLI fallback text so
  behavior stays byte-identical (no GPT-5 template fork)
- reserves model_catalog_json so free-form cliConfigArgs cannot override
  the system-managed file (3 spellings covered)

[砚砚/deepseek-flash🐾]

* fix(codex): declare native window in custom-model catalog

Why: Codex pins context_window/max_context_window to 272_000 for models
missing from its built-in catalog, then applies
min(--config model_context_window, max_context_window). The zts212653#1381 injection
correctly passes the configured 1M window, but Codex clamped it to 272_000
and reported 258_400 usable (272_000 x 95%) — the same silent
configured-vs-applied divergence we just verified for Claude. Probe against
codex-cli 0.163.0: previous entry reported 258_400; with this entry 950_000.

An absent context_window is a hole on its own: an invocation without a
model_context_window override then reported model_context_window: null,
i.e. no window awareness at all.

- entry declares context_window = max_context_window = 1_000_000 (the model
  real native window), so min() still honours a configured smaller value
- the 95% effective headroom is left to Codex; 950_000 usable is expected
  and not a second shrink
- tests assert the fields on the typed entry AND in the serialized catalog
  file (red-verified by removing them from dist)

[宪宪/deepseek-flash🐾]

* fix(codex): join fallback instructions with a bare newline

Why: the captured template was joined with "'\n'" — quote, newline, quote —
instead of "\n". Every one of the 274 line boundaries therefore carried a
stray pair of single quotes into the request 'instructions' field, so each
deepseek-flash invocation received a system prompt with 274 artifacts. That
also broke the byte-identical-to-fallback invariant this file exists to
guarantee.

- join with '\n'; the joined text is now 20_750 chars, byte-identical to the
  fallback template extracted from the codex-cli 0.163.0 binary
- regression test asserts on the serialized catalog (what the CLI reads):
  no quote-wrapped separator, no line starting or ending with a quote, and
  the exact 20_750 length — red-verified by re-introducing the bad separator
- document the invariant and the 0.163.0 provenance in the file header
- guard the per-model gate with a "never add builtin slugs" note (review P3)

[宪宪/deepseek-flash🐾]

* fix(codex): pin fallback instructions and scope catalog to exec_json

Why: review asked for an explicit source and upgrade path for the
embedded fallback prompt, observable catalog fallback, and an honest
carrier scope. The fallback text is upstream codex-rs/models-manager/
prompt.md (rust-v0.163.0), not a bundled model template; pin its hash
and add a sync script. app_server does not receive the per-invocation
window override, so keep the catalog on exec_json until that carrier
has its own evidence.

* fix(codex): bind catalog window and template to invocation

Why: review found three correctness gaps in the catalog path: reusing a content-addressed file without checking its bytes could point the CLI at corrupt or rewritten JSON; embedding the raw fallback prompt reintroduced update_plan instructions for invocations that do not expose that tool; and a fixed 1M window promoted one member's manual setting to every same-named provider route. Verify the cache bytes with O_NOFOLLOW before reuse, port the CLI's update_plan filter when the tool is disabled, and only declare the current invocation's resolved native window (omitting it when unconfigured). The real 0.163.0 CLI reads the rebuilt 200k catalog successfully and the adapted template stays at 16,979 chars without update_plan.

[宪宪/deepseek-flash🐾]

* fix(codex): resolve update_plan from final CLI overrides

Why: review P1 found the template selector returned on the first tools.update_plan.enabled leaf, while Codex applies every accepted -c/--config assignment in order. A later duplicate leaf wins, and a later parent-table assignment replaces the whole subtree (including dropping update_plan). Reuse the launch-config dotted-path/TOML parser to resolve the final effective value, and add regressions for both duplicate-leaf orders, explicit parent-table replacement, and parent-table replacement that drops the leaf.

Verification: API build clean; codex-model-catalog 18/18; codex-agent-service + app-server-pooling + plugin-native-launch + issue-1381 + config-overrides 136/136.

[宪宪/deepseek-flash🐾]

* test(codex): bind native_tool member window to model

Why: zts212653#1519 resolves native_tool members through configurationSource/defaultModel; the catalog's invocation native window must use that same source rather than an env override.

---------

Co-authored-by: CatB783vkmo-Deepseek-flash <ming@DESKTOP-IAJ4702.localdomain>
* fix(runtime): separate capability configuration and MCP binary roots

* fix(kimi): hand off managed MCP configuration to the native client

Why: Kimi Code no longer accepts an invoke-time MCP flag, so managed collaboration tools were absent even when the persistent capability registry was correct. Preserve native configuration bytes and authentication roots while lending the approved project MCP surface for each invocation.

* fix(runtime): preserve explicit authority and Kimi configuration boundaries

Keep missing explicit registries fail-closed even when their roots coincide. Refuse native HOME aliases and restore borrowed Kimi configuration without overwriting external atomic saves. Add regression coverage for the reported boundaries.

* fix(kimi): enforce native MCP parsing and complete capability overlays

Use parser-valid denials for native HOME and Git-root MCP layers while preserving host ownership, retired names and source-relative user commands. Pin official native parser and loader fixtures with licensed provenance, add effective-config regressions, and correct the Windows-only mock PATH fixture.

---------

Co-authored-by: Codex <codex@local>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
* fix(plugins): refresh catalog on explicit reads

Why: a five-minute attempt cache could preserve CATALOG_FETCH_FAILED after the remote recovered, while a five-second page poll generated background work to compensate. Fetch catalog truth for each explicit Host read, coalesce only concurrent reads, and let page entry or user operations drive refreshes.

[砚砚/gpt-5.6-sol🐾]

* fix(plugins): preserve first-start catalog snapshot

Why: removing the catalog TTL exposed an internal re-read between first-start selection and package admission. Keep that single operation on its already-validated fresh snapshot while explicit owner installs continue to read current catalog truth and reject stale release fences.

[砚砚/gpt-5.6-sol🐾]

* fix(plugins): reuse first-start catalog snapshot

Why: first-start installation already selected exact releases from one catalog snapshot, but automatic activation re-fetched discovery once per plugin and could linearly block Host recovery while offline. Carry the operation snapshot through Manager projection while keeping local lifecycle, auth, compatibility, and revision fences live.

[砚砚/gpt-5.6-sol🐾]

* fix(web): await plugin lifecycle completion

Why: plugin enable may legitimately spend up to four minutes in Host pre-active work, but the Console abandoned the request after the default 30-second deadline and could remain stuck on an intermediate row. Give only set-enabled operations a bounded five-minute deadline, then keep the existing explicit terminal refresh for both success and failure without restoring catalog caching or idle polling.

[砚砚/gpt-5.6-sol🐾]

* fix(plugin-manager): await configuration and uninstall completion

Why: configuration restarts and graceful uninstall can outlive the default 30-second request deadline. Keep lifecycle writes attached and refresh after uncertain configuration responses without repeating mutations.

[小星星·砚砚/gpt-6-astra🐾]

---------

Co-authored-by: Lysander Su <773678591@qq.com>
Co-authored-by: CodexAstra-GPT-6-astra <glm52@cat-cafe.local>
* feat(F232): Works 内直接预览已发布的 HTML widget

用户可见的变化:
- 在 Works 里点击 html_widget 作品,右侧工作区直接渲染 HTML,
  不再跳回原消息;interactive 审批/选择卡片仍回原消息。
- 同一消息里两个同名 HTML 各有自己的卡片、打开位置和返回位置,不会串。
- 原块缺失、无权限、读取失败时显示明确提示并保留「回原消息」入口,
  不拿别的块凑数。

做法:
- 目录 DTO 仍只带定位:新增可选 widgetBlockId,由聚合器从已持久化的
  html_widget 块生成,不带正文;interactive 不带这个坐标。
- 新增 GET /api/threads/:threadId/artifacts/:messageId/blocks/:blockId,
  按坐标读回正文,并在服务端复核 thread、归属、已发布/未删除、
  block id 与 kind === 'html_widget';任一不符返回 404,不泄露存在性。
- 前端打开时按坐标取正文;复用 sanitizeWidgetHtml 与
  iframe sandbox=allow-scripts(无 same-origin、no-referrer)。
- widget 的 artifactObjectId 改为 ['widget', sourceMessageId, blockId];
  旧 objectId 只在唯一匹配时恢复,同名歧义时让用户按块 id 选择。
- F232 KD-7 更新为「已授权 HTML 原块可直接预览,旧数据仍可回原消息」。

验证:
- 新增 API 路由 8 例、widget 身份 7 例、详情预览 4 例、Works 点击 1 例、
  F307 坐标恢复/歧义 3 例;相关 18 个 web 测试文件 212 例全过。
- API/shared/web tsc 通过;biome 通过。
- 真浏览器(Chrome + Playwright,1440/390):两件同名各自打开与返回、
  iframe 内按钮真实可点、预览填满工作区(底部 12px)、
  原块缺失/无权限提示、interactive 不进预览、无未捕获异常,17 项全 PASS。

* fix(F232): 按作品目录同一口径复用 HTML 块读取权限

review round 1:
- 新路由移到 threads.ts,紧挨 GET /api/threads/:threadId/artifacts(:1608),
  直接复用同一个 resolveUserId(request, {})、threadStore.get + createdBy 403、
  以及 store 的消息可见性口径;删掉独立路由文件与 index 注册。
- 新增 isThreadMessageVisibleToViewer:与 RedisMessageStore.getByThread
  (includeQueuedCatMessages) 同一组判定(tombstone、归属/系统消息、
  managed-hold、投递状态),目录能列出的块读得到,列不出的读不到。
- 不再额外拒绝 system/briefing 行,也不再只认 message.userId === userId;
  system thread、system-user 消息、queued cat speech 与目录一致。
- 测试改为挂载 threadsRoutes:401 无身份、404 缺 thread、403 非 owner、
  system thread、system-user 消息、他人消息、删除、queued 用户工作、
  queued 猫发言、非 HTML 块、缺块、错 thread,9 例。
- 真机证据改用真实 dev:direct(5172/5173,独立 Redis 6396),
  不再使用临时 harness 页/fixture API。

---------

Co-authored-by: Lysander Su <773678591@qq.com>
…ml_widget rules (zts212653#1648)

Add one line to RICH_BLOCK_RULES (served by cat_cafe_get_rich_block_rules /
GET /api/callbacks/rich-block-rules) saying inline on* attributes such as
onclick= are stripped by sanitization, so bind events with addEventListener
inside <script>. Lock it with an assertion in callback-docs-route.test.js.

Prevention hint only; publish-time detection for zts212653#1640 is not included.

Refs zts212653#1640

Co-authored-by: Lysander Su <773678591@qq.com>
…zts212653#1652)

* fix(plugin): package local Windows plugins without npm.cmd or tar drive paths (zts212653#1650)

* fix(plugin): bound local pack copies and recheck source selection (zts212653#1650)

The Windows local-directory fix copied the whole source with recursive cp
before npm pack. That filter also removed legitimate nested node_modules
fixtures, the final dry-run only proved the stale copy agreed with itself,
and the copy was not bounded or cancellable.

- Replace cp with an incremental LocalDirectoryOperation walk that skips only
  the package root node_modules/.git, charges every member to a Budget before
  reading, rejects over-budget files, and observes cancellation per entry.
- Record a manifest of the copied view and, after the final dry-run, re-walk
  the current original directory. A new member or a changed .npmignore/
  .gitignore digest now raises DEPENDENCY_SOURCE_CHANGED instead of trusting
  the frozen copy.
- Run explicit JavaScript npm entrypoints with process.execPath, which also
  lets regression tests drive real npm through a generated shim.
- Keep the Windows npm/tar fixes. The test archive fixture now invokes tar
  with a host-owned cwd and relative operands.

Regression tests cover nested node_modules fixtures, a late published file,
an .npmignore edit during the formal pack, an ignored 65 MiB cache, and
cancellation during the bounded copy.

* fix(plugin): share pack copy budget across dependency graph (zts212653#1650)

---------

Co-authored-by: Edgar <hdjhanded@gmail.com>
Co-authored-by: Lysander Su <773678591@qq.com>
…53#1628) (zts212653#1633)

* feat(test): add cross-platform test-home wrapper (zts212653#1628)

* test: cover process-tree and resolver boundaries (zts212653#1628)

* fix(api): address test-home lifecycle and public lane review (zts212653#1628)

* test(api): isolate temporary public fixture from Redis runner preload (zts212653#1628)

---------

Co-authored-by: Edgar <hdjhanded@gmail.com>
Co-authored-by: Lysander Su <773678591@qq.com>
* fix(onboarding): start new installs with an empty member list

* fix(onboarding): restore the existing onboarding UI

Why: The operator rejected unsynchronized UI layout and naming changes in
the empty-first-run fix. Restore the pre-PR member, home and demo surfaces
while preserving explicit member enrollment and durable guide receipts.

Restore the existing entry tests and remove the withdrawn dynamic-empty
hydration test and obsolete screenshot. Record the corrected scope in the plan.

Validation: 4 expected RED failures, then 62 Web and 5 API tests passed;
Web typecheck and Biome passed; classic/v2 browser journeys passed 2/2
with synthetic HTTP boundaries. No production runtime deployment.

[砚砚/GPT-6🐾]

* fix(onboarding): retain enrollment metadata and isolate guide eligibility

Why: Unknown user-selected policy versions must not silently become legacy
catalogs, and a damaged catalog must not block independent personal guide
receipts. Retain enrollment metadata in typed config parsing and disable
automatic onboarding when catalog eligibility cannot be established.

Preserve the operator-requested UI rollback. Add coverage proving failed
roster reads do not enter automatic team setup while manual creation stays
available, and proving raw account-binding reads already retain metadata.

Validation: two observed RED failures; 175 API and 11 Web tests passed,
shared/API TypeScript builds, Biome, diff and fallback checks passed.
No runtime config, production data, or deployment changed.

[砚砚/GPT-6🐾]

* test(onboarding): align first-read coverage with empty bootstrap

Why: CI distributable-6 still expected GET /api/cats to persist a default
Codex seed, contradicting the accepted explicit-enrollment behavior.

Isolate the test registry from the CI preload, verify an empty first and
second response plus persisted enrollment policy, and restore registry state.
Production code and the operator-requested UI rollback are unchanged.

Validation: reproduced the existing route-test failure, then 18/18 route
and empty-first-run tests passed with the CI registry preload in an isolated
test HOME. Biome and diff checks passed.

[砚砚/GPT-6🐾]

---------

Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
…12653#1659)

* fix(codex): preserve native tool configuration across lifecycle

* docs(F320): record isolated Codex lifecycle verification

---------

Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
…ts212653#1658)

* fix(acp): safely bootstrap audited Windows providers on data volumes

* docs: record issue 1653 independent security review and verification

* fix(acp): run Windows bootstrap regressions in CI and handle empty stderr

Why: The win32-only bootstrap security regressions were absent from the explicit Windows CI list. A failed verifier spawn could also stringify missing stderr, hiding the verification-unavailable diagnostic.

* refactor(acp): group bootstrap helpers within the directory size limit

Why: The first PR CI run correctly rejected the ACP directory's growth from 24 to 29 modules. Group the five new bootstrap helpers, update their imports and Pi bridge location, and keep the existing size guard intact.

* fix(acp): bind bootstrap audit environments to their intended cwd

Why: CI requires every buildChildEnv caller to declare its working directory. Audit admission against the resolved project root, then use the frozen private bootstrap cwd for default cold-start rechecks. Actual spawn environments remain rechecked by both clients.

---------

Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
…zts212653#1663)

* fix(web): Windows sidebar parity - fonts, tooltips, pending decisions

Refs #92, zts212653#1544

Three improvements for Windows sidebar visual parity:

A. Unified system font token
- Define --font-sans CSS variable with system font stack
- Remove undelivered Inter reference
- Tailwind font-sans now consumes the same token
- Stack: system-ui, Segoe UI Variable, PingFang SC, Microsoft YaHei, etc.

B. Project tree tooltips
- Add AppTooltip to SectionGroup project name button
- Show full name when truncated, with optional project path in detail
- Add tooltips to action buttons (+ and ...)
- Replace native title with accessible aria-label

C. Pending decision marks for regular threads
- Extend useGroupDecisions to v2 sidebar (not just attention clusters)
- Add hasPendingDecision prop through ThreadItem → ThreadRowSignals
- Display amber dot + "等你决定"/"Waiting for you" badge
- Only show when owner-fenced decisions reader confirms the thread
- Preserves existing presence states (working/done/error)

Why: Windows visual experience lagged macOS/design. This closes
font contract gap, recovers truncated project names, and surfaces
decisions that were invisible outside attention groups.

[宪宪/opus🐾]

* fix: address P2/R1 and P2/R2 from codex review

P2/R1: Enable multiline for SectionGroup project tooltip
- Add multiline prop to AppTooltip for project name button
- Long project name + path now fully recoverable in tooltip

P2/R2: Use existing needsDecision copy and transparent style
- Replace custom waitingForYou with existing needsDecision
- Remove background color, use transparent amber dot + text
- Matches CollapsedGroupPeek visual treatment

[宪宪/opus🐾]

* fix(P2/R3): connect groupDecisions to useSidebarRowHeight

- Add groupDecisions parameter to useSidebarRowHeight
- Pass hasPendingDecision to hasThreadRowSignals in height calculation
- Update ThreadSidebar.tsx call site to pass groupDecisions
- Update test mock to include MOCK_GROUP_DECISIONS
- Decisions now included in height callback dependencies

This ensures virtual row heights update when pending decisions
change, fixing the offscreen measurement cache staleness issue.

[宪宪/opus🐾]

* fix(P2/R3): invalidate measurement cache when decisions change

Problem: VirtualAttentionList cached row heights based on row identity,
ignoring decoration changes. When pending decisions changed offscreen,
cached heights remained stale until scrolling back.

Solution:
- Add groupDecisions param to useMeasuredSidebarRows
- Clear measurement cache when decisions status or threadIds change
- Propagate groupDecisions through VirtualAttentionList
- Update all call sites and tests

This ensures offscreen rows remeasure when decisions change, fixing
the geometry staleness issue identified in R3 review.

[宪宪/opus🐾]

* fix: address Biome lint warnings

- Fix import order in VirtualAttentionList.tsx
- Simplify useEffect dependencies: use groupDecisions instead of .status and .threadIds
- Use range object instead of range.start and range.end

[宪宪/opus🐾]

* chore: fix format and remove unused variable

- Fix HeightProbe span formatting in sidebar-draft-decoration.test.tsx
- Remove unused decisionsGeneration variable
- Biome check now passes (exit 0)

[宪宪/opus🐾]

* test: add offscreen cache invalidation regression test

Add test case for pending decisions cache invalidation:
- Measures row 50 at 52px baseline
- Scrolls it offscreen
- Adds decision for thread-50
- Verifies total height updates to 5224px immediately (cache cleared)
- Scrolls back to verify row already reflects new height
- Removes decision and verifies return to 5200px

This regression test ensures R3 fix works: decisions changes
invalidate measurement cache even for offscreen rows.

[宪宪/opus🐾]

* test: fix cache invalidation test to use real measurements

Mock getBoundingClientRect to return actual heights matching getRowHeight.
Without this, JSDOM returns 0 for all heights, causing useMeasuredSidebarRows
to filter out measurements (height > 0 check), leaving the cache empty.

The test now properly:
1. Measures row 50 at 52px (enters cache)
2. Moves it offscreen
3. Changes decision (should invalidate cache)
4. Verifies total height uses new 76px, not stale 52px
5. Repeats offscreen removal to test cache invalidation again

Verified with review-probe config: test now RED when cache preservation
bug is injected, GREEN with correct implementation.

Related: PR zts212653#1663 R4 收尾清单第1项

* chore: remove unrelated prototype and lockfile changes

Remove accidental changes from initial commit:
- bootcamp-onboarding-prototype-v2.html: const vs let declaration
- pnpm-lock.yaml: glob deprecation message update

These changes are unrelated to the Windows sidebar parity fix.

* fix(test): replace globalThis any with typed ref to satisfy ESLint

Replace globalThis as any with typed ref object to fix CI build failures:
- @typescript-eslint/no-explicit-any errors at lines 195, 235, 251, 257
- Both Build and Windows CI were failing at Next lint stage

Use updateDecisionsRef with explicit type signature instead of
untyped global mutation. Functional behavior unchanged.

Verified:
- Next lint: ✔ No ESLint warnings or errors
- Normal config: 4/4 tests passed (GREEN)
- Fault config: 1/4 failed as expected (RED)

Fixes CI build errors in:
- https://github.com/zts212653/clowder-ai/actions/runs/39602619298
- https://github.com/zts212653/clowder-ai/actions/runs/39602619109

* fix(P2): project tooltip shows path for real paths regardless of truncation

Fix issue where short project names (e.g. 'demo') without truncation would not
show the full path tooltip, making it impossible to distinguish between
C:\team-a\demo and D:\team-b\demo.

Changes:
1. SectionGroup: Replace onlyWhenTruncated with conditional logic that shows
   tooltip for any real projectPath (not just when truncated)
   - Real paths: always show tooltip with name + path detail
   - Virtual/default paths: only show tooltip when truncated

2. project-display-identity.test.tsx: Fix test locator from deleted title
   attribute to data-project-path attribute
   - Add data-project-path attribute to SectionGroup button
   - Use attribute for stable test locator instead of removed title

3. Add comprehensive test coverage for the scenario: short same-name projects
   with real paths should show complete path information on hover/focus

Related: zts212653#1585 Windows project display preserves project identity
Fixes: zts212653#1663 P2 review comment

* fix(P2): real project paths show tooltip regardless of truncation + test coverage

Fix external review P2: short project names with real paths now show complete
path tooltip on hover/focus, not just when truncated.

Changes:
1. SectionGroup.tsx: Conditional onlyWhenTruncated
   - Real projectPath (non-empty, non-'default'): always show tooltip
   - Virtual/default paths: only show when truncated
   - Add data-project-path for stable test locator

2. project-display-identity.test.tsx: Fix and enhance
   - Replace deleted title attribute with data-project-path selector
   - Add test for short same-name projects with distinct paths
   - Verify AppTooltip configuration (hover/focus verified in browser)

Verified:
- All 5 tests pass (was 2 fail + 2 pass, now 5 pass)
- Test locator uses stable data-project-path attribute
- AppTooltip configured correctly for real vs virtual paths

Related: zts212653#1663 (comment)
Fixes: P2 review finding - short names unable to show path

* test(P2): clarify AppTooltip configuration test scope and jsdom limitations

The test verifies that AppTooltip is correctly configured to always show
path tooltips for real project paths (onlyWhenTruncated=false), regardless
of name truncation. This ensures C:\team-a\demo and D:\team-b\demo can be
distinguished via hover/focus.

Actual tooltip display behavior (pointer events, focus-visible detection,
portal positioning) requires browser environment and is verified via:
- Browser isolation tests with real DOM and user interactions
- Manual verification in development/staging environments

jsdom limitations prevent testing:
- Pointer event handling and warm state timing
- CSS :focus-visible pseudo-class detection
- Portal rendering with dynamic positioning
- Real browser layout and scroll measurements

Related: zts212653#1663 (comment)
Test strategy: Configuration coverage in unit tests, interaction coverage in browser tests

Co-authored-by: ClaudeCode-Opus <whutzefengxie-ops@users.noreply.github.com>

* test(P2): add real hover/focus interaction tests for short project paths

Add comprehensive interaction tests verifying that short same-name projects
(C:\team-a\demo and D:\team-b\demo) can be distinguished via hover/focus
tooltips, regardless of name truncation.

New test file: section-group-path-tooltip.test.tsx
- 6 tests covering hover/focus behavior with real SectionGroup + AppTooltip
- Uses fake timers to control APP_TOOLTIP_CONTENT_DELAY_MS (600ms)
- Verifies tooltip appears in document.body portal with correct path
- Tests Escape dismissal and virtual/default section behavior

RED/GREEN verification:
- GREEN: 6/6 pass with current fix (onlyWhenTruncated conditional)
- RED: 4/6 fail when reverting to unconditional onlyWhenTruncated=true
  * 4 hover/focus tests fail (no tooltip for untruncated real paths)
  * 2 virtual section tests pass (correctly no tooltip)

Updated project-display-identity.test.tsx:
- Removed misleading DOM-only test with incorrect coverage claims
- Kept 4 core identity/creation/remount tests (all pass)

Test coverage: 10 tests total (4 identity + 6 path tooltip behavior)

Related: zts212653#1663 (comment)
Addresses: P2 review finding - short names unable to show path

Co-authored-by: ClaudeCode-Opus <whutzefengxie-ops@users.noreply.github.com>

* style: fix Biome format (remove extra blank line)

Fix Biome format error in project-display-identity.test.tsx line 140.
Remote CI lint failure: https://github.com/zts212653/clowder-ai/actions/runs/39634209804

Co-authored-by: ClaudeCode-Opus <whutzefengxie-ops@users.noreply.github.com>

---------

Co-authored-by: ClaudeCode-Opus <whutzefengxie-ops@users.noreply.github.com>
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
zts212653#1552)

* fix(runtime): recover Windows child executions without owner manifests

Why: An explicit empty PID set is complete ownership evidence on every platform. Checking Windows first prevented startup from retiring stale children and left the sidebar permanently working. Preserve unknown liveness for nonempty PID queries and cover the startup composition.

Upstream-Issue: zts212653#1551
[砚砚/gpt-6.1-sol🐾]

* test(runtime): align Windows recovery regression with current turn model

Follow up PR zts212653#1552 after merging main. Keep lifecycle and running-index assertions, include the existing outputFence field, and record independent comparison with current main. Original fix by amazing-fish; follow-up explicitly requested by the operator.

---------

Co-authored-by: Codex-GPT-6.1-sol <1097859252@qq.com>
Co-authored-by: Lysander Su <773678591@qq.com>
Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
Why: publish the verified full source export while preserving community changes and the public installation contract.

Includes execution-detail and message-location improvements, ACP empty-response handling, request-local Works catalogue reads, original Collective result integration, and the compiled test import correction.

Validation: Linux CI, Windows Smoke and macOS Preview Lifecycle passed on 6bb5aa6. Nine original API artifacts verify seven lanes and 2,689 planned test files against the published tree.

[小星星·砚砚/gpt-6-astra🐾]
…zts212653#1675)

* fix(windows): use Node clean-path in package scripts (zts212653#1634)

* fix(windows): reject redirected clean targets (zts212653#1634)

---------

Co-authored-by: Edgar <hdjhanded@gmail.com>
Co-authored-by: Lysander Su <773678591@qq.com>
…il scrolls (zts212653#1683)

The settings shells (classic, v2, standalone) hand the plugins section a
fixed-height flex container, but SettingsContent wrapped it in a plain
content-sized div. The plugin manager's h-full section therefore resolved
against an indefinite height, grew with content, and its overflow-y-auto
detail pane never engaged; the shell's overflow-hidden clipped the rest
of the page and the detail could not be scrolled down (seen on Windows
where longer CJK font metrics push content past the fold).

Give the plugins branch wrapper flex h-full min-h-0 flex-col so the
internal scroll regions resolve against a definite box, and add a
regression test guarding the wrapper contract.
Why: all 2676 public test files can pass while runner-dependent critical path exceeds the 10-minute target. Keep coverage, provenance, isolation and real test failures blocking; retain bounded job timeouts and publish timing metrics without turning an optimization target into a functional failure.

[小太阳·砚砚/gpt-6.1-sol🐾]

Co-authored-by: Codex61Sol-GPT-6.1-sol <26771442+zts212653@users.noreply.github.com>
Why: Public Lint runs the F286 governance checker, whose fail-closed ancestry proof cannot resolve an authentic exported bootstrap from a depth-1 checkout. Fetch complete history for that job and assert the workflow contract so future CI edits cannot silently remove the proof prerequisite.

[小太阳·砚砚/gpt-5.6-sol🐾]
Thread-Context: threadId=thread_msa6s9doceszr90t catId=codex-sol

Co-authored-by: CodexSol-GPT-5.6-sol <glm52@cat-cafe.local>
…653#1679) (zts212653#1680)

Co-authored-by: Edgar <hdjhanded@gmail.com>
Co-authored-by: Lysander Su <773678591@qq.com>
…zts212653#1684)

* fix(windows): make stale-process entrypoint explicit (zts212653#1629)

* fix(windows): compare process entry by real file identity (zts212653#1629)

---------

Co-authored-by: Edgar <hdjhanded@gmail.com>
Co-authored-by: Lysander Su <773678591@qq.com>
…ts212653#1660)

* fix(mcp): sync plugin descriptors and rebind session credentials

Why: plugin lifecycle updates regenerated home and CLI configuration without reaching existing project scopes, while cold pooled resumes left external MCP wrappers reading a previous invocation file. Reuse the generic project cascade and session rebinder, preserve explicit disables and malformed files, and retain per-scope sync errors. No plugin-specific business, grants, or token-expiry policy is added.

* test(mcp): seed authoritative source in global resolve fixtures

Why: the route regression tests exercised omitted projectPath using an absent global registry, conflicting with the reviewed safety guard that refuses to treat a missing source as empty. Give routing cases a valid empty source and explicitly verify missing/corrupt sources preserve project configuration. Production behavior and guards are unchanged.

* fix(mcp): reject missing host registries and preserve sync errors

Why: plugin lifecycle cascading must not replace a missing authoritative registry with sparse state or delete surviving project descriptors. Fastify registry failures carry actionable paths and reasons in message, which the sync UI must display.

* fix(mcp): keep inventory reads separate from registry mutations

Why: the shared adapter serves both authoritative lifecycle mutations and read-only plugin inventory. Require the Host registry before mutation while allowing inventory projection of an uninitialized root without writing or cascading.

* feat(plugin-host): consume plugin configurationVariants via the 0.2.0 contract

Why: the Host must not re-implement or silently degrade contract semantics
(design section 2.4). All four consumption paths now delegate to the single
@clowder-ai/plugin-contract implementation through one consumption boundary:

- 3.1 form projection: projectConfigurationVariants() drives web draft
  switching from the contract branch resolution
- 3.2 save/readiness: manifestConfigurationReady = selected &&
  effectiveConfigurationIsValid, so an invalid variant blocks enable
- 3.3 startup projection + module settings: two-phase resolveVariant ->
  effectiveConfiguration; unselected/invalid variants fail closed before any
  store read; inactive-branch fields are never read into the runtime
- 3.4 declared MCP launch env: same two-phase resolution; required
  bindings missing from the effective configuration refuse the launch

Also admits contractVersion 0.2.0 packages (host-inventory allowlist) and
vendors the 0.2.0 contract tarball for the api package.

Tests: 12 unit (projection/settings/readiness) + 3 end-to-end (feishu-shaped
install -> configure -> enable -> MCP launch env) + 86 regression across
seven existing plugin-manager/configuration suites, all green.

[kimi/k3🐾]

(cherry picked from commit 74afc9c)

* fix(plugin-host): complete configurationVariants consumption per review round 3

Why: astra's review of 74afc9c rejected the delivery with three
findings — string storage never crossed into the contract's typed
semantics (legal boolean config stayed incomplete), the web form kept
two legacy behaviors (implicit first-option select, masked-secret
condition compared against the mask), and the vendored contract tarball
disagreed with the feishu shrinkwrap's pinned bytes.

- web: variantDraftValues now excludes masked secrets, never implicitly
  selects the first option, and runs drafts through the contract's
  coerceStoredValues so requiredWhen compares typed values; fieldRequired
  falls back to the server's requiredNow when the condition references a
  stored secret; renderedFieldValue/configurationUpdates take explicit
  variantMode so legacy (non-variant) rendering is untouched
- vendor: contract tarball refreshed to the canonical pack
  (sha512 j44E4U/PLLNbiAh0/...), identical bytes to the feishu
  shrinkwrap after clowder-ai-plugins-config-variants 8aa1a87
- tests: astra's three reproductions (astra-variants-review.test.tsx)
  pass and join the regression suite; new variants-mode-switch-save
  covers the positive path — switching branches renders the right
  fields and save payloads include/omit the branch token correctly

[kimi/k3🐾]

(cherry picked from commit e6ddf22)

* fix(config-variants): unified publish artifact, unselected select state, deletion draft semantics

Why (astra round-4 review):
- P1 artifact chain: vendored plugin-contract tgz and pnpm-lock integrity
  now carry the official pack-publish-artifact.mjs bytes (npm pack),
  matching the feishu shrinkwrap pin; api regression 101/101 green on
  the swapped artifact.
- P2 unselected discriminator: variant-mode select renders an explicit
  "请选择" placeholder instead of the browser falling back to the first
  option, so the visible state equals the validated state.
- P2 cleared draft: an empty draft is an explicit deletion in
  variantDraftValues (matching configurationUpdates), so stale stored
  values no longer keep conditions/requiredness alive after clearing.
- Commits astra's review reproductions (4 tests, all green) as
  regression coverage alongside the existing switch/save acceptance.

[kimi/k3🐾]

(cherry picked from commit bc9f8ae)

* fix(config-variants): validate against the normalized variant projection

Why: review round 5 (astra) found the save-time validation still consumed
the legacy effectiveFieldValue path with its implicit first-option
fallback, so an unchosen mode passed validation and a cleared conditional
ignored the declared default. Display, requiredness and save validation
now share one pipeline: drafts overlay stored values, an empty draft is
an explicit deletion (the declared default then re-applies via the
contract), and coerceStoredValues produces the typed values both
requiredness and the emptiness check consume. Includes the reviewer's
regression reproductions (5 cases, previously 2 red).

[kimi/k3🐾]

(cherry picked from commit 2ce05b1)

* fix: treat an unedited stored secret as configured in variant save validation

Why: astra's review found a regression — when a required secret was already
saved and the page only projected the mask, the new normalized-path
validation read the absent mask as 'no value' and blocked saving any other
field (feishu appSecret affected). Existence is now judged from
currentValue for unedited secrets: the mask still never participates in
condition comparison or write-back, and an empty draft remains an explicit
deletion that re-judges requiredness. Adds the modified-secret case so
unset/stored/modified/deleted are all covered.

[kimi/k3🐾]

(cherry picked from commit dcc267b)

* fix(plugins): refresh declared MCP launch configuration in place

Why: enabled configuration saves refreshed only the runtime hook, leaving declaration-derived MCP environments and native launch snapshots stale. Reproject through the existing registry mutation and project synchronization path while retaining action tokens and explicit blocks. Cover both branch directions and restoration from stored inactive credentials.
(cherry picked from commit cc5d73d)

* fix(plugins): align contract archive metadata and compatibility guards

Why: Host consumes the vendored 0.2.0 contract, but runtime metadata and the archive integrity guard still pinned beta.37. Pin the shipped 0.2.0 artifact and retain beta.37 as an explicitly supported historical manifest line.
(cherry picked from commit 95e3663)

* fix(plugins): admit supported contract ranges independently of SDK releases

Why: exact historical release lists reject compatible protocol declarations and misclassify persisted plugins when the Host consumes a newer contract package. Share a bounded semver policy between admission and restore, retain declared requirements and grant authority, and preserve explicit breaking-range exclusions.

* test(plugins): type configuration variant fixtures for production lint

Why: these existing PR1660 regression fixtures pass Vitest but their explicit any casts fail Next production lint on both Linux and Windows. Use the real projected field type and typed React globals while preserving the test interactions.

* test(plugins): align catalog installation with supported contract ranges

Why: Windows and public CI still treated beta.14 as unlisted after range admission intentionally made it compatible. Keep that archive as a real positive install and quarantine below-floor, newer prerelease and newer stable declarations without inventory or grant writes.

* build(plugins): vendor the canonical contract 0.2.0 archive

Why: align the Host vendor, lockfile integrity and archive guard with the reviewed fixed-toolchain contract artifact. All 250 tar members and the complete decompressed tar stream remain byte-identical; only gzip encoding differs.

Source: clowder-ai-plugins 3a78912095e048934f6e1a801d7e8b47e1243409. Canonical SHA256: 9f8d97bc63647301036cb7b1f37310332cc02b20879352d37fe9c5217bf9c739.

* fix(plugins): consume variant URI and scalar validation safely

Why: contract 0.2.0 now emits standard URI constraints and excludes operation controls from scalar readiness. Register ajv-formats while preserving secrets verbatim, and verify persisted URL, operation target, and whitespace readiness through the real Host configuration service.

Consume the feature artifact from clowder-ai-plugins@b7f8ce5cecc63e778ca83819850acddbb8270149. Use a digest-qualified vendor filename because a same-name local tgz remained stale after a successful frozen install. This is a candidate integration, not publication or runtime acceptance.

* diag(plugins): identify native action authentication refusal layers

Why: native MCP clients report only HTTP 401, hiding whether callback credentials, current invocation, or the activation connection was rejected. Correlate fixed stage/reason diagnostics by request without logging tokens, headers, inputs, or package exceptions; leave all authentication behavior unchanged.
* feat(agent-session): session contract types, bridge and registry

Add an internal (unstable) agent session contract under
session-contract/: session/turn/event types, a bridge that adapts a
session provider to the existing AgentService.invoke path, event
projection, an active-run dispatcher, and a registry keyed by
builtin or plugin:<pluginId>/<contributionId> refs. Not wired into the
Host in this commit.

Refs zts212653#1647

* feat(agent-session): plugin-declared ACP session provider

Let a plugin package declare an ACP agent in a data-only
agent-provider.json; the Host validates it, registers it in the session
implementation registry on activation, unregisters and releases sessions
on deactivation, and runs it through its own ACP transport via
AcpSessionProvider. Cats opt in through CAT_CAFE_AGENT_SESSION_BINDINGS.

CAT_CAFE_AGENT_SESSION_CONTRACT defaults to plugin; unbound cats keep the
existing service selection (covered by service-selection.test.js).
Set it to off to disable the path entirely.

Refs zts212653#1647

* test(agent-session): independent acceptance tests for the session contract

Black-box acceptance suites written from the interface agreement by a
separate author who did not read the implementation:
agent-session-contract-smoke/ (contract types, bridge, registry,
dispatcher) and agent-session-contract-smoke-1b/ (declaration, settings,
registered service, ACP session provider).

Refs zts212653#1647

* fix(agent-session): 在桥接日志中保留成员标识

Refs zts212653#1647

真实 Pino 入口会忽略字符串后的对象字段,改用结构化参数顺序并覆盖成员标识和凭据不入日志。

* fix(agent-session): 补全插件声明生命周期日志并记录取消广播来源

Refs zts212653#1647

复用现有声明加载与停用路径,记录登记、注销和拒绝原因。用真实 ACP 子进程对照内置与桥接路径,证明取消双 done 来自既有传输清理和路由收尾,本轮不改旧行为。

* fix(acp): 支持唯一的原生模型短名并补 OpenCode 回执测试

Refs zts212653#1647

精确值优先;短模型名只映射到唯一的已公布原始值,歧义仍拒绝。用隔离 OpenCode 1.19.0 实际 configOptions 覆盖解析、配置回执和原生 ACP prompt 链路。

* test(agent-session): 用行为说明替代私有约定引用并按功能命名测试

* test(agent-session): 删除以源码字串代替行为验证的厂商检查

* fix(agent-session): 保留 ACP 系统事件正文和遥测语义

避免插件接入把思考、容量告警和遥测统一降为 status,沿用调用层已有的投递与用量处理。补真实 ACP transformer 经桥接到调用出口的回归。

* fix(agent-session): 保留原生绑定和工具事实,避免重复消费用量

让 ACP 插件路径沿用原有会话续接校验与工具失败状态;将消息用量从会话缓存中分离。用真实调用层、会话记录、工具 span 和 transcript 对照原生消费结果。

---------

Co-authored-by: Lysander Su <773678591@qq.com>
…1696)

Why: isolated OAuth launches disable parent environment inheritance, so discarding the configured proxy breaks Google connectivity on proxy-dependent networks. Preserve only the standard proxy keys while keeping account credentials and host authority isolated.

[砚砚/gpt-6-astra🐾]

Co-authored-by: CatXooblf7l-GPT-6-astra <yuki@YukideMacBook-Pro.local>
…s212653#1558)

Why: startup recovery can interrupt a child without writing a transcript
terminal, leaving history and detail stuck at running after actual completion.
Use one shared identity-fenced resolver for both summaries, preserving the
original transcript evidence and bounding ledger reads to the response page.

Upstream-Issue: zts212653#1556

[砚砚/gpt-6.1-sol🐾]

Co-authored-by: Codex-GPT-6.1-sol <1097859252@qq.com>
Co-authored-by: Codex61Sol-GPT-6.1-sol <glm52@cat-cafe.local>
…ts212653#1626)

* fix(claude): inject member context window into third-party CLI runs

Why: Claude CLI only knows native Anthropic model names; for glm-5.3-flash
it falls back to a 200k window. With ~175k tokens of fixed MCP tool schema
re-sent every turn, only ~25k remained for conversation, so auto-compact
refilled immediately and thrashed 3 times in a row (invocation
e9e09539-b4e9-4adb-9453-b01ea5d7594e, 2026-10-19).

The runtime already declares a 1M window for this member, but the provider
layer never passed it to the CLI. Forward the raw/native member window as
CLAUDE_CODE_MAX_CONTEXT_TOKENS for non-claude-* models in api_key mode.
zts212653#1381 semantics: prefer contextNativeWindowTokens; explicit null suppresses
injection; undefined falls back to the effective capacity for legacy
callers. Native Anthropic models are untouched — the CLI owns their windows.

Verified against Claude CLI 2.1.302: an unknown model reports
contextWindow=200000 by default and 1000000 with the env var set.
Tests: 4 new cases, 133 Claude carrier tests, 17 SDK/account tests.

[宪宪/deepseek-flash🐾]

* fix(claude): keep custom-model native windows independent of session capacity

Why: effective or session-pinned capacity is a downstream observation and must never become the next native window. Restrict automatic injection to positive integer member values for plain custom model IDs, preserve native and tagged CLI behavior, and cover SDK, background, and PTY handoffs.

Validation: two new regressions observed failing before the fix; new source contracts 3/3, carrier regressions 165/165, SDK/account tests 20/20 after restoring the CLI resolver PATH precondition, API build, formatter and diff checks pass. Isolated Claude Code 2.1.308 fake-gateway runs report 200k baseline, 1M configured, and 1M on resume.

---------

Co-authored-by: CatE1fvlxn8-Deepseek-flash <ming@DESKTOP-IAJ4702.localdomain>
Co-authored-by: Lysander Su <773678591@qq.com>
Co-authored-by: Codex61Sol-GPT-6.1-sol <codex61-sol@cat-cafe.local>
…ts212653#1641)

* fix(runtime): use stable process birth identity across clock jumps

Why: ps lstart follows the wall clock. After a host suspend/resume clock
jump, the managed runtime was refused with process-identity-mismatch even
though the daemon was unchanged. Linux exposes a stable birth marker
(/proc/<pid>/stat starttime + boot_id); record and compare it, keep ps
lstart as the cross-platform fallback, and let a per-launch token prove a
legacy token-bound incarnation without trusting lstart.

Tests: check:daemon-lifecycle 241/241.

* fix(runtime): keep ambiguous clock-shift stops unresolved

Why: wall-clock lstart cannot prove a still-running pre-marker daemon was replaced when argv becomes unreadable. Preserve its state until exit is observed, require a complete boot-relative marker, and isolate Linux birth collection from process lifecycle decisions.

Validation: observed three failing regressions before the fix; all 245 daemon lifecycle checks now pass. Formatter checks pass for all eight source files.

* fix(runtime): include birth identity in isolated script copies

Why: process-identity now imports the stable birth helper. Explicit runtime fixtures and frozen gate snapshots must copy that dependency too, or startup fails with ERR_MODULE_NOT_FOUND before lifecycle safety checks can run. Cover all six copy manifests; the affected runtime and macOS preview suites pass 86/86.

---------

Co-authored-by: CatE1fvlxn8-Deepseek-flash <ming@DESKTOP-IAJ4702.localdomain>
Co-authored-by: Lysander Su <773678591@qq.com>
Co-authored-by: Codex61Sol-GPT-6.1-sol <codex61-sol@cat-cafe.local>
EdgarR1170 and others added 29 commits October 22, 2026 08:47
…12653#1625) (zts212653#1692)

* fix(windows): make plugin native Codex symlink EPERM actionable (zts212653#1625)

* test(api): run native auth diagnostic in hosted CI (zts212653#1625)

---------

Co-authored-by: Edgar <hdjhanded@gmail.com>
Co-authored-by: Lysander Su <773678591@qq.com>
Co-authored-by: Codex61Sol-GPT-6.1-sol <26771442+zts212653@users.noreply.github.com>
* fix(plugins): load local state before remote discovery

Why: opening Plugin Manager and operating installed plugins waited on GitHub catalog I/O, while packaged Electron downloads bypassed the system proxy stack used by the browser. Project local inventory first, hydrate discovery asynchronously, and route only canonical catalog/npm resources through a bounded authenticated Electron bridge.

Why not split: the API local projection, Web hydration order, and desktop transport form one user-visible availability contract; landing any piece alone preserves either the blocking UI or the unusable packaged download path.

[砚砚/gpt-5.6-sol🐾]

* fix(plugins): close local-first review gaps

Why: local-first plugin management must not bypass live auth/config policy, remain busy on remote hydration, crash on bodyless bridge responses, or leave Electron fetches alive after their owner disconnects. Preserve zero-cache remote discovery while making local operations and bridge ownership complete.

[砚砚/gpt-5.6-sol🐾]

* fix(desktop): release rejected plugin downloads

Why: the loopback bridge rejected oversized declared bodies without cancelling the upstream response or aborting its request owner, leaving work beyond the bridge lifecycle. Make every non-consumed response path release both resources while preserving completed transfers.

[砚砚/gpt-5.6-sol🐾]

* fix(plugins): show bundled candidates before discovery

Why: the local-first endpoint only projected installed inventory, so Host-bundled candidates stayed invisible until the remote catalog timed out and returned its degraded bundle. Expose a no-I/O Host catalog snapshot through the existing adapters so built-ins render immediately while remote discovery remains incremental.

[砚砚/gpt-5.6-sol🐾]

* fix(plugins): preserve local-first network semantics

Why: cloud review found that the desktop proxy converted retryable transport failures into terminal HTTP responses, canonical catalog hydration displaced installed-plugin local detail reads, and the internal local projection routes occupied a valid plugin ID. Preserve transport failure identity, retain local membership through remote enrichment, and move the private projection below an invalid plugin-ID segment.

[砚砚/gpt-5.6-sol🐾]

* test(desktop): lock partial proxy stream failures

Why: review reproduced an upstream body that emits partial bytes before resetting. The bridge fix already destroys that response, but the regression suite only covered failures before headers; preserve the no-success invariant across both transport phases.

[砚砚/gpt-5.6-sol🐾]

* fix(web): retain local plugin documentation

Why: local-first detail reads correctly avoid remote catalog discovery, but the same flag also suppressed README assets and active tool projections that already come from the installed package and Host runtime. Keep the local detail source while loading those independent local resources.

[砚砚/gpt-5.6-sol🐾]

* fix(plugins): preserve local identity across searches

Why: filtered local search results replaced the component's knowledge of which installed plugins can be read without remote discovery, while a fresh local catalog bootstrap was mislabeled as stale. Preserve locally observed IDs across query projections and report the local bootstrap as loading without changing remote failure semantics.

[砚砚/gpt-5.6-sol🐾]

* fix(plugins): reconcile local detail identity

Why: filtered local searches must not erase installed detail routing, but a monotonically growing hint survives uninstall and misroutes marketplace candidates back to a missing local detail. Reconcile identity from the unfiltered local inventory and use it consistently for selection, list refresh, and operation refresh.

[砚砚/gpt-5.6-sol🐾]
* docs(acp): document native DSH custom provider configuration

Why: DSH ACP defaults can select the official route even when a custom provider works in another profile. Document the configuration fix and real native/main continuation evidence without widening Host behavior.

Authored-by: Codex (GPT-6)

* docs(acp): keep local verification evidence out of product plans

Why: Maintainer feedback asks to retain generic DSH configuration guidance upstream while keeping machine-specific kitcoding evidence in the PR verification record. Preserve the local report separately and remove its product-plan link.

Authored-by: Codex (GPT-6)

* docs(acp): explain home and launch overlay precedence

Why: Higher-priority home and ordered launch overlays can replace ACP choices and complete provider configs even when the profile patch is correct. Document the actual composition order and verify four credential-free dump-config scenarios.

Authored-by: Codex (GPT-6)

---------

Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
…s212653#1505)

* 按后端契约展示功能开关可编辑状态与保存错误 (#25)

Refs #24

Extract installed source changes onto current fork main for individual review.

Co-authored-by: jiao-ling <1097859252@qq.com>

* test(memory): isolate settings proof and use Web browser dependency

Why: preserve the exact settings-write assertions without shared-shell live socket registration, and run the same real Settings proof in public installs using the existing Web Playwright dependency.

---------

Co-authored-by: jiao-ling <1097859252@qq.com>
Co-authored-by: Codex61Sol-GPT-6.1-sol <26771442+zts212653@users.noreply.github.com>
…zts212653#1698)

* fix(plugins): bind MCP activation credentials from the current Host

Why: project MCP projections retain activation tokens from an earlier Host process. A fresh wrapper can therefore pass invocation authentication but fail with inactive_connection. Bind only Host-owned connection credentials at invocation assembly, preserving project policy and overrides without modifying persisted state or bypassing authentication.

* test(plugins): isolate the authoritative Host root in replacement probe

Why: the upstream replacement probe must declare its isolated capabilities file as Host authority rather than depend on the developer workspace registry.

* fix(plugins): keep activation credentials with Host-owned transport

Why: binding only fresh credentials to a project-selected command could refresh authority for a tampered transport. Require unique matching plugin ownership and transport, reject overrides, and take the complete launch environment from the Host while preserving project access policy.

* fix(plugins): keep MCP activations in the Host runtime registry

Why: activation credentials are runtime state, not durable project configuration. Ambient and native-policy launches must share the verified in-memory launch snapshot. Persist only discovery and project access policy; never reload activation credentials from Host or project files.

* test(plugins): provide the wrapper probe through the live Host port

Why: the replacement credential probe must obtain its plugin launch from in-memory Host authority, while its durable capabilities entry contains no activation token.

* fix(plugins): unify Host-lifetime MCP connection ownership

Why: runtime connection lookup must use the Host binary root rather than the persistent policy root. Activation credentials belong to one Host lifetime and must remain stable across enable/disable. Persisted plugin transport/env is no longer consumed; verified live launch bytes and existing project access policy are the only inputs.

* test(plugins): accept absent environments on disabled launches

Why: disabled plugin projections contain no persisted launch environment at all; the negative assertion must verify absent credentials without assuming an env object.

* fix(plugins): bind live MCP authority to the executable Host root

Why: persistent configuration may live outside the runtime checkout. Provider launches and production composition must identify the same Host without treating the workspace policy root as credential authority.

* test(plugins): bind the upstream wrapper fixture to its executable Host

Why: the provider looks up the live Host by binary identity even when capability policy lives in a different persistent workspace.

* fix(plugins): resolve the default MCP Host root from its executable module

Why: a normal API launch runs from packages/api without a runtime-root override. Using that cwd registered live plugin authority under a different root than provider MCP discovery, dropping enabled plugin tools before handshake. Exercise real composition and standard MCP initialize/tools-list from that exact startup shape.

* fix(plugins): connect provider launches directly to the Host plugin manager

Why: the single Host process already owns its plugin registry. A filesystem key is not credential authority and made ordinary package-directory startup lose enabled MCP tools. Remove directory selection rather than layering another path fallback; keep canonical launch provenance and project access policy unchanged.

* test(plugins): assert runtime credentials through live launch authority

Why: the old installed-contribution tests expected persisted activation tokens and per-enable rotation. Keep the real action, disable, blocked-project and package-update checks, require no durable credentials, and assert the reviewed Host-lifetime connection semantics.

* fix(plugins): register runtime credentials as standard MCP env references

Why: copied project activation tokens drifted from the Host and required plugin-specific provider lookups. Publish stable per-connection process environment variables from the manager and persist only standard references. Generic launch expansion handles all local MCP adapters, including ACP, while legacy project copies inherit registered references without writes.

* fix(acp): tolerate omitted environment in existing MCP registrations

Why: CI caught an existing valid MCP descriptor without env throwing before session/new. Use an empty mapping for generic expansion while retaining callback injection and session credential-file semantics.

* fix(acp): preserve file-only credentials for native MCPs

Why: native-action MCP materialization injected raw invocation credentials in AGY file-only sessions because the final filter only matched cat-cafe server names. Apply the same existing file-only contract to native-action transports and cover fresh sessions plus credential-file refresh on resume.

* fix(mcp): reject unreadable capability entry shapes

Why: invocation-time environment overlay bypassed the existing reader entry-shape validation, so a null/scalar project entry threw instead of retaining the established unreadable-config fallback. Match the existing plain-object contract for both project and global reads without rewriting files or tightening valid legacy configuration.
…ts212653#1700)

* fix(windows): run API dev through a Node supervisor (zts212653#1634)

* test(api): follow dev supervisor args in isolation check (zts212653#1634)

* fix(api): resolve dev supervisor aliases and backoff signals (zts212653#1634)

---------

Co-authored-by: Edgar <hdjhanded@gmail.com>
Co-authored-by: Lysander Su <773678591@qq.com>
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
…zts212653#1701)

* fix(desktop): recover transient project junction readiness failures

* test(desktop): decouple consumer diagnostics from short readiness deadlines

* fix(desktop): propagate profile cancellation through mirror recovery

* fix(ci): select latest public test attempt without losing evidence

* fix(desktop): preserve complete project mirror startup diagnostics

* docs(desktop): support PowerShell 5.1 identity inspection

* fix(desktop): materialize critical Windows resources without junctions

* fix(desktop): keep interrupted backup cleanup outside recovery slots

* fix(desktop): pair API binary root with persistent workspace mapping

* fix(desktop): enforce isolated workspace and profile physical resources

* fix(desktop): expand real source symlinks in startup profiles

* test(desktop): isolate default workspace from inherited environment

* test(desktop): decouple profile deadlines from repository size

---------

Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
Co-authored-by: Lysander Su <773678591@qq.com>
* docs: 规划内置 Pi 冷恢复与首轮空响应修复

说明推荐路线、状态契约、实施步骤及验收边界;本轮仅提交方案文档,等待用户审阅。

作者:Codex

* fix(pi): 持久化原生会话并修复首轮输出丢失

让内置桥精确恢复同一 Pi 历史,使用原生进程生命周期写者锁与当前 MCP 凭据。保留恢复失败绑定和空响应错误语义,复用 PR #14 的空 delta 防护意图。

验证:103 项定向检查中 102 通过、1 项条件跳过;真实 Pi、自定义 LLM 和 MCP 冷恢复通过。全仓检查受已复现的 Windows F290 基线失败影响。

作者:Codex

* fix(pi): 拒绝损坏历史并屏蔽跨行 PEM 诊断

* fix(pi): 按原生 LF 边界校验恢复文件

* docs(pi): 记录最终验证与独立审查回执

* fix(pi): 等待旧写者退役并统一错误脱敏

* refactor(acp): 将退役交接归入生命周期目录

---------

Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
…tion cards (zts212653#1605)

* feat(acp): carry iCode agents through a dialect, HTTP member gateway and question cards

Why: F306 needs the iCode (Chrys) ACP agent to serve as a full cat carrier: session
dialect parity, cat-cafe tool access, and native human-in-the-loop requests. All three
must land on the existing clowder contracts (ACP provider, member MCP registry,
RuntimeInteractionPort) instead of a parallel runtime path.

Phase A - iCode dialect on the ACP provider:
- AcpClient: session/set_model, session/close, per-session JSON-RPC request handler
  for _chrys/request_input, fail-closed permission default.
- AcpAgentService: protocolAdapter='icode' with fail-loud model switch and per-turn
  session/close so every turn can re-apply session config.
- Factory/config/pool wiring for protocolAdapter + modelProfileId; icode+httpstream
  is rejected (stdin/stdout only), pool signature includes the dialect.
- Event transformer: iCode tool content arrays, rawInput/rawOutput and plan entries.

Phase B - member MCP gateway (HTTP) for iCode tool access:
- mcp-server member-gateway: stateless Streamable HTTP MCP endpoint authenticated
  strictly by x-invocation-id + x-callback-token headers against the invocation
  registry; resolves the cat's tool families and runs them inside the existing
  invocation credential scope.
- api member-mcp route resolves tool families from the member's acp variant config
  (mcpSupport + mcpWhitelist + capabilities disablement).
- ACP session env injects a cat-cafe-member http overlay on session/new and
  session/load with fresh per-turn credentials; non-cat-cafe stdio servers are
  dropped with a warning instead of failing the turn.

Phase C - iCode ask-user bridged to runtime-interaction question cards:
- New acp-runtime-interaction-adapter maps _chrys/request_input to kind 'question'
  requests and maps port answers / cancel / skip / abort back to the wire response.
- Shared question schema gains multiSelect + allowUnanswered (optional, additive);
  empty answer arrays are only accepted when allowUnanswered is true.
- Web question form: checkbox multi-select, free-text 'other', optional answers.
- A turn ending with pending questions invalidates the interaction
  (provider_cancelled) so stale cards never outlive the session.

Validation: targeted suites green (acp-icode-adapter 15, acp-runtime-interaction-
adapter 5, member-gateway 9, member-mcp-route 5, question extension 6, web question
form 6; full ACP 322/332 with the 10 pre-existing Windows env failures verified on
base). api + web tsc clean; pnpm frozen-lockfile passes. Live E2E on the dev
instance: multi-mention relay 布偶猫 -> 暹罗猫 through the gateway; native ask_user
-> card -> operator answer -> final reply.

[缅因猫(Maine Coon)·iCode🐾]

* fix(acp): bind member gateway tool context per invocation

Why: the member MCP gateway runs cat-cafe tool handlers inside the API process,
where the host env carries no member identity and often no CAT_CAFE_API_URL.
Handlers that read those values from process.env therefore called the wrong
instance (any deployment not on the default port) or failed outright (identity
required, e.g. game actions), silently diverging from the stdio carrier whose
per-turn launch env always supplied them.

- invocation-auth: InvocationCredentialValues carries the verified member
  identity (catId/userId/threadId) and resolveInvocationEnv() resolves
  scoped-first with the launcher env as fallback, so stdio children keep
  reading their launch env unchanged (pinned by test).
- member-gateway: the full verified context enters the ALS scope, and family
  registration now runs inside the scope so registration-time principal/schema
  resolution sees the verified invocation and registration failures land in the
  existing 500 path instead of escaping after reply.hijack.
- member-image-tools: the nested scope entry spreads the inherited credentials
  so apiUrl/identity survive (publish_image no longer loses the gateway's
  callback target).
- 17 tool modules switch base-URL/identity reads to call-time
  resolveInvocationEnv() (no module-level env snapshots remain in src).

Validation: mcp-server build + targeted suites green (gateway 13/13 incl. the
new env-decoy scope test; new invocation-auth-scope 3/3; 15 swept-module suites
131/131); api tsc clean; api member-mcp-route 5/5. Resolves review findings
gateway.invocation-env.identity-and-baseurl (P1) and
gateway.credential-scope.nested-loss (P2).

[缅因猫(Maine Coon)·iCode🐾]

* fix(acp): rebind the iCode bridge across retry, guard dead agent pipes

Why: review round 3 escalated the zts212653#1091 zero-event retry path to a merge
blocker: the replacement session never re-registered `_chrys/request_input`,
so ask_user failed with -32603 on retry turns, the replaced session's handler
lingered in the pooled client, and its live instance was never closed (leaving
the next session/load unable to re-inject the per-turn overlay). The bridge
response writer also wrote to a possibly dead agent stdin without a guard
(EPIPE / ERR_STREAM_DESTROYED would surface as an uncaught exception).

- AcpAgentService: on the retry path, rebind the request_input bridge to the
  replacement session, clear the replaced session's handler, and best-effort
  close the replaced iCode instance before re-prompting.
- acp-runtime-interaction-adapter: the bridge now exposes setProviderSessionId
  so questions minted after the rebind carry the replacement session id.
- AcpClient: bridge responses go through writeAgentResponse(), which warns and
  drops instead of writing to a destroyed pipe.
- Wire test/runtime-interaction-question-extension.test.ts into
  test:runtime-interaction and the F306 registration guard's REQUIRED_TESTS
  (the shared-contract suite previously had no runner).
- acp-icode-adapter.test.js: regression for the retry rebind (handler on the
  replacement session, old key cleared, both instances closed, bridge threadId
  follows the replacement session).

Validation: api tsc clean; focused suites green (acp-icode-adapter incl. the
new retry case, acp-client, acp-runtime-interaction-adapter, question extension,
registration guard: 69/69). Resolves review findings
icode.request-handler.retry-sessionid (P1), acp.stdin-write.unprotected-epipe
(P2, guard) and test.runtime-interaction-question-extension.not-in-runner
(P2, wiring).

[缅因猫(Maine Coon)·iCode🐾]

* fix(F306): close member-gateway policy and question-outcome gaps

Address the three inline P1 findings on the current review revision:

- Invocation-bound scopes (member gateway and native-turn tool calls) are
  invocation-only: ambient CAT_CAFE_AGENT_KEY_* material is never resolved,
  and forceAgentKey operations fail closed instead of dispatching under the
  API host's persistent identity.
- Project the canonical durable tool policy onto an exact gateway allowlist.
  read_only denies every tool (not an MCP readonly profile), callback_allowlist
  cannot be represented and fails closed, and the collective modes expose only
  their canonical sets. Tools are filtered before registration, so denied
  tools/call requests never reach the callback API.
- Keep confirmation_unavailable, transport_lost and host_restarted as
  provider-wire errors instead of fabricating an iCode cancellation. Genuine
  user/provider cancellation and lifecycle withdrawal/expiry still map to
  {cancelled:true}.

Regression coverage: gateway host-key reproduction, read_only and
callback_allowlist negative tools/list + tools/call, exact allowlist
registration, and a real RuntimeInteractionService + bridge removed-card test.

Verification: API tsc and mcp-server tsc clean; Biome clean on changed files;
API ACP/route/bridge suites 111/111; mcp-server gateway/auth-scope/registration
55/55; web question form 7/7.

[缅因猫(Maine Coon)·iCode🐾]

* fix(F306): restore route import order for the member gateway

Move mediaRoutes above member-mcp in packages/api/src/index.ts, the single assist/source/organizeImports diagnostic reported on 2a54669. Both imports remain.

[缅因猫(Maine Coon)·iCode🐾]

* fix(F306): regenerate MCP surface baseline after main merge

The merge with main (zts212653#1487/zts212653#1630) combined this branch's tool-module
environment changes with main's tool surface, so the committed
implementation digests no longer described the merged sources.

The regenerated baseline changes only protectedImplementationDigest
(123 entries). Tool names, descriptions, input schemas, annotations,
runtime profiles and schema delivery are unchanged. It was generated
from an LF checkout so the digests match the Linux CI hashing, and
tool-governance-cli check passes on that tree.

[缅因猫(Maine Coon)·iCode🐾]

* docs(acp): declare the supported iCode/Chrys version range

Supported carrier versions: iCode/Chrys 0.29.2, 0.30.0 and 0.30.1+
(>= 0.29.2) on ACP protocol version 1. The wire shapes pinned by this
suite were captured against the 0.29.2 ACP bridge; later supported
versions expose the same methods and events.

[缅因猫(Maine Coon)·iCode]

* feat(F306): add downgrade recovery for question multiSelect/allowUnanswered

Why: the pre-Phase-C host reads stored question requests with a strict
schema that rejects the new optional fields. Optional fields do not make
pending or retained terminal/history records readable after a rollback,
and settling pending cards alone leaves the stored request untouched.

- New offline command downgrade:runtime-interaction (dry-run by default):
  scans runtime-interaction detail hashes, invalidates staged/pending
  question cards carrying the new fields (host_restarted + pending/active/
  invocation index cleanup), then rewrites every affected request into the
  frozen pre-Phase-C shape. Terminal/history records are rewritten without
  changing their status or terminal.
- Writes are ordered settle -> rewrite, so an interrupted run is
  idempotently recoverable; unrelated records stay byte-identical.
- The frozen legacyRuntimeQuestionRequestSchema is the downgrade target;
  records that still fail it are reported and left untouched.
- Regression suite covers dry-run, pending+history rewrite, base-reader
  accept/reject, idempotent replay, malformed/renamed records, and the
  current store normalizer; wired into test:runtime-interaction and the
  F306 registration guard.

[缅因猫(Maine Coon)·iCode]

* fix(F306): keep the ACP directory under the ADR-010 error threshold

Move the iCode _chrys/request_input bridge into
providers/acp/icode/runtime-interaction-adapter.ts. The ACP directory had
reached 25 .ts files, which trips scripts/check-dir-size.sh (error >= 25)
and failed both the Lint and Directory Size Guard required checks on the
updated head.

The parent ACP directory stays at 24 files (warning threshold 15); the
remaining tool-projection/native-config split is pre-existing debt, not
introduced here. Imports in AcpAgentService and the adapter test follow the
new path.

[缅因猫(Maine Coon)·iCode]

* fix(F306): make downgrade settlement atomic and recoverable

Why: settlement wrote status=invalidated first and then separately wrote
terminal/revision and removed the pending/active/invocation indexes. An
interruption after the first write left a record that the next run saw as
invalidated (settle skipped) and stripped, so a later run could not repair
the stale indexes or missing terminal. This blocked the retained-record
recovery condition.

- Commit settlement, index cleanup and the request rewrite in one
  MULTI/EXEC transaction, so an interruption leaves either the untouched
  record or a fully coherent settled record.
- On replay, finish invalidated records that still carry the fields:
  rewrite the terminal only when it is missing, always remove stale
  indexes and finish the request rewrite. Fully settled records keep their
  terminal/revision.
- Add interruption coverage at the commit boundary plus damaged-record and
  stale-index repair tests (9/9).
- Bound the iCode version claim to the captured 0.29.2/0.30.0 bindings;
  0.30.1+ is explicitly unverified compatibility.

[缅因猫(Maine Coon)·iCode]

* fix(F306): make downgrade recovery receipt-accurate and replayable

P1: ioredis resolves per-command EXEC errors instead of rejecting, so the
settlement transaction could strip the question fields while a WRONGTYPE
index cleanup was still pending. Pre-check the three index key types and
inspect every EXEC reply; move the request rewrite out of the transaction so
it is the last write. A failed run now reports the record in ailures,
leaves the detection fields for replay and exits non-zero.

P2: settlement completeness no longer equals terminal presence. An
invalidation the old runner interrupted between its separate status/terminal/
updatedAt/revision/HDEL writes is finished under its own recorded settledAt,
while already coherent terminals keep their revision and terminal bytes.

Tests pin a faithful per-command EXEC-error fake, the wrong-type index
refusal, both interrupted-write boundaries, the status-mismatched terminal,
and replay idempotency.

* test(F306): pin the request-rewrite interruption boundary

The request rewrite is the downgrade commit point, so an interruption after
the settlement transaction but before it must leave a replayable record.
Fake the direct HSET failure and assert the rerun lands on exactly the record
hash and index memberships an uninterrupted run produces.

* fix(F306): prove the downgrade settlement revision before stripping

Absent submission is not proof of a finished settlement: a normal pending
provider question (createStaged + anchor) has none, so a record the old runner
stopped before its revision HSET looked complete and kept its pending revision.

Completeness now needs positive proof:
- this tool writes downgradeSettledRevision in the same MULTI as the
  terminal/updatedAt/revision and removes it with the request rewrite, so its
  own interrupted settlement is recognized on replay;
- a terminal reason other than host_restarted can only come from the host's
  atomic Lua settlement, which cannot miss the revision bump;
- everything else is finished under the terminal's own settledAt with one
  revision bump, keeping the terminal bytes intact.

Tests seed the real no-submission shape (revision 2 -> 3), assert the marker
never survives a completed downgrade, and keep the settled-history case
(provider_cancelled) at its original revision.

* fix(F306): keep metadata checks alongside the downgrade settlement marker

A matching marker only proves the revision write: Redis applies the rest of
a MULTI when one command is rejected, so a rejected HDEL submission could
commit the marker and then let a replay skip the cleanup and strip the
detection fields.

planSettlement() now requires the settlement metadata (updatedAt equal to
the terminal's settledAt, submission gone) in addition to the matching
marker before it accepts a record as complete. A marker with incomplete
metadata is finished instead, which redoes the rejected write and only then
commits the rewrite.

Test injects a per-command HDEL failure, asserts the partial record keeps its
fields and submission, and asserts the replay completes the cleanup, removes
the marker and stays a no-op afterwards.

---------

Co-authored-by: Lysander Su <773678591@qq.com>
* fix(chat): use the member shell for plugin messages

Why: connector source URLs made avatar and author labels act as hidden GitHub navigation, while ConnectorBubble maintained a parallel visual shell for ordinary plugin messages. Keep destinations in explicit Markdown content, reject the retired URL contract without a Host compatibility path, and share the member nameplate/message shell without changing specialized hold, job, or card bodies.

[砚砚/gpt-5.6-sol🐾]

* fix(messaging): preserve historical plugin payloads

Why: removing the retired presentation URL must not make otherwise valid persisted plugin messages unreadable or block snapshot and append flows. Project persisted presentation records onto the current generic contract while keeping new admission strict.

[砚砚/gpt-5.6-sol🐾]

* fix(web): unify plugin message identity and replies

Why: connector-transport messages still bypassed the shared member identity and reply surfaces, leaving themed plugin chrome, ambiguous external authors, and missing parent previews. Render plugin, external-person, and Host identities through the common nameplate while preserving specialized message bodies and exact reply authorization.

[砚砚/gpt-5.6-sol🐾]

* fix(web): preserve id-only external senders

Why: external platforms guarantee a sender ID but may omit a display name. Treating only named senders as people mislabeled valid participants as Host and hid their canonical identity; use the ID fallback while keeping static Host notices purpose-first.

[砚砚/gpt-5.6-sol🐾]
…1707)

* feat(dsh): reuse custom LLM configuration for ACP members

* fix(dsh): preserve preparation identity and clear stale effort

* test(dsh): type the editable member fixture explicitly

* fix(dsh): invalidate test receipts on launch edits

* test(dsh): satisfy build lint for request fixture

* fix(dsh): restrict persistent configuration copies to typed fields

* fix(dsh): show first-use setup guidance before expanding settings

---------

Co-authored-by: whutzefengxie-ops <whutzefengxie-ops@users.noreply.github.com>
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
Why: A trusted installed plugin uses the public SDK through its active instance token and canonical caller context. Per-plugin capability policies, inventory grants, whole-feature eligibility and native MCP method lists duplicate that boundary and can leave registered tools without credentials. Preserve current upstream Task controller, lifecycle, owner, package integrity and CAS behavior while porting the reviewed fork cleanup. Old packages retain their verified raw manifest and receive legacy hello metadata only at the existing output boundary. This is a draft port of source 7c96f90c739b5f25c3c0a32cd73b81c795630f6a onto upstream f005686; related-base resolutions need fresh review. Same-schema persistent rollback remains unresolved and blocks merge or deployment.
Why: removing retired controller grant coordinates must not rewrite immutable receipts or break completed operation IDs. Preserve historical receipt input only for digest replay, keep current bindings and new receipts grant-free, and fix the Draft CI cleanup regressions.
Why: the reviewed archive replacement API no longer carries duplicate grant fields. Regenerate its canonical MCP surface snapshot so the existing governance check describes the actual schema; no registry, gate rule, runtime code or permission mechanism changes.
Why: the upstream port retained obsolete assumptions about exposed provider tokens, Kimi config rendering and moved materializer imports. Exercise the real secret descriptor and Kimi lease, preserve artifact conditions, and leave production behavior unchanged.
Why: keep one reviewable draft current with the checked public export.

Daily-Public-Sync: v1
Source-Commit: 2c7987ca2bf538aa806ff0f8ddb6fbeb6c5f929d
Public-Base: 0fc7e37

[小星星·砚砚/GPT-6-astra🐾]

Co-authored-by: 小星星·砚砚 (GPT-6-astra) <codex-astra@cat-cafe.local>
Co-authored-by: lang <39692836+mindfn@users.noreply.github.com>
Why: the new Contract no longer exports duplicate grant validation, and current inventory and Manager surfaces have no API grant rows. Keep Alpha isolation, nested-copy, desktop lifecycle and read-only legacy-origin behavior tests; remove only their retired permission plumbing and the obsolete mixed-grant refusal case.
Why: the installation-race fixture was already disabled, so assigning disabled again did not change the configuration fence. Advance its lifecycle revision to verify stale preflight rejection and remove the fixture's retired grant inputs.

[砚砚/gpt-6.1-sol🐾]
Why: rebuild the fork against upstream fa1dc90 while retaining the complete reviewed PR1720 source and CI fixes. Runtime checkout is unchanged.

[砚砚/gpt-6.1-sol🐾]
Why: preserve origin/fork/optimizations 8a90e14 while rebuilding against upstream and PR1720. The sole conflict was the generated MCP baseline, regenerated from the merged canonical tool sources. Host API/shared/web source remains identical to the reviewed 40f83e1 candidate.

[砚砚/gpt-6.1-sol🐾]
Why: the rebuilt tree is latest upstream fa1dc90 plus complete PR1720 and the existing fork customization layer. Record the old develop_base 70ab667 as an ancestor so the fork can adopt this verified replacement through an ordinary PR without rewriting shared branch history. Older plugin stopgaps are superseded by the complete upstream and PR1720 implementations; no runtime checkout or data is modified.

[砚砚/gpt-6.1-sol🐾]
@mindfn
mindfn merged commit 51cca01 into develop_base Oct 26, 2026
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.

9 participants