spec: add BEHAVIOR_SPEC and fix B-01~B-10 (resolved/decay/scoring)

- Add BEHAVIOR_SPEC.md as full system behaviour reference
- B-01: stop auto-archiving resolved buckets in update()
- B-03: keep activation_count as float in calculate_score
- B-04: initialise activation_count=0 on create
- B-05: time score coefficient 0.1 -> 0.02
- B-06: w_time default 2.5 -> 1.5
- B-07: content_weight default 3.0 -> 1.0
- B-08: refresh local meta after auto_resolve
- B-09: user-supplied valence/arousal takes priority over analyze()
- B-10: allow empty domain for feel buckets
- Refresh INTERNALS/README/dashboard accordingly
This commit is contained in:
P0luz
2026-04-21 18:45:52 +08:00
parent c7ddfd46ad
commit ccdffdb626
10 changed files with 1186 additions and 36 deletions

View File

@@ -54,7 +54,7 @@ class BucketManager:
天然兼容 Obsidian 直接浏览和编辑。
"""
def __init__(self, config: dict):
def __init__(self, config: dict, embedding_engine=None):
# --- Read storage paths from config / 从配置中读取存储路径 ---
self.base_dir = config["buckets_dir"]
self.permanent_dir = os.path.join(self.base_dir, "permanent")
@@ -92,6 +92,9 @@ class BucketManager:
self.w_importance = scoring.get("importance", 1.0)
self.content_weight = scoring.get("content_weight", 3.0) # Added to allow better content-based matching during merge
# --- Optional embedding engine for pre-filtering / 可选 embedding 引擎,用于预筛候选集 ---
self.embedding_engine = embedding_engine
# ---------------------------------------------------------
# Create a new bucket
# 创建新桶
@@ -473,6 +476,20 @@ class BucketManager:
else:
candidates = all_buckets
# --- Layer 1.5: embedding pre-filter (optional, reduces multi-dim ranking set) ---
# --- 第1.5层embedding 预筛(可选,缩小精排候选集)---
if self.embedding_engine and self.embedding_engine.enabled:
try:
vector_results = await self.embedding_engine.search_similar(query, top_k=50)
if vector_results:
vector_ids = {bid for bid, _ in vector_results}
emb_candidates = [b for b in candidates if b["id"] in vector_ids]
if emb_candidates: # only replace if there's non-empty overlap
candidates = emb_candidates
# else: keep original candidates as fallback
except Exception as e:
logger.warning(f"Embedding pre-filter failed, using fuzzy only / embedding 预筛失败: {e}")
# --- Layer 2: weighted multi-dim ranking ---
# --- 第二层:多维加权精排 ---
scored = []