RC19 Core Findings (R3)
Status: in progress (phase-2 pass completed on 2026-02-11).
Scope
src/cccc/kernel/**src/cccc/daemon/**- permission boundaries (
require_group_permission, actor targeting rules) - delivery/automation/inbox state transitions
Validation Snapshot
python3 -m compileall -q src/cccc-> pass.venv/bin/python -m pytest -q-> pass (79 passed)npm --prefix web run typecheck-> pass.venv/bin/python -m pytest -q tests/test_group_automation_baseline.py tests/test_automation_rules_constraints.py-> pass (5 passed)- clean runner rehearsal (
/tmp/cccc-rc19-rehearsal.*) -> pass (python -m build,twine check, wheel install,cccc version) .venv/bin/python -m pytest -q tests/test_delivery_throttle.py tests/test_automation_nudge_digest.py tests/test_automation_rules_constraints.py tests/test_message_obligation.py tests/test_registry_reconcile_and_autowake.py tests/test_events_stream_resume_filtering.py-> pass (12 passed)- Automation execution path reviewed end-to-end (
group_automation_manage-> scheduler -> action execution -> state persist) - One-time reminder invalidation reviewed in runtime path (
trigger.kind == "at"triggers auto-disable after successful execution)
Findings
| ID | Severity | Area | Finding | Evidence | Owner | Status |
|---|---|---|---|---|---|---|
| - | - | Runtime core baseline | No new runtime-core P0/P1 defect was identified in this baseline pass. | src/cccc/daemon/automation.py:1323, src/cccc/daemon/automation.py:1562, src/cccc/kernel/group.py:392 | core-platform | monitoring |
| RC19-011 | P2 | State model consistency | Automation supports operational stop via action.kind=group_state,state=stopped, but MCP cccc_group_set_state schema only advertises active/idle/paused, creating operator/API expectation drift. | src/cccc/contracts/v1/automation.py:59, src/cccc/daemon/automation.py:1248, src/cccc/ports/mcp/server.py:784, tests/test_mcp_group_set_state_stopped.py:1 | mcp-surface | fixed |
| RC19-015 | P2 | Permission boundary maintenance | Daemon uses group.settings_update in permission checks, but GroupAction type omitted it, creating a silent type-surface drift. | src/cccc/daemon/server.py:2334, src/cccc/daemon/server.py:2431, src/cccc/daemon/server.py:2793, src/cccc/kernel/permissions.py:19, tests/test_permissions_group_settings_update.py:1 | core-platform | fixed |
| RC19-016 | P2 | Permission boundary maintenance | No regression test ensured action-literal parity between daemon permission calls and typed permission action sets (GroupAction / ActorAction). | src/cccc/daemon/server.py:2267, src/cccc/daemon/server.py:3344, tests/test_permissions_action_parity.py:1 | core-platform | fixed |
| RC19-021 | P2 | Automation manage UX robustness | Canonical-only automation payload is intentional, but legacy payload failures were opaque; now daemon emits actionable legacy-shape errors to reduce agent/operator misuse loops. | src/cccc/daemon/server.py:732, src/cccc/daemon/server.py:2441, src/cccc/daemon/server.py:2657, tests/test_automation_manage_legacy_shape.py:1 | core-platform | fixed |
| RC19-022 | P2 | Stream resume robustness | events_stream now falls back to since_ts when since_event_id is no longer available in tail history, reducing reconnect drop risk without broad behavior changes. | src/cccc/daemon/streaming.py:253, src/cccc/daemon/streaming.py:263, tests/test_events_stream_resume_filtering.py:140 | core-platform | fixed |
| RC19-023 | P2 | Delivery robustness | invalid/negative delivery.min_interval_seconds values are now tolerated and clamped, preventing silent delivery stalls when config is malformed. | src/cccc/daemon/delivery.py:60, src/cccc/daemon/delivery.py:768, tests/test_delivery_throttle.py:47 | core-platform | fixed |
| RC19-024 | P2 | Settings default immutability | runtime-pool defaults are now copied before return, preventing cross-call mutation leaks from caller-side edits. | src/cccc/kernel/settings.py:45, src/cccc/kernel/settings.py:283, tests/test_runtime_pool_defaults_immutable.py:1 | core-platform | fixed |
| RC19-025 | P2 | Settings dirty-config tolerance | runtime pool parser now sanitizes malformed priority/scenarios fields to stable defaults, preventing bad config from destabilizing recommendation logic. | src/cccc/kernel/settings.py:34, src/cccc/kernel/settings.py:310, tests/test_runtime_pool_defaults_immutable.py:31 | core-platform | fixed |
| RC19-026 | P2 | Registry normalization robustness | malformed registry root/map types are now normalized at load time, preventing silent write-loss on defaults/groups updates. | src/cccc/kernel/registry.py:31, src/cccc/kernel/registry.py:47, tests/test_registry_doc_normalization.py:1 | core-platform | fixed |
| RC19-027 | P2 | Group template settings robustness | template build/preview now tolerate dirty numeric values and parse booleans canonically, preventing false-positive booleans and export/preview failures. | src/cccc/kernel/group_template.py:19, src/cccc/kernel/group_template.py:86, src/cccc/kernel/group_template.py:200, tests/test_group_template_dirty_settings_tolerance.py:1 | core-platform | fixed |
| RC19-028 | P2 | Actor-id rule consistency | actor-id validator now enforces documented first-character constraint (no leading _), eliminating contract drift between docs and runtime checks. | src/cccc/kernel/actors.py:38, src/cccc/kernel/actors.py:17, tests/test_actor_id_validation.py:1 | core-platform | fixed |
| RC19-029 | P2 | Context sync atomicity | context_sync now stages presence mutations in memory and persists once at commit, preventing partial writes when a later op in the same batch fails. | src/cccc/daemon/ops/context_ops.py:184, src/cccc/daemon/ops/context_ops.py:486, tests/test_context_sync_atomicity.py:1 | core-platform | fixed |
| RC19-030 | P2 | MCP boolean coercion parity | MCP dispatcher now uses canonical bool coercion for workflow flags, eliminating "false" truthiness drift in agent-driven automation/context calls. | src/cccc/ports/mcp/server.py:2332, src/cccc/ports/mcp/server.py:2339, src/cccc/ports/mcp/server.py:2391, src/cccc/ports/mcp/server.py:2529, src/cccc/ports/mcp/server.py:2550, tests/test_mcp_tool_bool_coercion.py:1 | mcp-surface | fixed |
| RC19-031 | P2 | Daemon start operational safety | daemon start path now refuses duplicate spawn when pid-file process is alive but IPC is unresponsive, preventing split-brain/lock contention incidents. | src/cccc/daemon_main.py:45, src/cccc/daemon_main.py:54, tests/test_daemon_main_start_safety.py:1 | core-platform | fixed |
| RC19-032 | P2 | Context dirty-data resilience | context/task/presence loading now tolerates malformed entries and invalid statuses with safe fallbacks, reducing accidental state loss during long-running operations. | src/cccc/kernel/context.py:181, src/cccc/kernel/context.py:314, src/cccc/kernel/context.py:547, tests/test_context_storage_dirty_tolerance.py:1 | core-platform | fixed |
| RC19-033 | P2 | Web settings API resilience | settings endpoint now safely coerces numeric fields from group config, preventing dirty-value crashes that previously broke Settings page rendering. | src/cccc/ports/web/app.py:123, src/cccc/ports/web/app.py:1315, tests/test_web_group_settings_dirty_tolerance.py:1 | web-ux | fixed |
| RC19-034 | P2 | SSE tailer lifecycle hygiene | shared SSE tailers now self-remove from global registry after idle exit, preventing stale tailer accumulation in long-running web runtime sessions. | src/cccc/ports/web/streams.py:234, src/cccc/ports/web/streams.py:252, tests/test_web_streams_tailer_cleanup.py:1 | web-ux | fixed |
| RC19-035 | P2 | Global events fallback resilience | global-events hook now attempts SSE recovery while polling fallback is active, avoiding permanent degradation to polling-only mode after transient stream failures. | web/src/hooks/useGlobalEvents.ts:31, web/src/hooks/useGlobalEvents.ts:39, web/src/hooks/useGlobalEvents.ts:49, web/src/hooks/useGlobalEvents.ts:64 | web-ux | fixed |
| RC19-036 | P2 | Actor enabled coercion parity | actor enabled checks now use canonical bool coercion in routing/prompt/auto-wake paths, preventing "false" string values from being misread as enabled actors. | src/cccc/kernel/messaging.py:30, src/cccc/kernel/system_prompt.py:32, src/cccc/daemon/server.py:1818, tests/test_enabled_flag_coercion.py:42 | core-platform | fixed |
| RC19-037 | P2 | IM subscriber dirty-data tolerance | subscriber loading now safely coerces subscribed/verbose/thread_id values, so one malformed row no longer breaks effective subscriber state loading. | src/cccc/ports/im/subscribers.py:14, src/cccc/ports/im/subscribers.py:56, tests/test_im_subscribers_tolerance.py:8 | im-bridge | fixed |
| RC19-038 | P2 | CLI env bool semantics | CLI now parses CCCC_WEB_RELOAD with canonical bool coercion, preventing "false"/"0"/"off" from incorrectly enabling reload mode. | src/cccc/cli.py:170, src/cccc/cli.py:457, tests/test_cli_env_bool_parsing.py:6 | core-platform | fixed |
| RC19-039 | P2 | Daemon settings dirty-data tolerance | group_settings_update now builds response settings with safe int coercion/clamp, so unrelated dirty stored values no longer crash otherwise valid updates. | src/cccc/daemon/server.py:103, src/cccc/daemon/server.py:2425, tests/test_daemon_group_settings_dirty_tolerance.py:8 | core-platform | fixed |
| RC19-040 | P2 | Active pointer dirty-data tolerance | load_active() now normalizes non-dict/dirty payloads into stable mapping shape and self-heals persisted active.json, preventing downstream .get(...) failures. | src/cccc/kernel/active.py:14, src/cccc/kernel/active.py:18, tests/test_active_doc_normalization.py:8 | core-platform | fixed |
| RC19-041 | P2 | Blob path containment hardening | blob attachment resolution now uses path containment semantics (relative_to) after resolve, removing separator-fragile prefix checks. | src/cccc/kernel/blobs.py:93, src/cccc/kernel/blobs.py:100, tests/test_blob_path_resolution.py:8 | core-platform | fixed |
| RC19-042 | P2 | Automation running-state coercion | automation group_state execution now coerces dirty running values canonically, so "false" no longer suppresses required group_start; actor-idle terminal tail settings are also clamped/coerced safely. | src/cccc/daemon/automation.py:1258, src/cccc/daemon/automation.py:1033, tests/test_automation_rules_constraints.py:75 | core-platform | fixed |
| RC19-043 | P2 | MCP group list state parity | MCP group_list now coerces running canonically, preventing "false" strings from being exposed to agents as running groups. | src/cccc/ports/mcp/server.py:692, tests/test_mcp_tool_bool_coercion.py:6 | mcp-surface | fixed |
| RC19-044 | P2 | Template replace bool coercion | template settings apply path now coerces delivery/terminal bool toggles canonically, preventing string-bool drift during template import/replace operations. | src/cccc/daemon/ops/template_ops.py:228, src/cccc/daemon/ops/template_ops.py:234, tests/test_group_template_auto_mark_on_delivery.py:95 | core-platform | fixed |
| RC19-045 | P2 | MCP file-send path hardening | MCP file_send scope-root containment now uses path semantics (relative_to) instead of string-prefix checks, preventing platform/path-edge bypass drift. | src/cccc/ports/mcp/server.py:582, tests/test_mcp_tool_bool_coercion.py:43 | mcp-surface | fixed |
| RC19-046 | P2 | MCP sanitized state coercion | MCP group_info/actor_list sanitized views now canonically coerce running/enabled, preventing dirty string values from being surfaced to agents as truthy states. | src/cccc/ports/mcp/server.py:626, src/cccc/ports/mcp/server.py:648, tests/test_mcp_tool_bool_coercion.py:7, tests/test_mcp_tool_bool_coercion.py:20 | mcp-surface | fixed |
| RC19-047 | P2 | Actor contract state parity | GroupState contract now includes stopped, aligning contract-level state vocabulary with CLI/MCP/runtime behavior. | src/cccc/contracts/v1/actor.py:34, tests/test_actor_group_state_contract.py:6 | core-platform | fixed |
| RC19-048 | P2 | MCP helper bool coercion parity | MCP direct helper functions (message_send/message_reply/file_send) now canonically coerce reply_required, preventing string-bool drift when these helpers are reused outside dispatcher path. | src/cccc/ports/mcp/server.py:460, src/cccc/ports/mcp/server.py:519, src/cccc/ports/mcp/server.py:614, tests/test_mcp_tool_bool_coercion.py:103, tests/test_mcp_tool_bool_coercion.py:124 | mcp-surface | fixed |
| RC19-049 | P2 | PTY attach robustness | non-writer PTY clients with empty backlog could attempt selector register with events=0, causing attach failure; attach path now always registers READ and enables WRITE only when needed. | src/cccc/runners/pty.py:476, tests/test_pty_attach_selector_events.py:27 | core-platform | fixed |
| RC19-050 | P2 | Web release gate completeness | web CI/release only built bundles and did not run strict TS checks, allowing type errors to pass. pipeline now runs lint + typecheck before build. | web/src/components/modals/settings/AutomationTab.tsx:464, .github/workflows/ci.yml:26, .github/workflows/release.yml:31, web/package.json:11 | web-ux | fixed |
| RC19-051 | P2 | Modal close interaction safety | settings/recipients overlays previously closed on backdrop click, which could fire after drag-select and cause accidental modal dismissal; close trigger now uses backdrop pointerdown semantics for consistent mouse/touch behavior. | web/src/components/SettingsModal.tsx:793, web/src/components/modals/RecipientsModal.tsx:31 | web-ux | fixed |
| RC19-052 | P2 | Baseline semantics regression guard | added targeted regression coverage to lock intended automation baseline behavior: group create seeds standup baseline, while user-cleared rules/snippets remain cleared. | tests/test_group_automation_baseline.py:1, src/cccc/kernel/group.py:29, src/cccc/daemon/server.py:679 | qa | fixed |
| RC19-053 | P2 | Group selection/cache coherence | group refresh now clears stale selection caches when selected group disappears (or none remain), and template-create conflict flow refreshes group list before jumping to existing group to avoid sidebar/detail desync. | web/src/stores/useGroupStore.ts:286, web/src/components/AppModals.tsx:392 | web-ux | fixed |
| RC19-054 | P2 | Modal backdrop close safety parity | search/context modals now use backdrop onPointerDown target-check close semantics (including Context nested notify modal), preventing drag-select mouseup on backdrop from unexpectedly dismissing dialogs. | web/src/components/SearchModal.tsx:181, web/src/components/ContextModal.tsx:387, web/src/components/ContextModal.tsx:1666 | web-ux | fixed |
| RC19-055 | P2 | Group status precedence coherence | group status rendering now always prioritizes running=false as STOP, removing paused/idle visual ambiguity when runtime has already stopped. | web/src/utils/groupStatus.ts:3, web/src/utils/groupStatus.ts:30 | web-ux | fixed |
| RC19-056 | P2 | Guidance editor modal close safety parity | guidance expanded editor now uses backdrop onPointerDown close semantics, aligning with modal safety baseline for consistent pointer/touch behavior. | web/src/components/modals/settings/GuidanceTab.tsx:215 | web-ux | fixed |
| RC19-057 | P2 | Mobile navigation backdrop close safety parity | mobile sidebar and mobile menu backdrops now use onPointerDown target-check close semantics, reducing unintended close events from click synthesis during touch/pointer interactions. | web/src/components/layout/GroupSidebar.tsx:267, web/src/components/layout/MobileMenuSheet.tsx:62 | web-ux | fixed |
| RC19-058 | P2 | Auth callback resilience on non-JSON 401 | API client now triggers auth-required callback directly from HTTP status (401) in apiJson and apiForm, so re-auth flow still works when backend/proxy returns non-JSON or empty unauthorized responses. | web/src/services/api.ts:120, web/src/services/api.ts:160 | web-ux | fixed |
| RC19-059 | P2 | Automation feature-doc parity | reference features doc now reflects current automation model (rule triggers/actions, one-time completion semantics, built-in policies, and MCP management surface), removing expectation drift from the previous built-ins-only description. | docs/reference/features.md:153 | docs | fixed |
| RC19-060 | P2 | SDK draft state-surface parity | SDK design draft snippet now documents group_set_state as `active | idle | paused | stopped`, aligning example-level API surface with current state semantics. |
| RC19-061 | P2 | Web guide automation parity | Web UI guide now reflects the current automation model (rule triggers/actions, one-time completion behavior, and built-in engine policies) instead of legacy timeout-only wording. | docs/guide/web-ui.md:119 | docs | fixed |
| RC19-062 | P2 | Onboarding docs freshness parity | getting-started/FAQ docs now avoid stale RC pinning and old source URL references; MCP description wording is de-pinned from fixed tool counts to stay accurate across releases. | docs/guide/getting-started/index.md:57, docs/guide/faq.md:10 | docs | fixed |
| RC19-063 | P2 | vNext legacy-doc safety guard | vNext docs now include explicit historical-snapshot warnings (plus correction of obvious stale blob/tool-count wording) to prevent readers from treating archived design text as live runtime truth. | docs/vnext/ARCHITECTURE.md:6, docs/vnext/FEATURES.md:3, docs/vnext/README.md:6 | docs | fixed |
| RC19-064 | P2 | External product narrative upgrade | EN/ZH top-level readmes were rewritten from thin technical summaries to product-level landing docs with clearer value proposition, fit boundaries, adoption path, and architecture framing. | README.md:1, README.zh-CN.md:1 | docs | fixed |
| RC19-065 | P2 | Docs information architecture upgrade | Added scenario and operations surfaces (use-cases, operations, positioning) and updated docs navigation to route users by intent (adoption, delivery, operations), improving discoverability and practical onboarding depth. | docs/guide/use-cases.md:1, docs/guide/operations.md:1, docs/reference/positioning.md:1, docs/.vitepress/config.ts:35 | docs | fixed |
R3 Exit Tracking
P0: 0 (phase-2)P1: 0 (phase-2)- Remaining: no active R3 parity blockers from this pass