feat(memory) + chore(workplan): complete T02 for CYA-WP-0003 — port extensions for activation, kinds, and retrospection records (backward compatible)

This commit is contained in:
2026-05-26 15:15:20 +02:00
parent 03aaaf99e5
commit abc54989e5
2 changed files with 96 additions and 31 deletions

View File

@@ -23,6 +23,11 @@ import time
from pathlib import Path
from typing import Any
# Standard memory kinds used by cya (especially after CYA-WP-0003)
KIND_PREFERENCE = "preference"
KIND_RETROSPECTION = "retrospection"
KIND_INTERACTION_GOAL = "interaction_goal"
def _warn_not_connected(feature: str) -> None:
"""Loud, visible marker that phase-memory is not yet wired (fallback path)."""
@@ -67,10 +72,10 @@ def _save(scope: str, items: list[dict[str, Any]]) -> None:
# ---------------------------------------------------------------------------
# Explicit ports (the four capabilities from the workplan)
# Refined in T01 per phase-memory architecture + interop + lifecycle.
# Real (non-no-op) implementation added in T02: actual persist + recall across
# invocations, with provenance for explainability. Still graceful.
# See MemoryVision.md "cya ↔ phase-memory Integration Contract".
# Refined in T01 (0003) per phase-memory architecture + interop + lifecycle.
# Real (non-no-op) implementation added in T02 (0002): actual persist + recall.
# Extended in T02 (0003) for contextual activation and retrospection support.
# See docs/cya-memory-activation-and-retrospection-concept.md and MemoryVision.md.
# ---------------------------------------------------------------------------
@@ -81,12 +86,15 @@ def remember_preference(
*,
profile: str | None = None,
ttl: str | None = None,
kind: str = KIND_PREFERENCE,
) -> None:
"""Remember a user preference or workflow pattern (preference kind).
"""Remember a user preference, workflow pattern, retrospection outcome, or goal.
Real T02: persists to user-controlled json (scoped).
Future: delegates to phase-memory profile execution / graph store + planner.
Dry-run plans and policy checks will come from phase-memory lifecycle.
`kind` defaults to "preference" for backward compatibility.
Special kinds (e.g. "retrospection", "interaction_goal") are supported for
higher-order memory from retrospection sessions (see CYA-WP-0003).
Real T02 + 0003: persists to user-controlled json (scoped).
"""
try:
items = _load(scope)
@@ -96,7 +104,7 @@ def remember_preference(
"ts": time.time(),
"scope": scope,
"profile": profile,
"kind": "preference",
"kind": kind,
}
# avoid exact dups for same key in small stores
items = [i for i in items if i.get("key") != key]
@@ -115,30 +123,52 @@ def recall_preferences(
kinds: list[str] | None = None,
profile: str | None = None,
limit: int = 50,
activation_context: dict | None = None,
) -> dict[str, Any]:
"""Recall relevant history / preferences for cwd + task (preference + context).
"""Recall relevant memory for the current context.
Real T02: loads from user-controlled scoped json.
Returns structured payload with items, provenance, phase for explain.
Future: real phase-memory retrieval + planner + dry_run_plan.
Supports:
- `kinds`: filter or boost specific kinds (e.g. ["interaction_goal", "retrospection"])
- `activation_context`: hints for smarter activation (e.g. {"cwd": "...", "project": "..."})
- Backward compatible with all previous call sites.
Real T02 + 0003 extensions for contextual activation and retrospection support.
"""
try:
items = _load(scope)
# Basic kind filtering (existing behavior + 0003 enhancement)
if kinds:
items = [i for i in items if i.get("kind") in kinds or not i.get("kind")]
items = items[-limit:] # most recent
# Simple activation boost: prefer items whose scope or profile matches context
if activation_context:
ctx_cwd = activation_context.get("cwd") or activation_context.get("scope")
ctx_profile = activation_context.get("profile")
boosted = []
normal = []
for item in items:
if (ctx_cwd and item.get("scope") == ctx_cwd) or (ctx_profile and item.get("profile") == ctx_profile):
boosted.append(item)
else:
normal.append(item)
items = boosted + normal
items = items[-limit:] # most recent first (after boosting)
return {
"items": items,
"provenance": [
{
"source": "cya-local-memory-json (T02; phase models ready)",
"source": "cya-local-memory-json (T02+0003; activation + retrospection support)",
"scope": scope,
"count": len(items),
"activation_context": activation_context,
}
],
"phase": "fluid",
"profile": profile,
"note": "real persist across invocations; full phase-memory graph/planner in later T02 slice",
"note": "real persist + contextual activation; full phase-memory in later slices",
}
except Exception as e:
_warn_not_connected(
@@ -164,23 +194,32 @@ def forget(scope: str = "cwd", keys: list[str] | None = None, *, profile: str |
_warn_not_connected(f"forget(scope={scope}, keys={keys}, profile={profile}) err={e}")
def export_memory(scope: str = "cwd", *, profile: str | None = None) -> dict[str, Any]:
def export_memory(scope: str = "cwd", *, profile: str | None = None, kinds: list[str] | None = None) -> dict[str, Any]:
"""Inspect / export current memory for this project or user.
Real T02: returns the raw items + meta for full transparency (used by explain).
Includes phase, provenance summary, policy notes placeholder.
Supports optional `kinds` filter (e.g. to export only retrospection records).
Real T02 + 0003: improved transparency for different memory kinds.
"""
try:
items = _load(scope)
if kinds:
items = [i for i in items if i.get("kind") in kinds]
by_kind = {}
for item in items:
k = item.get("kind", "unknown")
by_kind.setdefault(k, []).append(item)
return {
"status": "real (T02 local json; phase ready)",
"status": "real (T02+0003 local json; activation + retrospection ready)",
"scope": scope,
"profile": profile,
"count": len(items),
"items": items,
"by_kind": {k: len(v) for k, v in by_kind.items()},
"phase": "fluid",
"provenance_summary": f"{len(items)} preference records from ~/.config/cya/memory/",
"note": "Replace this module with real phase-memory ports/graph (see MemoryVision contract). User can edit the json directly.",
"provenance_summary": f"{len(items)} records from ~/.config/cya/memory/ (kinds: {list(by_kind.keys())})",
"note": "User-controlled. Replace with real phase-memory when available.",
"phases": ["ephemeral", "fluid", "stabilized", "rigid"],
}
except Exception as e:
@@ -191,10 +230,30 @@ def export_memory(scope: str = "cwd", *, profile: str | None = None) -> dict[str
}
def remember_retrospection_outcome(
key: str,
value: Any,
scope: str = "cwd",
*,
profile: str | None = None,
) -> None:
"""Convenience helper to record outcomes from a retrospection session.
Stores with kind="retrospection" or "interaction_goal" (caller decides via key/value).
This is a thin wrapper around remember_preference for clarity in T04+.
"""
kind = KIND_RETROSPECTION if "retrospection" in str(key).lower() else KIND_INTERACTION_GOAL
remember_preference(key, value, scope=scope, profile=profile, kind=kind)
__all__ = [
"remember_preference",
"recall_preferences",
"forget",
"export_memory",
"remember_retrospection_outcome",
"KIND_PREFERENCE",
"KIND_RETROSPECTION",
"KIND_INTERACTION_GOAL",
]

View File

@@ -73,20 +73,26 @@ completed: "2026-05-27"
```task
id: CYA-WP-0003-T02
status: todo
status: done
priority: high
state_hub_task_id: "6f50bdf4-6252-4b93-9697-407ef432cd90"
started: "2026-05-27 ralph continuation (after T01 review)"
completed: "2026-05-27"
```
- Evolve the four ports (or add minimal new ones) to better support:
- Richer scoping and activation hints (e.g., directory + project identity + optional profile).
- Storing and retrieving "retrospection outcomes" and "interaction goals" as first-class memory.
- Define lightweight structures for retrospection records and activated context packages.
- Maintain full backward compatibility and user inspectability.
**Done** — implemented in `src/cya/memory/__init__.py`.
**Acceptance criteria**:
- Ports and data model support the concepts from T01 without breaking existing usage.
- All new memory remains fully user-visible and editable.
- Added `kind` parameter to `remember_preference` (defaults to "preference" for full backward compat).
- Added `KIND_*` constants and `remember_retrospection_outcome()` convenience helper.
- Enhanced `recall_preferences` with better `kinds` filtering + new `activation_context` parameter for smarter directory/project-aware activation.
- Improved `export_memory` with optional `kinds` filter and `by_kind` summary.
- All changes maintain 100% backward compatibility with existing call sites.
- Verified manually (roundtrips for preferences, retrospection records, kind filtering, and activation hints all work).
**Acceptance criteria met**:
- Ports and data model now support the T01 concepts.
- Everything remains fully user-visible/editable (still plain JSON under `~/.config/cya/memory/`).
- No breaking changes.
### T03 — Implement directory- and project-bound memory activation