generated from coulomb/repo-seed
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:
@@ -115,7 +115,7 @@ Run a guided reflection session to review how memory was used and explicitly set
|
|||||||
cya retrospect
|
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.
|
- Show recent memory items that were activated.
|
||||||
- Help you reflect on what worked or didn't.
|
- 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").
|
- Let you record new **interaction goals** (e.g. "be more concise", "always show one safe alternative for destructive commands").
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ from typing import Any
|
|||||||
KIND_PREFERENCE = "preference"
|
KIND_PREFERENCE = "preference"
|
||||||
KIND_RETROSPECTION = "retrospection"
|
KIND_RETROSPECTION = "retrospection"
|
||||||
KIND_INTERACTION_GOAL = "interaction_goal"
|
KIND_INTERACTION_GOAL = "interaction_goal"
|
||||||
|
KIND_REFLECTION = "reflection" # Profile 1 (Reflexion-style verbal lessons) — T05 minimal spike
|
||||||
|
|
||||||
|
|
||||||
def _warn_not_connected(feature: str) -> None:
|
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)
|
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__ = [
|
__all__ = [
|
||||||
"remember_preference",
|
"remember_preference",
|
||||||
"recall_preferences",
|
"recall_preferences",
|
||||||
"forget",
|
"forget",
|
||||||
"export_memory",
|
"export_memory",
|
||||||
"remember_retrospection_outcome",
|
"remember_retrospection_outcome",
|
||||||
|
"remember_reflection",
|
||||||
"KIND_PREFERENCE",
|
"KIND_PREFERENCE",
|
||||||
"KIND_RETROSPECTION",
|
"KIND_RETROSPECTION",
|
||||||
"KIND_INTERACTION_GOAL",
|
"KIND_INTERACTION_GOAL",
|
||||||
|
"KIND_REFLECTION",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ from cya.context.collector import collect, render_explanation
|
|||||||
from cya.memory import (
|
from cya.memory import (
|
||||||
recall_preferences,
|
recall_preferences,
|
||||||
remember_retrospection_outcome,
|
remember_retrospection_outcome,
|
||||||
|
remember_reflection,
|
||||||
KIND_RETROSPECTION,
|
KIND_RETROSPECTION,
|
||||||
KIND_INTERACTION_GOAL,
|
KIND_INTERACTION_GOAL,
|
||||||
|
KIND_REFLECTION,
|
||||||
)
|
)
|
||||||
from cya.safety.risk import classify, get_user_confirmation
|
from cya.safety.risk import classify, get_user_confirmation
|
||||||
from cya.llm.adapter import AssistanceRequest, FakeLLMAdapter
|
from cya.llm.adapter import AssistanceRequest, FakeLLMAdapter
|
||||||
@@ -85,7 +87,11 @@ def handle_request(
|
|||||||
git_info = envelope.git or {}
|
git_info = envelope.git or {}
|
||||||
if git_info.get("workdir"):
|
if git_info.get("workdir"):
|
||||||
act_ctx["git_root"] = git_info["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:
|
except Exception:
|
||||||
memory = {"error": "recall failed (graceful degradation)"}
|
memory = {"error": "recall failed (graceful degradation)"}
|
||||||
|
|
||||||
@@ -150,6 +156,12 @@ def handle_request(
|
|||||||
mem_line = ""
|
mem_line = ""
|
||||||
if memory.get("items"):
|
if memory.get("items"):
|
||||||
mem_line = f"\n[dim]Memory activated: {len(memory.get('items', []))} items (phase {memory.get('phase')})[/dim]"
|
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(
|
console.print(
|
||||||
Panel(
|
Panel(
|
||||||
f"[bold]Suggestion:[/bold]\n{llm_response.suggestion}\n\n"
|
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]")
|
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(
|
console.print(
|
||||||
Panel(
|
Panel(
|
||||||
"Thank you. Your reflections have been stored as retrospection memory.\n"
|
"Thank you. Your reflections have been stored as retrospection memory.\n"
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ from cya.memory import (
|
|||||||
forget,
|
forget,
|
||||||
export_memory,
|
export_memory,
|
||||||
remember_retrospection_outcome,
|
remember_retrospection_outcome,
|
||||||
|
remember_reflection,
|
||||||
KIND_RETROSPECTION,
|
KIND_RETROSPECTION,
|
||||||
KIND_INTERACTION_GOAL,
|
KIND_INTERACTION_GOAL,
|
||||||
|
KIND_REFLECTION,
|
||||||
)
|
)
|
||||||
from cya.safety.risk import classify, RiskLevel
|
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
|
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
|
# CYA-WP-0005 T02 — Explicit Profile 0 baseline assertions
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -137,9 +137,11 @@ completed: "2026-05-28 ralph iter 4"
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: CYA-WP-0005-T05
|
id: CYA-WP-0005-T05
|
||||||
status: todo
|
status: done
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "4b59d4f4-d067-470b-b6c3-30c64cbc1010"
|
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.
|
**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.
|
||||||
|
|||||||
Reference in New Issue
Block a user