CYA-WP-0005 T05 done (ralph iter 5): Minimal Profile 1 (Reflexion verbal) spike

- Added KIND_REFLECTION + remember_reflection() helper in memory (thin, exported).
- Wired into run_retrospection(): optional 'capture verbal lesson' step at end.
- Main recall now includes reflections for preferential activation.
- Final LLM response + explain surface verbal reflections when activated.
- Added roundtrip test + import updates.
- Small README note.
- All changes small/inspectable, safety preserved (still through RiskClassifier).
- T05 acceptance criteria met with working end-to-end spike.

Committed as ralph iter 5. Ready for T06+ or close.
This commit is contained in:
2026-05-28 03:24:44 +02:00
parent 16fde868cf
commit a87cd4ab42
5 changed files with 72 additions and 3 deletions

View File

@@ -115,7 +115,7 @@ Run a guided reflection session to review how memory was used and explicitly set
cya retrospect
```
During the session `cya` will:
During the session `cya` will (Profile 1 spike in T05 adds optional verbal lesson capture at the end):
- Show recent memory items that were activated.
- Help you reflect on what worked or didn't.
- Let you record new **interaction goals** (e.g. "be more concise", "always show one safe alternative for destructive commands").

View File

@@ -38,6 +38,7 @@ from typing import Any
KIND_PREFERENCE = "preference"
KIND_RETROSPECTION = "retrospection"
KIND_INTERACTION_GOAL = "interaction_goal"
KIND_REFLECTION = "reflection" # Profile 1 (Reflexion-style verbal lessons) — T05 minimal spike
def _warn_not_connected(feature: str) -> None:
@@ -257,14 +258,31 @@ def remember_retrospection_outcome(
remember_preference(key, value, scope=scope, profile=profile, kind=kind)
def remember_reflection(
key: str,
value: Any,
scope: str = "cwd",
*,
profile: str | None = None,
) -> None:
"""Convenience helper for Profile 1 (Reflexion-style verbal self-improvement).
Stores verbal lessons/reflections with kind="reflection" for preferential
activation in future turns. Thin wrapper for the T05 minimal spike.
"""
remember_preference(key, value, scope=scope, profile=profile, kind=KIND_REFLECTION)
__all__ = [
"remember_preference",
"recall_preferences",
"forget",
"export_memory",
"remember_retrospection_outcome",
"remember_reflection",
"KIND_PREFERENCE",
"KIND_RETROSPECTION",
"KIND_INTERACTION_GOAL",
"KIND_REFLECTION",
]

View File

@@ -32,8 +32,10 @@ from cya.context.collector import collect, render_explanation
from cya.memory import (
recall_preferences,
remember_retrospection_outcome,
remember_reflection,
KIND_RETROSPECTION,
KIND_INTERACTION_GOAL,
KIND_REFLECTION,
)
from cya.safety.risk import classify, get_user_confirmation
from cya.llm.adapter import AssistanceRequest, FakeLLMAdapter
@@ -85,7 +87,11 @@ def handle_request(
git_info = envelope.git or {}
if git_info.get("workdir"):
act_ctx["git_root"] = git_info["workdir"]
memory = recall_preferences(".", activation_context=act_ctx)
memory = recall_preferences(
".",
activation_context=act_ctx,
kinds=[KIND_REFLECTION, KIND_RETROSPECTION, KIND_INTERACTION_GOAL, "preference"],
)
except Exception:
memory = {"error": "recall failed (graceful degradation)"}
@@ -150,6 +156,12 @@ def handle_request(
mem_line = ""
if memory.get("items"):
mem_line = f"\n[dim]Memory activated: {len(memory.get('items', []))} items (phase {memory.get('phase')})[/dim]"
# Minimal Profile 1 surface (T05 spike)
reflections = [i for i in memory.get("items", []) if i.get("kind") == KIND_REFLECTION]
if reflections:
refl_text = "; ".join(str(i.get("value", ""))[:60] for i in reflections[:2])
mem_line += f"\n[cyan]Verbal reflections activated: {len(reflections)}{refl_text}[/cyan]"
console.print(
Panel(
f"[bold]Suggestion:[/bold]\n{llm_response.suggestion}\n\n"
@@ -251,6 +263,24 @@ def run_retrospection(scope: str = ".", limit: int = 8) -> None:
)
console.print("[green]Recorded as safety preference.[/green]")
# Minimal Profile 1 spike (T05): optional verbal reflection / lesson capture
capture_lesson = typer.prompt(
"Capture any verbal lessons or reflections from this session? (y/n or short text)",
default="n",
show_default=False,
)
if capture_lesson and capture_lesson.lower() not in ("n", "no", "skip", "s", ""):
lesson_text = capture_lesson if len(capture_lesson) > 3 else typer.prompt(
"What is the key lesson? (1-2 sentences)",
default="",
show_default=False,
)
if lesson_text:
remember_reflection(
"verbal_lesson", lesson_text, scope=scope
)
console.print("[green]Recorded as verbal reflection (Profile 1).[/green]")
console.print(
Panel(
"Thank you. Your reflections have been stored as retrospection memory.\n"

View File

@@ -21,8 +21,10 @@ from cya.memory import (
forget,
export_memory,
remember_retrospection_outcome,
remember_reflection,
KIND_RETROSPECTION,
KIND_INTERACTION_GOAL,
KIND_REFLECTION,
)
from cya.safety.risk import classify, RiskLevel
@@ -167,6 +169,23 @@ def test_recall_with_kinds_and_activation_context(isolated_memory):
assert KIND_INTERACTION_GOAL in kinds or "retrospection" in kinds
def test_profile_1_reflection_helper_and_activation(isolated_memory):
"""Minimal T05 Profile 1 spike: remember_reflection + preferential recall by kind."""
remember_reflection("lesson_rust", "Always run cargo clippy before suggesting fixes", scope="proj-rust")
data = recall_preferences(
scope="proj-rust",
kinds=[KIND_REFLECTION],
activation_context={"cwd": "proj-rust"},
)
assert len(data.get("items", [])) >= 1
kinds = [i.get("kind") for i in data.get("items", [])]
assert KIND_REFLECTION in kinds
# The helper stored it correctly
assert any("cargo clippy" in str(i.get("value", "")) for i in data.get("items", []))
# ---------------------------------------------------------------------------
# CYA-WP-0005 T02 — Explicit Profile 0 baseline assertions
# ---------------------------------------------------------------------------

View File

@@ -137,9 +137,11 @@ completed: "2026-05-28 ralph iter 4"
```task
id: CYA-WP-0005-T05
status: todo
status: done
priority: medium
state_hub_task_id: "4b59d4f4-d067-470b-b6c3-30c64cbc1010"
started: "2026-05-28 ralph iter 5 (optional spike)"
completed: "2026-05-28 ralph iter 5"
```
**Description**: If time and review allow, implement a thin but real end-to-end slice of Profile 1 on top of Profile 0: new `kind="reflection"` support (or reuse retrospection), enhancement to `cya retrospect` (or new `cya reflect`) to capture verbal lessons, preferential activation for reflection kinds, rendering in `--explain-context` and final output, tests, and docs. All changes must be small, inspectable, and preserve safety invariants.