Skip to content

Commit 07fd45d

Browse files
authored
Merge branch 'ChesterRa:main' into main
2 parents 0d7c20f + 53afce4 commit 07fd45d

10 files changed

Lines changed: 615 additions & 31 deletions

File tree

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,77 @@
11
# CCCC v0.4.6 Release Notes
22

3-
`v0.4.6` is a smaller quality release focused on operator discipline and agent behavior rather than new product surface area.
3+
`v0.4.6` builds on `v0.4.5` with a broader set of improvements than a pure prompt/preset polish release.
44

5-
It strengthens the built-in role presets with higher-signal planning, review, debugging, and implementation rules, while keeping the core prompt stack compact and predictable.
5+
Compared with `v0.4.5`, this version extends IM bridge coverage, tightens Web-side context and cache behavior, introduces the first built-in role preset workflow, and hardens startup/shutdown behavior further across Windows and the supervised Web runtime.
66

77
## Highlights
88

9-
## 1) Built-in role presets are more rigorous
9+
## 1) WeCom IM bridge support is now real and documented
1010

11-
This release upgrades the first-wave built-in role presets with stronger execution discipline harvested from high-quality external prompt patterns.
11+
The biggest functional addition in `v0.4.6` is WeCom bridge support.
12+
13+
Key changes:
14+
15+
- a dedicated WeCom adapter was added instead of trying to force everything through the older bridge path
16+
- Web-side IM bridge settings were extended so WeCom can be configured from the same operator surface as other bridge providers
17+
- authentication and readiness behavior for the bridge were repaired and covered by targeted tests
18+
- the docs now include a dedicated WeCom guide and screenshots for the operator flow
19+
20+
This matters because `v0.4.5` still treated IM bridge support as narrower and more uneven in practice. `v0.4.6` makes WeCom a real supported path instead of a partial edge lane.
21+
22+
## 2) Web context and cache behavior are tighter and less wasteful
23+
24+
`v0.4.6` also improves how the Web surface reads and refreshes shared control-plane state.
1225

1326
Key improvements:
1427

15-
- planners now push harder on existing-code leverage, minimum viable scope, and complete-vs-shortcut tradeoffs
16-
- implementers are pushed more explicitly to finish the real blast radius in one pass, including nearby tests, docs, and obvious edge-case handling
17-
- reviewers are stricter about reading the full diff first and checking whether docs, diagrams, or adjacent tests went stale
18-
- debuggers are more firmly rooted in regression checks, hypothesis confirmation, and regression-test follow-through
19-
- explorers are better at separating true canonical anchor files from nearby noise
28+
- actor and context route caching is more deliberate and more thoroughly tested
29+
- cache invalidation after writes is less fragile, which reduces stale readback after actor/context updates
30+
- related API/client/store coverage was expanded significantly so the Web state layer is less likely to drift silently
31+
- surrounding settings and control surfaces were cleaned up so context-related interactions behave more predictably
32+
33+
This is not a flashy feature, but it is a meaningful quality improvement over `v0.4.5` because it reduces a class of “the write succeeded but the UI still feels stale or noisy” problems.
34+
35+
## 3) Built-in role presets and prompt discipline landed
36+
37+
This release introduces the first built-in role preset workflow in the Web actor surfaces and strengthens the default collaboration guidance around those roles.
38+
39+
Highlights:
40+
41+
- built-in role presets were added for the first-wave roster, including planner, implementer, reviewer, debugger, explorer, and related roles
42+
- preset application now gives actors a faster way to start from a strong role note instead of writing everything from scratch
43+
- the prompt/help surface was tightened so startup guidance stays lean while richer discipline lives in the longer-lived help/preset layers
44+
- planning, implementation, review, and debugging guidance are now sharper about things like existing-code leverage, full-diff-first review, regression thinking, and one-pass blast-radius cleanup
2045

21-
## 2) The startup prompt stays lean, but a bit smarter
46+
Relative to `v0.4.5`, this is the biggest day-to-day agent-behavior improvement in the release.
2247

23-
`v0.4.6` keeps the startup preamble compact while sharpening one important default:
48+
## 4) Windows and runtime lifecycle handling were hardened again
2449

25-
- actors are nudged to reuse working paths first instead of inventing parallel ones
50+
`v0.4.5` already improved startup and shutdown behavior. `v0.4.6` continues that line with another pass of runtime hardening.
2651

27-
This is intentionally a small change. The goal is to improve default judgment without making the startup prompt bloated again.
52+
Important changes:
2853

29-
## 3) Built-in help now has a safer growth budget
54+
- Windows shutdown cleanup was tightened further so lingering process/lifecycle edge cases are handled more reliably
55+
- daemon/Web supervised runtime ownership and cleanup paths were hardened with additional lifecycle coverage
56+
- Web readiness checks now tolerate more real failure modes, including `OSError` and `HTTPException`, instead of surfacing brittle behavior
57+
- process-path handling and related platform-sensitive helpers received more validation, especially around mocked Windows path resolution and runtime probing
3058

31-
The built-in help surface remains compact, but the enforced ceiling is relaxed from `1300` to `1500` words.
59+
This makes `v0.4.6` a stronger operational release than `v0.4.5`, especially if you are running CCCC on Windows or frequently exercising stop/start/restart flows.
3260

33-
Why this matters:
61+
## 5) Quality bar and verification
3462

35-
- it preserves a hard anti-bloat boundary
36-
- it leaves room for a few more genuinely universal rules in future iterations
37-
- it avoids treating the previous `1300` test limit as a product law when it was really just a local compactness guardrail
63+
Beyond the visible changes above, `v0.4.6` also includes:
3864

39-
## 4) Release readiness stayed clean
65+
- additional tests around Web cache behavior and stores
66+
- stronger coverage for IM bridge startup/config flows
67+
- targeted prompt-default and role-preset tests so the new guidance surfaces are less likely to regress silently
68+
- follow-up lint/typecheck cleanup after the role preset work landed
4069

41-
This version is intentionally small in scope, and the main goal was to land the quality improvements without reopening broader workflow or UI churn.
70+
In short, `v0.4.6` is not just “the preset release.” It is the release that combines:
4271

43-
Validation included:
72+
1. WeCom bridge support
73+
2. better Web context/cache behavior
74+
3. the first built-in role preset workflow
75+
4. another round of Windows/runtime hardening
4476

45-
- Python test suite passing cleanly
46-
- targeted prompt-default tests passing after the compactness-budget change
47-
- Web lint and type-check remaining clean alongside the role-preset text updates
77+
relative to the `v0.4.5` baseline.

src/cccc/daemon/ops/capability_ops/_handlers.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from typing import Any, Dict, List, Optional, Tuple
99

1010
from ....contracts.v1 import DaemonResponse
11-
from ....kernel.capabilities import BUILTIN_CAPABILITY_PACKS
11+
from ....kernel.capabilities import BUILTIN_CAPABILITY_PACKS, BUILTIN_CAPSULE_SKILLS
1212
from ....util.time import parse_utc_iso, utc_now_iso
1313

1414
from ._common import (
@@ -268,11 +268,58 @@ def _build_curated_records_from_policy(policy: Dict[str, Any]) -> Dict[str, Dict
268268
return out
269269

270270

271+
def _build_builtin_skill_records() -> Dict[str, Dict[str, Any]]:
272+
now_iso = utc_now_iso()
273+
out: Dict[str, Dict[str, Any]] = {}
274+
for cap_id, raw in BUILTIN_CAPSULE_SKILLS.items():
275+
if not isinstance(raw, dict):
276+
continue
277+
name = str(raw.get("name") or "").strip() or _display_name_from_capability_id(cap_id).replace(" ", "-")
278+
description_short = str(raw.get("description_short") or "").strip()
279+
capsule_text = str(raw.get("capsule_text") or "").strip()
280+
tags = [str(x).strip() for x in (raw.get("tags") if isinstance(raw.get("tags"), (list, tuple)) else []) if str(x).strip()]
281+
requires_capabilities = [
282+
str(x).strip()
283+
for x in (raw.get("requires_capabilities") if isinstance(raw.get("requires_capabilities"), (list, tuple)) else [])
284+
if str(x).strip()
285+
]
286+
out[cap_id] = {
287+
"capability_id": cap_id,
288+
"kind": "skill",
289+
"name": name,
290+
"description_short": description_short,
291+
"tags": ["skill", "builtin", *tags],
292+
"source_id": "cccc_builtin",
293+
"source_tier": "builtin",
294+
"source_uri": "",
295+
"source_record_id": name,
296+
"source_record_version": "",
297+
"updated_at_source": now_iso,
298+
"last_synced_at": now_iso,
299+
"sync_state": "builtin",
300+
"install_mode": "builtin",
301+
"install_spec": {},
302+
"requirements": {},
303+
"license": "",
304+
"trust_tier": "builtin",
305+
"qualification_status": _QUAL_QUALIFIED,
306+
"qualification_reasons": [],
307+
"health_status": "builtin",
308+
"enable_supported": True,
309+
"capsule_text": capsule_text or f"Skill: {name}\nSummary: {description_short}".strip(),
310+
"requires_capabilities": requires_capabilities,
311+
}
312+
return out
313+
314+
271315
def _ensure_curated_catalog_records(catalog_doc: Dict[str, Any], *, policy: Dict[str, Any]) -> bool:
272316
records = catalog_doc.get("records") if isinstance(catalog_doc.get("records"), dict) else {}
273317
if not isinstance(records, dict):
274318
records = {}
275-
curated = _build_curated_records_from_policy(policy)
319+
curated = {
320+
**_build_builtin_skill_records(),
321+
**_build_curated_records_from_policy(policy),
322+
}
276323
if not curated:
277324
return False
278325

src/cccc/daemon/ops/capability_ops/_search.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
from ....kernel.actors import get_effective_role
1212
from ....kernel.capabilities import (
1313
BUILTIN_CAPABILITY_PACKS,
14+
BUILTIN_CAPSULE_SKILLS,
1415
CORE_TOOL_NAMES,
1516
all_builtin_pack_ids,
17+
all_builtin_skill_ids,
1618
resolve_visible_tool_names,
1719
)
1820
from ....kernel.context import ContextStorage
@@ -264,9 +266,64 @@ def _build_builtin_search_records() -> List[Dict[str, Any]]:
264266
"tool_names": [str(x).strip() for x in tuple(pack.get("tool_names") or ()) if str(x).strip()],
265267
}
266268
)
269+
for cap_id in all_builtin_skill_ids():
270+
skill = BUILTIN_CAPSULE_SKILLS.get(cap_id, {})
271+
out.append(
272+
{
273+
"capability_id": cap_id,
274+
"kind": "skill",
275+
"name": str(skill.get("name") or cap_id),
276+
"description_short": str(skill.get("description_short") or ""),
277+
"tags": list(skill.get("tags") or []),
278+
"source_id": "cccc_builtin",
279+
"source_tier": "builtin",
280+
"source_uri": "",
281+
"trust_tier": "builtin",
282+
"qualification_status": "qualified",
283+
"sync_state": "fresh",
284+
"enable_supported": True,
285+
}
286+
)
267287
return out
268288

269289

290+
def _is_builtin_search_record(item: Dict[str, Any]) -> bool:
291+
return str(item.get("source_id") or "").strip() == "cccc_builtin"
292+
293+
294+
def _skill_capsule_preview(value: Any, *, max_lines: int = 4, max_chars: int = 420) -> str:
295+
text = str(value or "").strip()
296+
if not text:
297+
return ""
298+
raw_lines = [str(raw or "").strip() for raw in text.splitlines() if str(raw or "").strip()]
299+
if not raw_lines:
300+
return ""
301+
protocol_start = next(
302+
(
303+
idx
304+
for idx, line in enumerate(raw_lines)
305+
if str(line).strip().lower() in {"protocol:", "workflow:", "steps:", "playbook:"}
306+
),
307+
-1,
308+
)
309+
if protocol_start >= 0:
310+
selected = [line for line in raw_lines[protocol_start + 1 :] if line]
311+
else:
312+
selected = [
313+
line
314+
for line in raw_lines
315+
if not str(line).strip().lower().startswith(("you are ", "use this skill "))
316+
]
317+
if not selected:
318+
selected = list(raw_lines)
319+
merged = "\n".join(selected[:max_lines])
320+
if len(merged) <= max_chars:
321+
return merged
322+
if max_chars <= 3:
323+
return merged[:max_chars]
324+
return merged[: max_chars - 3].rstrip() + "..."
325+
326+
270327
def _search_matches(query: str, item: Dict[str, Any]) -> bool:
271328
q = str(query or "").strip().lower()
272329
if not q:
@@ -581,7 +638,7 @@ def _rank(row: Dict[str, Any]) -> Tuple[int, int, int, str]:
581638
recent_count = int(recent.get("success_count") or 0)
582639
recent_ts = str(recent.get("last_success_at") or "")
583640
cap_id = str(row.get("capability_id") or "")
584-
builtin_bias = 0 if cap_id.startswith("pack:") else 1
641+
builtin_bias = 0 if _is_builtin_search_record(row) else 1
585642
return (
586643
blocked_penalty,
587644
builtin_bias,
@@ -883,7 +940,7 @@ def handle_capability_search(args: Dict[str, Any]) -> DaemonResponse:
883940

884941
def _rank(item: Dict[str, Any]) -> Tuple[int, int, int, int, int, str]:
885942
cap_id = str(item.get("capability_id") or "")
886-
is_builtin = 0 if cap_id.startswith("pack:") else 1
943+
is_builtin = 0 if _is_builtin_search_record(item) else 1
887944
name_key = str(item.get("name") or cap_id).lower()
888945
enabled_bias = 0 if cap_id in enabled_set else 1
889946
qualification = str(item.get("qualification_status") or "").strip().lower()
@@ -1285,6 +1342,7 @@ def _scope_mismatch_for_capability(capability_id: str) -> bool:
12851342
"capability_id": cap_id,
12861343
"name": str(rec.get("name") or cap_id),
12871344
"description_short": str(rec.get("description_short") or ""),
1345+
"capsule_preview": _skill_capsule_preview(rec.get("capsule_text")),
12881346
"source_id": str(rec.get("source_id") or ""),
12891347
"source_uri": str(rec.get("source_uri") or ""),
12901348
"policy_level": _effective_policy_level(
@@ -1309,6 +1367,7 @@ def _scope_mismatch_for_capability(capability_id: str) -> bool:
13091367
"capability_id": cap_id,
13101368
"name": str(rec.get("name") or cap_id),
13111369
"description_short": str(rec.get("description_short") or ""),
1370+
"capsule_preview": _skill_capsule_preview(rec.get("capsule_text")),
13121371
"source_id": str(rec.get("source_id") or ""),
13131372
"policy_level": _effective_policy_level(
13141373
policy,

0 commit comments

Comments
 (0)