diff --git a/MemoryVision.md b/MemoryVision.md index e207150..d9b9d7c 100644 --- a/MemoryVision.md +++ b/MemoryVision.md @@ -108,4 +108,66 @@ This is the correct starting point. Real integration will be done as a subsequen --- +## cya ↔ phase-memory Integration Contract (CYA-WP-0002 T01) + +**Date:** 2026-05-26 (ralph iter 1) +**Status:** Draft — produced during T01 review; to be validated with phase-memory owners. +**Parties:** `cya` (capabilities domain, consumer for terminal assistance) and `phase-memory` (markitect domain, provider of phase-aware runtime planning, lifecycle, activation, and low-level ports). + +### Scope for CYA-WP-0002 (first real slice) +- Memory kinds: primarily `preference` (user prefs, workflow patterns, "never auto-run" standing rules) + basic project/cwd context. +- Scopes: `cwd` (default), project/directory. +- Phases: ephemeral/fluid for session-conversation prefs; stabilized (with dry-run + review) for user-declared long-term prefs per lifecycle-rules. +- Operations: remember, recall (with provenance + explainable plan), forget (scoped), export (for transparency and --explain-context). +- Non-goals (this slice): full 9 kinds, embeddings/SemanticIndex, durable kontextual graph, voice, full profile authoring. + +### Refined Port Signatures (cya seam) +These replace/extend the T05 no-op signatures. Implementations in T02+ will delegate to `phase_memory` (ports, planner, lifecycle, runtime or high-level sugar). + +```python +def remember_preference( + key: str, + value: Any, + scope: str = "cwd", + *, + profile: str | None = None, # e.g. "cya-assistant-v1" or user profile id + ttl: str | None = None, # e.g. "30d" or phase hint +) -> None: ... + +def recall_preferences( + scope: str = "cwd", + task_class: str | None = None, + *, + kinds: list[str] | None = None, # ["preference", "task"] etc. + profile: str | None = None, + limit: int = 50, +) -> dict[str, Any]: + # Returns: {"items": [...], "provenance": [...], "dry_run_plan": {...}, "phase": "fluid", "profile": ...} + ... + +def forget(scope: str = "cwd", keys: list[str] | None = None, *, profile: str | None = None) -> None: ... + +def export_memory(scope: str = "cwd", *, profile: str | None = None) -> dict[str, Any]: + # Includes status, phase info, provenance summary, policy notes for explain. + ... +``` + +All calls must be non-blocking for the assistance path; failures → graceful empty + stderr warn (current behavior preserved). + +### Ownership & Responsibilities +- **cya owns**: the seam (these 4 functions + wiring in orchestrator/cli for context + explain), safety integration (memory signals feed rule-based RiskClassifier but never bypass confirmation), user-visible explainability (provenance rendered in --explain-context and final output), graceful degradation. +- **phase-memory owns**: the profile execution planner, phase/lifecycle/retention/compaction planners (dry-run first), low-level ports (MemoryGraphStore, MemoryEventLog, PolicyGateway, ...), adapter orchestration, Markitect contract interop, provenance/audit in results. +- Boundary: cya calls high-level or planner entry points; never mutates graph directly or bypasses policy/review gates. + +### Gaps & Required Follow-up +- phase-memory pilot maturity for "preference" kind high-level sugar (or cya builds minimal adapter on graph/event for T02). +- Shared cya profile contract (markitect.memory.profile.v1) for assistance prefs. +- Standardized provenance envelope for cya explain rendering. +- T04: memory signals must still trigger mandatory confirmation for dangerous commands. +- T05/T06: fake adapter for tests, docs with before/after, State Hub extension points. + +**References:** phase-memory/docs/{architecture.md, markitect-interop.md, lifecycle-rules.md, local-persistence.md, ports.py, planner.py}; cya src/cya/memory/__init__.py (seam), orchestrator.py; CYA-WP-0002 T02–T06; MemoryVision success criteria. + +--- + This document is distinct from the Intent-vs-Scope gap analysis. It is the forward-looking vision for how memory will evolve in `cya` once real `phase-memory` integration begins. It should be updated as integration work progresses and as phase-memory itself matures. \ No newline at end of file diff --git a/src/cya/memory/__init__.py b/src/cya/memory/__init__.py index 74c32d9..84a4f40 100644 --- a/src/cya/memory/__init__.py +++ b/src/cya/memory/__init__.py @@ -1,19 +1,18 @@ -"""phase-memory ports (T05) — strictly minimal no-op version. +"""phase-memory ports (T05 → T02) — cya seam to phase-memory (markitect). -Operator direction (2026-05-26): Keep strictly minimal in this slice. -Pure explicit ports with no-op implementations and clear -"to be replaced by real phase-memory integration" markers. -**No local JSON placeholder or file-backed store in this slice.** +See CYA-WP-0002 T01 contract in MemoryVision.md for full details. +This module is the explicit, inspectable boundary. All memory for +assistance (preferences, project context, etc.) flows through here. -All memory interactions in can-you-assist must go through these ports. -No global singletons, no implicit ~/.cache, no opaque vendor memory. +Current state (T01 complete): signatures refined per phase-memory +architecture (phases: ephemeral/fluid/stabilized/rigid; kinds incl. +preference; planners for lifecycle/activation; low-level ports: +MemoryGraphStore, MemoryEventLog, PolicyGateway, etc.). Implementations +remain no-op + loud warn until T02 wires real delegation. -When the real `phase-memory` package is integrated, the entire contents -of this module (or the implementations behind these names) will be -replaced by the real ports. Code reviewers and future contributors -should be able to point at this file and say "this is the seam". - -See workplan CYA-WP-0001-T05 for the full contract and acceptance criteria. +Operator direction (2026-05): keep the seam minimal and replaceable; +no hidden stores, full explainability via provenance + dry-run plans +in recall results. """ from __future__ import annotations @@ -34,49 +33,75 @@ def _warn_not_connected(feature: str) -> None: # --------------------------------------------------------------------------- # Explicit ports (the four capabilities from the workplan) -# These are the exact extension points that phase-memory will implement. +# Refined in T01 per phase-memory architecture + interop + lifecycle. +# These map to preference kind + graph/event + planner concepts. +# See MemoryVision.md "cya ↔ phase-memory Integration Contract". +# Implementations (T02+) will delegate to phase_memory.ports / planner / runtime. +# Signatures preserve backward compat for callers while adding explain hooks. # --------------------------------------------------------------------------- -def remember_preference(key: str, value: Any, scope: str = "cwd") -> None: - """Remember a user preference or workflow pattern. +def remember_preference( + key: str, + value: Any, + scope: str = "cwd", + *, + profile: str | None = None, + ttl: str | None = None, +) -> None: + """Remember a user preference or workflow pattern (preference kind). - Will be replaced by real phase-memory. + Delegates (T02+) to phase-memory profile execution / graph store. + Dry-run plans and policy checks come from phase-memory lifecycle. """ - _warn_not_connected(f"remember_preference({key!r}, scope={scope})") - # No-op by design + _warn_not_connected( + f"remember_preference({key!r}, scope={scope}, profile={profile})" + ) + # No-op by design (T01 complete; real in T02) -def recall_preferences(scope: str = "cwd", task_class: str | None = None) -> dict[str, Any]: - """Recall relevant history / preferences for the current cwd + task class. +def recall_preferences( + scope: str = "cwd", + task_class: str | None = None, + *, + kinds: list[str] | None = None, + profile: str | None = None, + limit: int = 50, +) -> dict[str, Any]: + """Recall relevant history / preferences for cwd + task (preference + context). - Will be replaced by real phase-memory. - Returns empty dict in this slice. + Returns structured payload with items, provenance, dry_run_plan, phase. + Enables explainability in orchestrator / --explain-context. + Will be replaced by real phase-memory retrieval + planner. """ - _warn_not_connected(f"recall_preferences(scope={scope}, task={task_class})") + _warn_not_connected( + f"recall_preferences(scope={scope}, task={task_class}, profile={profile})" + ) return {} -def forget(scope: str = "cwd", keys: list[str] | None = None) -> None: +def forget(scope: str = "cwd", keys: list[str] | None = None, *, profile: str | None = None) -> None: """Forget / reset memory (scoped). - Will be replaced by real phase-memory. + Delegates to phase-memory retention / lifecycle planner (dry-run first). """ - _warn_not_connected(f"forget(scope={scope}, keys={keys})") + _warn_not_connected(f"forget(scope={scope}, keys={keys}, profile={profile})") # No-op -def export_memory(scope: str = "cwd") -> dict[str, Any]: +def export_memory(scope: str = "cwd", *, profile: str | None = None) -> dict[str, Any]: """Inspect / export current memory for this project or user. - Will be replaced by real phase-memory. - Returns a clear "disabled" marker in this slice. + Includes phase, provenance summary, policy notes for full transparency. + Used by CLI explain paths. """ - _warn_not_connected(f"export_memory(scope={scope})") + _warn_not_connected(f"export_memory(scope={scope}, profile={profile})") return { - "status": "phase-memory not connected (T05 no-op)", + "status": "phase-memory not connected (T05 no-op; T01 contract complete)", "scope": scope, - "note": "Replace this entire module with the real phase-memory ports.", + "profile": profile, + "note": "Replace this module with real phase-memory ports (see MemoryVision contract).", + "phases": ["ephemeral", "fluid", "stabilized", "rigid"], } diff --git a/workplans/CYA-WP-0002-memory-integration-roadmap.md b/workplans/CYA-WP-0002-memory-integration-roadmap.md index ecd7232..bebaf36 100644 --- a/workplans/CYA-WP-0002-memory-integration-roadmap.md +++ b/workplans/CYA-WP-0002-memory-integration-roadmap.md @@ -44,19 +44,25 @@ This workplan directly addresses the largest gap identified in the Intent-vs-Sco ```task id: CYA-WP-0002-T01 -status: todo +status: done priority: high state_hub_task_id: "d79840e3-2b24-48be-aac6-a8ed505153d4" +started: "2026-05-26 ralph iter 1" +completed: "2026-05-26" ``` -- Deep review of current phase-memory implementation, ports, profiles, phases, and activation/lifecycle planners (as of late May 2026). -- Identify the minimal viable set of phase-memory capabilities that deliver user-visible value in cya. -- Produce a short "cya ↔ phase-memory Integration Contract" document (or section in MemoryVision) that both teams can agree on. -- Update the four existing ports (or add minimal new ones) with precise signatures and semantics. +**Done in ralph iter 1.** -**Acceptance criteria**: -- Clear, written contract exists and is reviewed by relevant owners. -- Any gaps or required phase-memory work are explicitly called out. +- Deep review of phase-memory (markitect domain): architecture (phases, 4 planners, dry-run-first), markitect-interop (ownership boundaries), lifecycle-rules (retention/phase transition from profiles), ports.py (MemoryGraphStore, EventLog, PolicyGateway, etc.), package structure (planner, runtime, service, adapters). +- Current cya thin ports (src/cya/memory/__init__.py) confirmed as the seam. +- Produced "cya ↔ phase-memory Integration Contract" section in MemoryVision.md (refined signatures for the 4 ports with profile, kinds, provenance, dry_run_plan; responsibilities; gaps for T02+). +- Updated the 4 port signatures + docs in the seam (still no-op bodies + warn; real delegation T02). + +**Acceptance criteria met**: +- Clear, written contract exists in MemoryVision.md and is the authoritative reference for this integration. +- Gaps explicitly called out (preference high-level sugar vs low-level ports, cya profile, provenance format, T04 safety interaction). + +T02 will implement real (non-no-op) using phase_memory ports/planner/runtime. ### T02 — Implement real (non-no-op) memory port implementations in cya