memorix 1.2.6 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +6 -3
- package/README.zh-CN.md +5 -2
- package/dist/cli/index.js +954 -72
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/memcode.js +0 -0
- package/dist/index.js +632 -27
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.js +39 -1
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +12 -0
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.js +632 -27
- package/dist/sdk.js.map +1 -1
- package/dist/types.d.ts +38 -1
- package/dist/types.js.map +1 -1
- package/docs/1.2.7-CONTEXT-CONTINUITY.md +68 -0
- package/docs/API_REFERENCE.md +6 -2
- package/docs/dev-log/progress.txt +23 -0
- package/docs/hooks-architecture.md +2 -1
- package/package.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/omp/memorix/extensions/memorix.js +17 -0
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/extensions/memorix.js +17 -0
- package/plugins/pi/memorix/package.json +1 -1
- package/src/cli/capability-map.ts +1 -0
- package/src/cli/command-guide.ts +10 -0
- package/src/cli/commands/checkpoint.ts +144 -0
- package/src/cli/index.ts +3 -1
- package/src/codegraph/auto-context.ts +51 -5
- package/src/hooks/handler.ts +103 -11
- package/src/hooks/normalizer.ts +85 -1
- package/src/hooks/types.ts +16 -0
- package/src/knowledge/workset.ts +43 -2
- package/src/memory/compaction.ts +165 -0
- package/src/server/tool-profile.ts +1 -0
- package/src/server.ts +94 -0
- package/src/store/compaction-checkpoint-store.ts +397 -0
- package/src/store/sqlite-db.ts +41 -0
- package/src/types.ts +46 -0
package/dist/types.d.ts
CHANGED
|
@@ -141,6 +141,43 @@ interface Session {
|
|
|
141
141
|
/** Agent/IDE that started this session */
|
|
142
142
|
agent?: string;
|
|
143
143
|
}
|
|
144
|
+
/** Whether a checkpoint is still waiting for host compaction or has completed. */
|
|
145
|
+
type CompactionCheckpointPhase = 'pre' | 'complete';
|
|
146
|
+
/** Native compaction reason when the host exposes it. */
|
|
147
|
+
type CompactionReason = 'manual' | 'auto' | 'unknown';
|
|
148
|
+
/** How much first-party compaction evidence the host actually exposed. */
|
|
149
|
+
type CompactionCaptureKind = 'preflight' | 'lifecycle' | 'native-summary';
|
|
150
|
+
/** Lifecycle state for a persisted compaction checkpoint. */
|
|
151
|
+
type CompactionCheckpointStatus = 'active' | 'archived';
|
|
152
|
+
/**
|
|
153
|
+
* A source-aware record of one host-native context compaction.
|
|
154
|
+
*
|
|
155
|
+
* This is intentionally not an Observation: a host summary is evidence for
|
|
156
|
+
* continuation, not automatically durable project truth.
|
|
157
|
+
*/
|
|
158
|
+
interface CompactionCheckpoint {
|
|
159
|
+
id: string;
|
|
160
|
+
projectId: string;
|
|
161
|
+
sessionId: string;
|
|
162
|
+
agent: string;
|
|
163
|
+
phase: CompactionCheckpointPhase;
|
|
164
|
+
captureKind: CompactionCaptureKind;
|
|
165
|
+
reason: CompactionReason;
|
|
166
|
+
sourceEvent: string;
|
|
167
|
+
sourceKey: string;
|
|
168
|
+
summary?: string;
|
|
169
|
+
tokensBefore?: number;
|
|
170
|
+
firstKeptEntryId?: string;
|
|
171
|
+
details?: Record<string, unknown>;
|
|
172
|
+
transcriptAvailable: boolean;
|
|
173
|
+
status: CompactionCheckpointStatus;
|
|
174
|
+
preCapturedAt: string;
|
|
175
|
+
completedAt?: string;
|
|
176
|
+
deliveredAt?: string;
|
|
177
|
+
deliveryCount: number;
|
|
178
|
+
createdAt: string;
|
|
179
|
+
updatedAt: string;
|
|
180
|
+
}
|
|
144
181
|
/** L1 index entry — lightweight, ~50-100 tokens per result */
|
|
145
182
|
interface IndexEntry {
|
|
146
183
|
id: number;
|
|
@@ -453,4 +490,4 @@ interface MCPConfigAdapter {
|
|
|
453
490
|
getConfigPath(projectRoot?: string): string;
|
|
454
491
|
}
|
|
455
492
|
|
|
456
|
-
export { type AgentTarget, DEFAULT_CONFIG, type DetectionFailure, type DetectionFailureReason, type DetectionResult, type DocumentType, type Entity, type IndexEntry, type KnowledgeGraph, type KnowledgeLayer, type MCPConfigAdapter, type MCPServerEntry, type MemorixConfig, type MemorixDocument, type MemoryRef, type MiniSkill, OBSERVATION_ICONS, type Observation, type ObservationAdmissionState, type ObservationReader, type ObservationRef, type ObservationStatus, type ObservationType, type ObservationVisibility, type ProgressInfo, type ProjectInfo, type Relation, type RetrievalQuality, type RuleFormatAdapter, type RuleSource, type SearchOptions, type Session, type SkillConflict, type SkillEntry, type SnapshotObservation, type SourceSnapshot, TOPIC_KEY_FAMILIES, type TimelineContext, type UnifiedRule, type WorkflowEntry, type WorkspaceSyncResult };
|
|
493
|
+
export { type AgentTarget, type CompactionCaptureKind, type CompactionCheckpoint, type CompactionCheckpointPhase, type CompactionCheckpointStatus, type CompactionReason, DEFAULT_CONFIG, type DetectionFailure, type DetectionFailureReason, type DetectionResult, type DocumentType, type Entity, type IndexEntry, type KnowledgeGraph, type KnowledgeLayer, type MCPConfigAdapter, type MCPServerEntry, type MemorixConfig, type MemorixDocument, type MemoryRef, type MiniSkill, OBSERVATION_ICONS, type Observation, type ObservationAdmissionState, type ObservationReader, type ObservationRef, type ObservationStatus, type ObservationType, type ObservationVisibility, type ProgressInfo, type ProjectInfo, type Relation, type RetrievalQuality, type RuleFormatAdapter, type RuleSource, type SearchOptions, type Session, type SkillConflict, type SkillEntry, type SnapshotObservation, type SourceSnapshot, TOPIC_KEY_FAMILIES, type TimelineContext, type UnifiedRule, type WorkflowEntry, type WorkspaceSyncResult };
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Memorix Core Types\n *\n * Data model sources:\n * - Entity/Relation/KnowledgeGraph: MCP Official Memory Server (v0.6.3)\n * - Observation/ObservationType: claude-mem Progressive Disclosure\n * - UnifiedRule/RuleSource: Memorix original (rules sync)\n *\n * Designed for extensibility: new agent formats (Kiro, Copilot, Antigravity)\n * can be added by extending RuleSource and adding format adapters.\n */\n\n// ============================================================\n// Knowledge Graph (adopted from MCP Official Memory Server)\n// ============================================================\n\n/** A node in the knowledge graph representing a concept, component, or config */\nexport interface Entity {\n name: string;\n entityType: string;\n observations: string[];\n}\n\n/** A directed edge between two entities */\nexport interface Relation {\n from: string;\n to: string;\n relationType: string;\n}\n\n/** The complete knowledge graph */\nexport interface KnowledgeGraph {\n entities: Entity[];\n relations: Relation[];\n}\n\n// ============================================================\n// Observation (adopted from claude-mem Progressive Disclosure)\n// ============================================================\n\n/**\n * Observation type classification using claude-mem's icon-based legend system.\n *\n * Icon mapping:\n * [SESSION] session-request — User's original goal\n * [GOTCHA] gotcha — Critical pitfall / trap\n * [FIX] problem-solution — Bug fix or workaround\n * [INFO] how-it-works — Technical explanation\n * [CHANGE] what-changed — Code/architecture change\n * [DISCOVERY] discovery — New learning or insight\n * [WHY] why-it-exists — Design rationale\n * [DECISION] decision — Architecture decision\n * [TRADEOFF] trade-off — Deliberate compromise\n * [REASONING] reasoning — Why this approach was chosen (System 2 reasoning trace)\n * [PROBE] probe — Operational heartbeat / connectivity check (short-lived, excluded from default search)\n */\nexport type ObservationType =\n | 'session-request'\n | 'gotcha'\n | 'problem-solution'\n | 'how-it-works'\n | 'what-changed'\n | 'discovery'\n | 'why-it-exists'\n | 'decision'\n | 'trade-off'\n | 'reasoning'\n | 'probe';\n\n/** Map from ObservationType to display icon */\nexport const OBSERVATION_ICONS: Record<ObservationType, string> = {\n 'session-request': '[SESSION]',\n 'gotcha': '[GOTCHA]',\n 'problem-solution': '[FIX]',\n 'how-it-works': '[INFO]',\n 'what-changed': '[CHANGE]',\n 'discovery': '[DISCOVERY]',\n 'why-it-exists': '[WHY]',\n 'decision': '[DECISION]',\n 'trade-off': '[TRADEOFF]',\n 'reasoning': '[REASONING]',\n 'probe': '[PROBE]',\n};\n\n/** Observation lifecycle status */\nexport type ObservationStatus = 'active' | 'resolved' | 'archived';\n\n/**\n * Control-plane admission state for automatically captured observations.\n * Candidate and ephemeral records remain inspectable, but only qualified\n * records are eligible for automatic context delivery. Missing state preserves\n * legacy behavior for observations written before this policy existed.\n */\nexport type ObservationAdmissionState = 'ephemeral' | 'candidate' | 'qualified';\n\n/**\n * Who may retrieve an observation through agent-facing memory surfaces.\n * Missing visibility is a legacy record and resolves to `project`.\n */\nexport type ObservationVisibility = 'personal' | 'project' | 'team';\n\n/**\n * Identity available to an agent-facing retrieval call. Internal maintenance\n * deliberately omits this and may inspect all project records for lifecycle work.\n */\nexport interface ObservationReader {\n /** Bound project for a normal project-scoped call. Omit only for explicit global search. */\n projectId?: string;\n /** Stable coordination identity, available after an explicit team join. */\n agentId?: string;\n /** True only when agentId is an active member of the bound project team. */\n isTeamMember?: boolean;\n}\n\n/** Progress tracking for task/feature observations */\nexport interface ProgressInfo {\n feature: string;\n status: 'in-progress' | 'completed' | 'blocked';\n completion?: number;\n}\n\n/** A rich observation record attached to an entity */\nexport interface Observation {\n id: number;\n entityName: string;\n type: ObservationType;\n title: string;\n narrative: string;\n facts: string[];\n filesModified: string[];\n concepts: string[];\n tokens: number;\n createdAt: string;\n updatedAt?: string;\n projectId: string;\n /** Whether the observation contains causal language (because, due to, etc.) */\n hasCausalLanguage?: boolean;\n /** Optional topic key for upsert — same project+topicKey updates existing observation */\n topicKey?: string;\n /** How many times this observation was revised via topic key upsert (starts at 1) */\n revisionCount?: number;\n /** Session ID this observation belongs to */\n sessionId?: string;\n /** Lifecycle status: active (default) → resolved → archived */\n status?: ObservationStatus;\n /** ID of the observation that superseded this one (set when auto-resolved by topicKey upsert) */\n supersededBy?: number;\n /** Progress tracking for task/feature observations */\n progress?: ProgressInfo;\n /** Origin of this observation: agent (IDE hooks/MCP), git (commit ingest), manual (CLI) */\n source?: 'agent' | 'git' | 'manual';\n /** Git commit hash if source is 'git' */\n commitHash?: string;\n /** Related commit hashes — links reasoning memories to the commits they explain */\n relatedCommits?: string[];\n /** Related entity names — explicit cross-references to other memory entities */\n relatedEntities?: string[];\n /** Provenance detail: how this observation entered the system */\n sourceDetail?: 'explicit' | 'hook' | 'git-ingest';\n /** Value category from formation pipeline evaluation */\n valueCategory?: 'core' | 'contextual' | 'ephemeral';\n /** Control-plane admission state for automatic capture and delivery. */\n admissionState?: ObservationAdmissionState;\n /** Short, sanitized explanation for the latest admission decision. */\n admissionReason?: string;\n /** Retrieval scope. Legacy records without a value remain project-visible. */\n visibility?: ObservationVisibility;\n /** Explicit additional readers for a personal record, used by targeted handoffs. */\n sharedWithAgentIds?: string[];\n /** Phase 4a: Agent ID that created this observation (team attribution) */\n createdByAgentId?: string;\n /** Phase 4a: Monotonic write generation — snapshot of storage_generation at write time (watermark coherence) */\n writeGeneration?: number;\n}\n\n// ============================================================\n// Session Lifecycle (inspired by Engram's session management)\n// ============================================================\n\n/** A coding session tracked by Memorix */\nexport interface Session {\n id: string;\n projectId: string;\n startedAt: string;\n endedAt?: string;\n summary?: string;\n status: 'active' | 'completed';\n /** Agent/IDE that started this session */\n agent?: string;\n}\n\n// ============================================================\n// Compact Engine (adopted from claude-mem 3-layer workflow)\n// ============================================================\n\n/** L1 index entry — lightweight, ~50-100 tokens per result */\nexport interface IndexEntry {\n id: number;\n time: string;\n type: ObservationType;\n icon: string;\n title: string;\n tokens: number;\n /** Relevance score from search (time-decayed). Used by compact engine. */\n score?: number;\n /** Project that owns this observation. Needed to disambiguate global results. */\n projectId?: string;\n /** Origin of the memory for source-aware retrieval and display. */\n source?: 'agent' | 'git' | 'manual';\n /** Provenance detail for source-aware display */\n sourceDetail?: 'explicit' | 'hook' | 'git-ingest';\n /** Value category for source-aware ranking */\n valueCategory?: 'core' | 'contextual' | 'ephemeral';\n /** Control-plane admission state when known. */\n admissionState?: ObservationAdmissionState;\n /** Retrieval scope when known. */\n visibility?: ObservationVisibility;\n /** Explainable recall: why this result matched. */\n matchedFields?: string[];\n /** Entity name — used for entity-affinity scoring and workstream deduplication. */\n entityName?: string;\n /** Document type: observation or mini-skill (Phase 3a) */\n documentType?: DocumentType;\n /** Knowledge layer for layer-aware ranking (Phase 3a) */\n knowledgeLayer?: KnowledgeLayer;\n}\n\n/** Explicit reference to an observation, optionally scoped to a project. */\nexport interface ObservationRef {\n id: number;\n projectId?: string;\n}\n\n/** L2 timeline context — observations around an anchor */\nexport interface TimelineContext {\n anchorId: number;\n anchorEntry: IndexEntry | null;\n before: IndexEntry[];\n after: IndexEntry[];\n}\n\n/** Retrieval work allowed for a search request. */\nexport type RetrievalQuality = 'fast' | 'balanced' | 'thorough';\n\n/** Search options for the compact engine */\nexport interface SearchOptions {\n query: string;\n limit?: number;\n type?: ObservationType;\n projectId?: string;\n since?: string;\n until?: string;\n /** Token budget — trim results to fit within this many tokens (0 = unlimited) */\n maxTokens?: number;\n /** Filter by observation status. Default: 'active' (only show active memories) */\n status?: ObservationStatus | 'all';\n /** Filter by observation source: 'agent', 'git', 'manual', or undefined for all */\n source?: 'agent' | 'git' | 'manual';\n /** Internal observability probes can disable access tracking without affecting normal search behavior. */\n trackAccess?: boolean;\n /** Internal reader context for agent-facing visibility filtering. */\n reader?: ObservationReader;\n /**\n * `fast` stays fully local, `balanced` (default) permits embeddings, and\n * `thorough` explicitly permits optional LLM query rewrite and reranking.\n */\n quality?: RetrievalQuality;\n}\n\n/** Topic key family heuristics for suggesting stable topic keys */\nexport const TOPIC_KEY_FAMILIES: Record<string, string[]> = {\n 'architecture': ['architecture', 'design', 'adr', 'structure', 'pattern'],\n 'bug': ['bugfix', 'fix', 'error', 'regression', 'crash', 'problem-solution'],\n 'decision': ['decision', 'trade-off', 'choice', 'strategy'],\n 'config': ['config', 'setup', 'env', 'environment', 'deployment'],\n 'discovery': ['discovery', 'learning', 'insight', 'gotcha'],\n 'pattern': ['pattern', 'convention', 'standard', 'best-practice'],\n};\n\n// ============================================================\n// Orama Document Schema\n// ============================================================\n\n/** The document shape stored in Orama */\nexport interface MemorixDocument {\n id: string;\n observationId: number;\n entityName: string;\n type: string;\n title: string;\n narrative: string;\n facts: string;\n filesModified: string;\n concepts: string;\n tokens: number;\n createdAt: string;\n projectId: string;\n /** Number of times this observation was returned in search results */\n accessCount: number;\n /** ISO timestamp of last access via search/detail */\n lastAccessedAt: string;\n /** Lifecycle status: active, resolved, archived */\n status: string;\n /** Origin: agent, git, manual */\n source: string;\n /** Provenance detail: explicit, hook, or git-ingest */\n sourceDetail?: string;\n /** Value category from formation evaluation */\n valueCategory?: string;\n /** Control-plane admission state for automatic capture and delivery. */\n admissionState?: string;\n /** Short, sanitized explanation for the latest admission decision. */\n admissionReason?: string;\n /** Retrieval scope for agent-facing filtering. */\n visibility?: string;\n /** Agent that owns a personal record, or authored a shared record. */\n createdByAgentId?: string;\n /** Explicit readers for a targeted personal record. */\n sharedWithAgentIds?: string;\n /** Optional vector embedding for semantic/hybrid retrieval */\n embedding?: number[];\n /** Document type: observation or mini-skill (Phase 3a) */\n documentType?: DocumentType;\n /** Knowledge layer for layer-aware ranking (Phase 3a) */\n knowledgeLayer?: KnowledgeLayer;\n}\n\n// ============================================================\n// Rules System (Memorix original — extensible for new agents)\n// ============================================================\n\n/**\n * Supported agent/IDE rule sources.\n * All 7 major AI IDEs are supported.\n */\nexport type RuleSource =\n | 'cursor'\n | 'claude-code'\n | 'codex'\n | 'windsurf'\n | 'antigravity'\n | 'gemini-cli'\n | 'copilot'\n | 'kiro'\n | 'trae'\n | 'memorix';\n\n/** A parsed rule in the unified intermediate representation */\nexport interface UnifiedRule {\n id: string;\n content: string;\n description?: string;\n source: RuleSource;\n scope: 'global' | 'project' | 'path-specific';\n paths?: string[];\n alwaysApply?: boolean;\n priority: number;\n hash: string;\n}\n\n/**\n * Format adapter interface — implement this for each agent/IDE.\n * Adding a new agent (e.g., Kiro) only requires implementing this interface.\n */\nexport interface RuleFormatAdapter {\n /** Unique identifier for this agent format */\n readonly source: RuleSource;\n\n /** File paths/globs this adapter can parse */\n readonly filePatterns: string[];\n\n /** Parse rule files into unified representation */\n parse(filePath: string, content: string): UnifiedRule[];\n\n /** Generate rule file content from unified representation */\n generate(rules: UnifiedRule[]): { filePath: string; content: string }[];\n}\n\n// ============================================================\n// Project Identity\n// ============================================================\n\nexport interface ProjectInfo {\n id: string;\n name: string;\n gitRemote?: string;\n rootPath: string;\n}\n\n/**\n * Diagnostic failure info from project detection.\n * Tells callers exactly WHY detection failed so they can report actionable errors.\n */\nexport type DetectionFailureReason =\n | 'path_not_found'\n | 'not_a_directory'\n | 'no_git'\n | 'git_worktree_error'\n | 'git_safe_directory'\n | 'remote_resolve_failed';\n\nexport interface DetectionFailure {\n reason: DetectionFailureReason;\n path: string;\n detail: string;\n}\n\nexport interface DetectionResult {\n project: ProjectInfo | null;\n failure: DetectionFailure | null;\n}\n\n// ============================================================\n// Memorix Server Configuration\n// ============================================================\n\nexport interface MemorixConfig {\n dataDir: string;\n projectId: string;\n projectName: string;\n enableEmbeddings: boolean;\n enableRulesSync: boolean;\n watchRuleFiles: boolean;\n}\n\nexport const DEFAULT_CONFIG: Partial<MemorixConfig> = {\n enableEmbeddings: false,\n enableRulesSync: false,\n watchRuleFiles: false,\n};\n\n// ============================================================\n// Workspace Sync — Cross-Agent workspace migration\n// ============================================================\n\n/** Supported agent targets for workspace sync */\nexport type AgentTarget =\n | 'windsurf'\n | 'cursor'\n | 'claude-code'\n | 'codex'\n | 'copilot'\n | 'antigravity'\n | 'gemini-cli'\n | 'openclaw'\n | 'hermes'\n | 'omp'\n | 'kiro'\n | 'opencode'\n | 'trae';\n\n/** A unified MCP server entry across all agent config formats */\nexport interface MCPServerEntry {\n name: string;\n /** Command for stdio transport */\n command: string;\n /** Args for stdio transport */\n args: string[];\n /** Environment variables */\n env?: Record<string, string> | null;\n /** URL for HTTP/SSE transport (Codex uses `url`, Windsurf uses `serverUrl`) */\n url?: string;\n /** HTTP headers (Windsurf uses `headers` for HTTP transport) */\n headers?: Record<string, string>;\n /** Whether this server is disabled */\n disabled?: boolean;\n /** Claude Code: force small core tool sets to load before the first prompt */\n alwaysLoad?: boolean;\n}\n\n/** Unified workflow entry */\nexport interface WorkflowEntry {\n name: string;\n description: string;\n content: string;\n source: AgentTarget;\n filePath: string;\n}\n\n/** A skill folder discovered from an agent's skills directory */\nexport interface SkillEntry {\n name: string;\n description: string;\n sourcePath: string;\n sourceAgent: AgentTarget;\n}\n\n/** Conflict when two agents have a skill with the same folder name */\nexport interface SkillConflict {\n name: string;\n kept: SkillEntry;\n skipped: SkillEntry;\n}\n\n/** Result of a workspace sync operation */\nexport interface WorkspaceSyncResult {\n mcpServers: {\n scanned: MCPServerEntry[];\n generated: { filePath: string; content: string }[];\n };\n workflows: {\n scanned: WorkflowEntry[];\n generated: { filePath: string; content: string }[];\n };\n rules: {\n scanned: number;\n generated: number;\n };\n skills: {\n scanned: SkillEntry[];\n conflicts: SkillConflict[];\n copied: string[];\n skipped: string[];\n };\n}\n\n// ============================================================\n// Mini-Skills — Promoted memories that never decay\n// ============================================================\n\n/** A mini-skill promoted from one or more observations */\nexport interface MiniSkill {\n id: number;\n /** Observation IDs this mini-skill was derived from (live refs, best-effort) */\n sourceObservationIds: number[];\n /** Entity the source observations belong to */\n sourceEntity: string;\n /** Short title for the skill */\n title: string;\n /** What the agent should do (imperative instruction) */\n instruction: string;\n /** When this skill should be applied (scenario description) */\n trigger: string;\n /** Key facts extracted from source observations */\n facts: string[];\n /** Project this skill belongs to */\n projectId: string;\n /** ISO timestamp */\n createdAt: string;\n /** How many times this skill was injected in session_start */\n usedCount: number;\n /** Classification tags */\n tags: string[];\n /** Frozen source observation content at promote time (JSON, immutable provenance proof) */\n sourceSnapshot?: string;\n /** ISO timestamp of last modification (Phase 3a: set once at creation) */\n updatedAt?: string;\n}\n\n// ============================================================\n// Source Snapshot — immutable provenance proof for promoted knowledge\n// ============================================================\n\n/** A single observation entry within a source snapshot */\nexport interface SnapshotObservation {\n id: number;\n title: string;\n type: string;\n narrative: string;\n facts: string[];\n entityName: string;\n projectId: string;\n createdAt: string;\n /** Frozen source detail for provenance (explicit / hook / git-ingest) */\n sourceDetail?: string;\n}\n\n/** Frozen source content captured at promote time */\nexport interface SourceSnapshot {\n observations: SnapshotObservation[];\n promotedAt: string;\n}\n\n// ============================================================\n// Knowledge Layer — Phase 3a retrieval classification\n// ============================================================\n\n/** Classification of knowledge for layer-aware ranking */\nexport type KnowledgeLayer = 'project-truth' | 'promoted' | 'evidence';\n\n/** Document type discriminator for Orama index */\nexport type DocumentType = 'observation' | 'mini-skill';\n\n// ============================================================\n// Typed Memory Reference — Phase 3a reference protocol\n// ============================================================\n\n/** A typed reference to a memory object (observation or mini-skill) */\nexport interface MemoryRef {\n kind: 'obs' | 'skill';\n id: number;\n projectId?: string;\n}\n\n/** MCP config format adapter interface */\nexport interface MCPConfigAdapter {\n readonly source: AgentTarget;\n /** Parse MCP server entries from a config file */\n parse(content: string): MCPServerEntry[];\n /** Generate config file content from MCP server entries */\n generate(servers: MCPServerEntry[]): string;\n /** Get the default config file path for this agent */\n getConfigPath(projectRoot?: string): string;\n}\n"],"mappings":";AAsEO,IAAM,oBAAqD;AAAA,EAChE,mBAAmB;AAAA,EACnB,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,aAAa;AAAA,EACb,SAAS;AACX;AA4LO,IAAM,qBAA+C;AAAA,EAC1D,gBAAgB,CAAC,gBAAgB,UAAU,OAAO,aAAa,SAAS;AAAA,EACxE,OAAO,CAAC,UAAU,OAAO,SAAS,cAAc,SAAS,kBAAkB;AAAA,EAC3E,YAAY,CAAC,YAAY,aAAa,UAAU,UAAU;AAAA,EAC1D,UAAU,CAAC,UAAU,SAAS,OAAO,eAAe,YAAY;AAAA,EAChE,aAAa,CAAC,aAAa,YAAY,WAAW,QAAQ;AAAA,EAC1D,WAAW,CAAC,WAAW,cAAc,YAAY,eAAe;AAClE;AAoJO,IAAM,iBAAyC;AAAA,EACpD,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,gBAAgB;AAClB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Memorix Core Types\n *\n * Data model sources:\n * - Entity/Relation/KnowledgeGraph: MCP Official Memory Server (v0.6.3)\n * - Observation/ObservationType: claude-mem Progressive Disclosure\n * - UnifiedRule/RuleSource: Memorix original (rules sync)\n *\n * Designed for extensibility: new agent formats (Kiro, Copilot, Antigravity)\n * can be added by extending RuleSource and adding format adapters.\n */\n\n// ============================================================\n// Knowledge Graph (adopted from MCP Official Memory Server)\n// ============================================================\n\n/** A node in the knowledge graph representing a concept, component, or config */\nexport interface Entity {\n name: string;\n entityType: string;\n observations: string[];\n}\n\n/** A directed edge between two entities */\nexport interface Relation {\n from: string;\n to: string;\n relationType: string;\n}\n\n/** The complete knowledge graph */\nexport interface KnowledgeGraph {\n entities: Entity[];\n relations: Relation[];\n}\n\n// ============================================================\n// Observation (adopted from claude-mem Progressive Disclosure)\n// ============================================================\n\n/**\n * Observation type classification using claude-mem's icon-based legend system.\n *\n * Icon mapping:\n * [SESSION] session-request — User's original goal\n * [GOTCHA] gotcha — Critical pitfall / trap\n * [FIX] problem-solution — Bug fix or workaround\n * [INFO] how-it-works — Technical explanation\n * [CHANGE] what-changed — Code/architecture change\n * [DISCOVERY] discovery — New learning or insight\n * [WHY] why-it-exists — Design rationale\n * [DECISION] decision — Architecture decision\n * [TRADEOFF] trade-off — Deliberate compromise\n * [REASONING] reasoning — Why this approach was chosen (System 2 reasoning trace)\n * [PROBE] probe — Operational heartbeat / connectivity check (short-lived, excluded from default search)\n */\nexport type ObservationType =\n | 'session-request'\n | 'gotcha'\n | 'problem-solution'\n | 'how-it-works'\n | 'what-changed'\n | 'discovery'\n | 'why-it-exists'\n | 'decision'\n | 'trade-off'\n | 'reasoning'\n | 'probe';\n\n/** Map from ObservationType to display icon */\nexport const OBSERVATION_ICONS: Record<ObservationType, string> = {\n 'session-request': '[SESSION]',\n 'gotcha': '[GOTCHA]',\n 'problem-solution': '[FIX]',\n 'how-it-works': '[INFO]',\n 'what-changed': '[CHANGE]',\n 'discovery': '[DISCOVERY]',\n 'why-it-exists': '[WHY]',\n 'decision': '[DECISION]',\n 'trade-off': '[TRADEOFF]',\n 'reasoning': '[REASONING]',\n 'probe': '[PROBE]',\n};\n\n/** Observation lifecycle status */\nexport type ObservationStatus = 'active' | 'resolved' | 'archived';\n\n/**\n * Control-plane admission state for automatically captured observations.\n * Candidate and ephemeral records remain inspectable, but only qualified\n * records are eligible for automatic context delivery. Missing state preserves\n * legacy behavior for observations written before this policy existed.\n */\nexport type ObservationAdmissionState = 'ephemeral' | 'candidate' | 'qualified';\n\n/**\n * Who may retrieve an observation through agent-facing memory surfaces.\n * Missing visibility is a legacy record and resolves to `project`.\n */\nexport type ObservationVisibility = 'personal' | 'project' | 'team';\n\n/**\n * Identity available to an agent-facing retrieval call. Internal maintenance\n * deliberately omits this and may inspect all project records for lifecycle work.\n */\nexport interface ObservationReader {\n /** Bound project for a normal project-scoped call. Omit only for explicit global search. */\n projectId?: string;\n /** Stable coordination identity, available after an explicit team join. */\n agentId?: string;\n /** True only when agentId is an active member of the bound project team. */\n isTeamMember?: boolean;\n}\n\n/** Progress tracking for task/feature observations */\nexport interface ProgressInfo {\n feature: string;\n status: 'in-progress' | 'completed' | 'blocked';\n completion?: number;\n}\n\n/** A rich observation record attached to an entity */\nexport interface Observation {\n id: number;\n entityName: string;\n type: ObservationType;\n title: string;\n narrative: string;\n facts: string[];\n filesModified: string[];\n concepts: string[];\n tokens: number;\n createdAt: string;\n updatedAt?: string;\n projectId: string;\n /** Whether the observation contains causal language (because, due to, etc.) */\n hasCausalLanguage?: boolean;\n /** Optional topic key for upsert — same project+topicKey updates existing observation */\n topicKey?: string;\n /** How many times this observation was revised via topic key upsert (starts at 1) */\n revisionCount?: number;\n /** Session ID this observation belongs to */\n sessionId?: string;\n /** Lifecycle status: active (default) → resolved → archived */\n status?: ObservationStatus;\n /** ID of the observation that superseded this one (set when auto-resolved by topicKey upsert) */\n supersededBy?: number;\n /** Progress tracking for task/feature observations */\n progress?: ProgressInfo;\n /** Origin of this observation: agent (IDE hooks/MCP), git (commit ingest), manual (CLI) */\n source?: 'agent' | 'git' | 'manual';\n /** Git commit hash if source is 'git' */\n commitHash?: string;\n /** Related commit hashes — links reasoning memories to the commits they explain */\n relatedCommits?: string[];\n /** Related entity names — explicit cross-references to other memory entities */\n relatedEntities?: string[];\n /** Provenance detail: how this observation entered the system */\n sourceDetail?: 'explicit' | 'hook' | 'git-ingest';\n /** Value category from formation pipeline evaluation */\n valueCategory?: 'core' | 'contextual' | 'ephemeral';\n /** Control-plane admission state for automatic capture and delivery. */\n admissionState?: ObservationAdmissionState;\n /** Short, sanitized explanation for the latest admission decision. */\n admissionReason?: string;\n /** Retrieval scope. Legacy records without a value remain project-visible. */\n visibility?: ObservationVisibility;\n /** Explicit additional readers for a personal record, used by targeted handoffs. */\n sharedWithAgentIds?: string[];\n /** Phase 4a: Agent ID that created this observation (team attribution) */\n createdByAgentId?: string;\n /** Phase 4a: Monotonic write generation — snapshot of storage_generation at write time (watermark coherence) */\n writeGeneration?: number;\n}\n\n// ============================================================\n// Session Lifecycle (inspired by Engram's session management)\n// ============================================================\n\n/** A coding session tracked by Memorix */\nexport interface Session {\n id: string;\n projectId: string;\n startedAt: string;\n endedAt?: string;\n summary?: string;\n status: 'active' | 'completed';\n /** Agent/IDE that started this session */\n agent?: string;\n}\n\n// ============================================================\n// Cross-Agent Compaction Continuity\n// ============================================================\n\n/** Whether a checkpoint is still waiting for host compaction or has completed. */\nexport type CompactionCheckpointPhase = 'pre' | 'complete';\n\n/** Native compaction reason when the host exposes it. */\nexport type CompactionReason = 'manual' | 'auto' | 'unknown';\n\n/** How much first-party compaction evidence the host actually exposed. */\nexport type CompactionCaptureKind = 'preflight' | 'lifecycle' | 'native-summary';\n\n/** Lifecycle state for a persisted compaction checkpoint. */\nexport type CompactionCheckpointStatus = 'active' | 'archived';\n\n/**\n * A source-aware record of one host-native context compaction.\n *\n * This is intentionally not an Observation: a host summary is evidence for\n * continuation, not automatically durable project truth.\n */\nexport interface CompactionCheckpoint {\n id: string;\n projectId: string;\n sessionId: string;\n agent: string;\n phase: CompactionCheckpointPhase;\n captureKind: CompactionCaptureKind;\n reason: CompactionReason;\n sourceEvent: string;\n sourceKey: string;\n summary?: string;\n tokensBefore?: number;\n firstKeptEntryId?: string;\n details?: Record<string, unknown>;\n transcriptAvailable: boolean;\n status: CompactionCheckpointStatus;\n preCapturedAt: string;\n completedAt?: string;\n deliveredAt?: string;\n deliveryCount: number;\n createdAt: string;\n updatedAt: string;\n}\n\n// ============================================================\n// Compact Engine (adopted from claude-mem 3-layer workflow)\n// ============================================================\n\n/** L1 index entry — lightweight, ~50-100 tokens per result */\nexport interface IndexEntry {\n id: number;\n time: string;\n type: ObservationType;\n icon: string;\n title: string;\n tokens: number;\n /** Relevance score from search (time-decayed). Used by compact engine. */\n score?: number;\n /** Project that owns this observation. Needed to disambiguate global results. */\n projectId?: string;\n /** Origin of the memory for source-aware retrieval and display. */\n source?: 'agent' | 'git' | 'manual';\n /** Provenance detail for source-aware display */\n sourceDetail?: 'explicit' | 'hook' | 'git-ingest';\n /** Value category for source-aware ranking */\n valueCategory?: 'core' | 'contextual' | 'ephemeral';\n /** Control-plane admission state when known. */\n admissionState?: ObservationAdmissionState;\n /** Retrieval scope when known. */\n visibility?: ObservationVisibility;\n /** Explainable recall: why this result matched. */\n matchedFields?: string[];\n /** Entity name — used for entity-affinity scoring and workstream deduplication. */\n entityName?: string;\n /** Document type: observation or mini-skill (Phase 3a) */\n documentType?: DocumentType;\n /** Knowledge layer for layer-aware ranking (Phase 3a) */\n knowledgeLayer?: KnowledgeLayer;\n}\n\n/** Explicit reference to an observation, optionally scoped to a project. */\nexport interface ObservationRef {\n id: number;\n projectId?: string;\n}\n\n/** L2 timeline context — observations around an anchor */\nexport interface TimelineContext {\n anchorId: number;\n anchorEntry: IndexEntry | null;\n before: IndexEntry[];\n after: IndexEntry[];\n}\n\n/** Retrieval work allowed for a search request. */\nexport type RetrievalQuality = 'fast' | 'balanced' | 'thorough';\n\n/** Search options for the compact engine */\nexport interface SearchOptions {\n query: string;\n limit?: number;\n type?: ObservationType;\n projectId?: string;\n since?: string;\n until?: string;\n /** Token budget — trim results to fit within this many tokens (0 = unlimited) */\n maxTokens?: number;\n /** Filter by observation status. Default: 'active' (only show active memories) */\n status?: ObservationStatus | 'all';\n /** Filter by observation source: 'agent', 'git', 'manual', or undefined for all */\n source?: 'agent' | 'git' | 'manual';\n /** Internal observability probes can disable access tracking without affecting normal search behavior. */\n trackAccess?: boolean;\n /** Internal reader context for agent-facing visibility filtering. */\n reader?: ObservationReader;\n /**\n * `fast` stays fully local, `balanced` (default) permits embeddings, and\n * `thorough` explicitly permits optional LLM query rewrite and reranking.\n */\n quality?: RetrievalQuality;\n}\n\n/** Topic key family heuristics for suggesting stable topic keys */\nexport const TOPIC_KEY_FAMILIES: Record<string, string[]> = {\n 'architecture': ['architecture', 'design', 'adr', 'structure', 'pattern'],\n 'bug': ['bugfix', 'fix', 'error', 'regression', 'crash', 'problem-solution'],\n 'decision': ['decision', 'trade-off', 'choice', 'strategy'],\n 'config': ['config', 'setup', 'env', 'environment', 'deployment'],\n 'discovery': ['discovery', 'learning', 'insight', 'gotcha'],\n 'pattern': ['pattern', 'convention', 'standard', 'best-practice'],\n};\n\n// ============================================================\n// Orama Document Schema\n// ============================================================\n\n/** The document shape stored in Orama */\nexport interface MemorixDocument {\n id: string;\n observationId: number;\n entityName: string;\n type: string;\n title: string;\n narrative: string;\n facts: string;\n filesModified: string;\n concepts: string;\n tokens: number;\n createdAt: string;\n projectId: string;\n /** Number of times this observation was returned in search results */\n accessCount: number;\n /** ISO timestamp of last access via search/detail */\n lastAccessedAt: string;\n /** Lifecycle status: active, resolved, archived */\n status: string;\n /** Origin: agent, git, manual */\n source: string;\n /** Provenance detail: explicit, hook, or git-ingest */\n sourceDetail?: string;\n /** Value category from formation evaluation */\n valueCategory?: string;\n /** Control-plane admission state for automatic capture and delivery. */\n admissionState?: string;\n /** Short, sanitized explanation for the latest admission decision. */\n admissionReason?: string;\n /** Retrieval scope for agent-facing filtering. */\n visibility?: string;\n /** Agent that owns a personal record, or authored a shared record. */\n createdByAgentId?: string;\n /** Explicit readers for a targeted personal record. */\n sharedWithAgentIds?: string;\n /** Optional vector embedding for semantic/hybrid retrieval */\n embedding?: number[];\n /** Document type: observation or mini-skill (Phase 3a) */\n documentType?: DocumentType;\n /** Knowledge layer for layer-aware ranking (Phase 3a) */\n knowledgeLayer?: KnowledgeLayer;\n}\n\n// ============================================================\n// Rules System (Memorix original — extensible for new agents)\n// ============================================================\n\n/**\n * Supported agent/IDE rule sources.\n * All 7 major AI IDEs are supported.\n */\nexport type RuleSource =\n | 'cursor'\n | 'claude-code'\n | 'codex'\n | 'windsurf'\n | 'antigravity'\n | 'gemini-cli'\n | 'copilot'\n | 'kiro'\n | 'trae'\n | 'memorix';\n\n/** A parsed rule in the unified intermediate representation */\nexport interface UnifiedRule {\n id: string;\n content: string;\n description?: string;\n source: RuleSource;\n scope: 'global' | 'project' | 'path-specific';\n paths?: string[];\n alwaysApply?: boolean;\n priority: number;\n hash: string;\n}\n\n/**\n * Format adapter interface — implement this for each agent/IDE.\n * Adding a new agent (e.g., Kiro) only requires implementing this interface.\n */\nexport interface RuleFormatAdapter {\n /** Unique identifier for this agent format */\n readonly source: RuleSource;\n\n /** File paths/globs this adapter can parse */\n readonly filePatterns: string[];\n\n /** Parse rule files into unified representation */\n parse(filePath: string, content: string): UnifiedRule[];\n\n /** Generate rule file content from unified representation */\n generate(rules: UnifiedRule[]): { filePath: string; content: string }[];\n}\n\n// ============================================================\n// Project Identity\n// ============================================================\n\nexport interface ProjectInfo {\n id: string;\n name: string;\n gitRemote?: string;\n rootPath: string;\n}\n\n/**\n * Diagnostic failure info from project detection.\n * Tells callers exactly WHY detection failed so they can report actionable errors.\n */\nexport type DetectionFailureReason =\n | 'path_not_found'\n | 'not_a_directory'\n | 'no_git'\n | 'git_worktree_error'\n | 'git_safe_directory'\n | 'remote_resolve_failed';\n\nexport interface DetectionFailure {\n reason: DetectionFailureReason;\n path: string;\n detail: string;\n}\n\nexport interface DetectionResult {\n project: ProjectInfo | null;\n failure: DetectionFailure | null;\n}\n\n// ============================================================\n// Memorix Server Configuration\n// ============================================================\n\nexport interface MemorixConfig {\n dataDir: string;\n projectId: string;\n projectName: string;\n enableEmbeddings: boolean;\n enableRulesSync: boolean;\n watchRuleFiles: boolean;\n}\n\nexport const DEFAULT_CONFIG: Partial<MemorixConfig> = {\n enableEmbeddings: false,\n enableRulesSync: false,\n watchRuleFiles: false,\n};\n\n// ============================================================\n// Workspace Sync — Cross-Agent workspace migration\n// ============================================================\n\n/** Supported agent targets for workspace sync */\nexport type AgentTarget =\n | 'windsurf'\n | 'cursor'\n | 'claude-code'\n | 'codex'\n | 'copilot'\n | 'antigravity'\n | 'gemini-cli'\n | 'openclaw'\n | 'hermes'\n | 'omp'\n | 'kiro'\n | 'opencode'\n | 'trae';\n\n/** A unified MCP server entry across all agent config formats */\nexport interface MCPServerEntry {\n name: string;\n /** Command for stdio transport */\n command: string;\n /** Args for stdio transport */\n args: string[];\n /** Environment variables */\n env?: Record<string, string> | null;\n /** URL for HTTP/SSE transport (Codex uses `url`, Windsurf uses `serverUrl`) */\n url?: string;\n /** HTTP headers (Windsurf uses `headers` for HTTP transport) */\n headers?: Record<string, string>;\n /** Whether this server is disabled */\n disabled?: boolean;\n /** Claude Code: force small core tool sets to load before the first prompt */\n alwaysLoad?: boolean;\n}\n\n/** Unified workflow entry */\nexport interface WorkflowEntry {\n name: string;\n description: string;\n content: string;\n source: AgentTarget;\n filePath: string;\n}\n\n/** A skill folder discovered from an agent's skills directory */\nexport interface SkillEntry {\n name: string;\n description: string;\n sourcePath: string;\n sourceAgent: AgentTarget;\n}\n\n/** Conflict when two agents have a skill with the same folder name */\nexport interface SkillConflict {\n name: string;\n kept: SkillEntry;\n skipped: SkillEntry;\n}\n\n/** Result of a workspace sync operation */\nexport interface WorkspaceSyncResult {\n mcpServers: {\n scanned: MCPServerEntry[];\n generated: { filePath: string; content: string }[];\n };\n workflows: {\n scanned: WorkflowEntry[];\n generated: { filePath: string; content: string }[];\n };\n rules: {\n scanned: number;\n generated: number;\n };\n skills: {\n scanned: SkillEntry[];\n conflicts: SkillConflict[];\n copied: string[];\n skipped: string[];\n };\n}\n\n// ============================================================\n// Mini-Skills — Promoted memories that never decay\n// ============================================================\n\n/** A mini-skill promoted from one or more observations */\nexport interface MiniSkill {\n id: number;\n /** Observation IDs this mini-skill was derived from (live refs, best-effort) */\n sourceObservationIds: number[];\n /** Entity the source observations belong to */\n sourceEntity: string;\n /** Short title for the skill */\n title: string;\n /** What the agent should do (imperative instruction) */\n instruction: string;\n /** When this skill should be applied (scenario description) */\n trigger: string;\n /** Key facts extracted from source observations */\n facts: string[];\n /** Project this skill belongs to */\n projectId: string;\n /** ISO timestamp */\n createdAt: string;\n /** How many times this skill was injected in session_start */\n usedCount: number;\n /** Classification tags */\n tags: string[];\n /** Frozen source observation content at promote time (JSON, immutable provenance proof) */\n sourceSnapshot?: string;\n /** ISO timestamp of last modification (Phase 3a: set once at creation) */\n updatedAt?: string;\n}\n\n// ============================================================\n// Source Snapshot — immutable provenance proof for promoted knowledge\n// ============================================================\n\n/** A single observation entry within a source snapshot */\nexport interface SnapshotObservation {\n id: number;\n title: string;\n type: string;\n narrative: string;\n facts: string[];\n entityName: string;\n projectId: string;\n createdAt: string;\n /** Frozen source detail for provenance (explicit / hook / git-ingest) */\n sourceDetail?: string;\n}\n\n/** Frozen source content captured at promote time */\nexport interface SourceSnapshot {\n observations: SnapshotObservation[];\n promotedAt: string;\n}\n\n// ============================================================\n// Knowledge Layer — Phase 3a retrieval classification\n// ============================================================\n\n/** Classification of knowledge for layer-aware ranking */\nexport type KnowledgeLayer = 'project-truth' | 'promoted' | 'evidence';\n\n/** Document type discriminator for Orama index */\nexport type DocumentType = 'observation' | 'mini-skill';\n\n// ============================================================\n// Typed Memory Reference — Phase 3a reference protocol\n// ============================================================\n\n/** A typed reference to a memory object (observation or mini-skill) */\nexport interface MemoryRef {\n kind: 'obs' | 'skill';\n id: number;\n projectId?: string;\n}\n\n/** MCP config format adapter interface */\nexport interface MCPConfigAdapter {\n readonly source: AgentTarget;\n /** Parse MCP server entries from a config file */\n parse(content: string): MCPServerEntry[];\n /** Generate config file content from MCP server entries */\n generate(servers: MCPServerEntry[]): string;\n /** Get the default config file path for this agent */\n getConfigPath(projectRoot?: string): string;\n}\n"],"mappings":";AAsEO,IAAM,oBAAqD;AAAA,EAChE,mBAAmB;AAAA,EACnB,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,aAAa;AAAA,EACb,SAAS;AACX;AA0OO,IAAM,qBAA+C;AAAA,EAC1D,gBAAgB,CAAC,gBAAgB,UAAU,OAAO,aAAa,SAAS;AAAA,EACxE,OAAO,CAAC,UAAU,OAAO,SAAS,cAAc,SAAS,kBAAkB;AAAA,EAC3E,YAAY,CAAC,YAAY,aAAa,UAAU,UAAU;AAAA,EAC1D,UAAU,CAAC,UAAU,SAAS,OAAO,eAAe,YAAY;AAAA,EAChE,aAAa,CAAC,aAAa,YAAY,WAAW,QAAQ;AAAA,EAC1D,WAAW,CAAC,WAAW,cAAc,YAAY,eAAe;AAClE;AAoJO,IAAM,iBAAyC;AAAA,EACpD,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,gBAAgB;AAClB;","names":[]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# 1.2.7 Context Continuity
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Host agents own their own `/compact` implementation. Memorix does not replace
|
|
6
|
+
the host compactor, rewrite its prompt, or pretend that every hook exposes a
|
|
7
|
+
summary. Its job is narrower: preserve a small, source-aware continuity record
|
|
8
|
+
so one compacted session, a new window, or another configured agent can resume
|
|
9
|
+
without replaying a transcript.
|
|
10
|
+
|
|
11
|
+
## Data Boundary
|
|
12
|
+
|
|
13
|
+
Compact checkpoints live in `compaction_checkpoints` in the local SQLite data
|
|
14
|
+
store. They are not Observations, claims, Knowledge Workspace pages, or
|
|
15
|
+
transcript archives.
|
|
16
|
+
|
|
17
|
+
- A `pre` marker says the host is about to compact.
|
|
18
|
+
- A `complete` checkpoint records either a genuine `native-summary` or an
|
|
19
|
+
honest `lifecycle` completion with no summary.
|
|
20
|
+
- Repeated hook delivery is idempotent. A second real compact in the same
|
|
21
|
+
session creates a new checkpoint when the host provides a fresh preflight
|
|
22
|
+
marker or native compaction event ID.
|
|
23
|
+
- Checkpoints are never automatically promoted into durable memory.
|
|
24
|
+
|
|
25
|
+
## Host Capability
|
|
26
|
+
|
|
27
|
+
| Host path | Evidence Memorix stores | Automatic delivery |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| Pi / Oh-my-Pi package extension | Native compaction entry fields when exposed by the host, including summary and token metadata | Explicit continuation Workset or `memorix checkpoint context` |
|
|
30
|
+
| Codex plugin hooks | `PreCompact` marker plus `SessionStart` compact lifecycle completion | One bounded `SessionStart.additionalContext` delivery |
|
|
31
|
+
| Claude Code hooks | `PreCompact` marker plus compact `SessionStart` lifecycle completion | One bounded next `UserPromptSubmit.additionalContext` delivery |
|
|
32
|
+
| Other hook integrations | Only the fields their official event surface actually provides | Explicit CLI/MCP inspection unless that host has a documented context injection point |
|
|
33
|
+
|
|
34
|
+
`manual`, `auto`, and native summary fields are retained only when the host
|
|
35
|
+
payload reports them. Unknown remains `unknown`.
|
|
36
|
+
|
|
37
|
+
## Agent Experience
|
|
38
|
+
|
|
39
|
+
For normal work, nothing new needs to be typed. The native compact path uses a
|
|
40
|
+
single bounded recovery packet when the host supports an official injection
|
|
41
|
+
channel. It contains current task wording, the host/source label, and at most a
|
|
42
|
+
small checkpoint excerpt. It never contains a full conversation transcript.
|
|
43
|
+
|
|
44
|
+
For Claude Code, a handoff or continuation prompt also receives one short
|
|
45
|
+
`UserPromptSubmit` routing hint to call `memorix_project_context` before broad
|
|
46
|
+
file or Git exploration. The hint is not a memory dump, and unrelated feature
|
|
47
|
+
or documentation prompts remain quiet.
|
|
48
|
+
|
|
49
|
+
For an explicit cross-agent handoff or a CLI-only agent:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
memorix resume "continue the authentication regression"
|
|
53
|
+
memorix checkpoint list
|
|
54
|
+
memorix checkpoint context --task "continue the authentication regression"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`memorix resume` can add one recent checkpoint to its normal continuation
|
|
58
|
+
Workset. The item is labelled as historical host lifecycle evidence and current
|
|
59
|
+
code remains authoritative. A checkpoint older than 24 hours is not
|
|
60
|
+
automatically added; it remains inspectable through the CLI.
|
|
61
|
+
|
|
62
|
+
## MCP Surface
|
|
63
|
+
|
|
64
|
+
The normal MCP profiles remain unchanged. The advanced action tool
|
|
65
|
+
`memorix_compaction_checkpoint` is available only with `--mode full` or
|
|
66
|
+
`MEMORIX_MODE=full` and supports `list`, `show`, `context`, and `archive`.
|
|
67
|
+
This keeps ordinary agent tool schemas small while preserving a complete
|
|
68
|
+
inspection path for debugging and handoff work.
|
package/docs/API_REFERENCE.md
CHANGED
|
@@ -98,6 +98,8 @@ memorix context
|
|
|
98
98
|
memorix context --task "continue auth bug"
|
|
99
99
|
memorix context "continue auth bug"
|
|
100
100
|
memorix resume "continue auth bug"
|
|
101
|
+
memorix checkpoint list
|
|
102
|
+
memorix checkpoint context --task "continue auth bug"
|
|
101
103
|
memorix context --task "prepare 1.1.7 release"
|
|
102
104
|
memorix explain
|
|
103
105
|
memorix codegraph context-pack --task "continue auth bug"
|
|
@@ -109,11 +111,11 @@ MCP:
|
|
|
109
111
|
- `memorix_codegraph_status` returns provider/index counts for the current project.
|
|
110
112
|
- `memorix_context_pack` builds a task-specific packet with reliable current memories, lower-trust unbound memories, current code facts, freshness warnings, suggested reads, and suggested verification.
|
|
111
113
|
|
|
112
|
-
`memorix context` defaults to `--refresh auto`, so first use can seed Code State without a separate manual `memorix codegraph refresh`. Its brief puts live package/changelog/Git facts before memory hints and flags old `progress.txt` / dev-log notes as historical when they predate the latest changelog, so agents should treat current facts as the source of truth when files disagree. Task lenses keep the packet shaped to the work: bugfix briefs prefer failing tests and repros, release briefs prefer metadata/changelog/package checks, and onboarding briefs prefer docs and entry points while hiding unrelated suspect details. Continuation delivery is separate from the task lens: continuation language in `memorix_project_context` enables a bounded prior-work projection, and `memorix resume "..."` makes that choice explicit. It includes only the latest useful session summary
|
|
114
|
+
`memorix context` defaults to `--refresh auto`, so first use can seed Code State without a separate manual `memorix codegraph refresh`. Its brief puts live package/changelog/Git facts before memory hints and flags old `progress.txt` / dev-log notes as historical when they predate the latest changelog, so agents should treat current facts as the source of truth when files disagree. Task lenses keep the packet shaped to the work: bugfix briefs prefer failing tests and repros, release briefs prefer metadata/changelog/package checks, and onboarding briefs prefer docs and entry points while hiding unrelated suspect details. Continuation delivery is separate from the task lens: continuation language in `memorix_project_context` enables a bounded prior-work projection, and `memorix resume "..."` makes that choice explicit. It includes only the latest useful session summary, up to three readable durable memories, and at most one recent source-labelled compact checkpoint. Checkpoints are host lifecycle evidence, not durable memory or transcript backups; ordinary new tasks do not receive historical-session context. A completed MCP brief is the default retrieval boundary: search, detail, or Context Pack should expand it only for a named missing fact or an explicit request for deeper history. Use `--refresh never` for read-only inspection and `--refresh always` when you want to force a fresh scan.
|
|
113
115
|
|
|
114
116
|
Project-specific generated, vendored, or cache paths can be excluded from Code State with `[codegraph].exclude_patterns` in `memorix.toml` or `~/.memorix/config.toml` (`codegraph.excludePatterns` in legacy YAML). User patterns extend the built-in excludes and are applied to indexing, Project Context suggested reads, and Context Pack suggested reads.
|
|
115
117
|
|
|
116
|
-
SessionStart hooks keep the default minimal hint lightweight. When memory behavior is configured with `sessionInject=full`, Codex receives the compact Memory Autopilot brief at session start instead of only listing recent text memories. Claude Code
|
|
118
|
+
SessionStart hooks keep the default minimal hint lightweight. When memory behavior is configured with `sessionInject=full`, Codex receives the compact Memory Autopilot brief at session start instead of only listing recent text memories. After a native compact, Codex receives one bounded checkpoint through its official `SessionStart` compact context channel. Claude Code receives one bounded checkpoint through the next official `UserPromptSubmit` context channel, then delivery stops. Pi and Oh-my-Pi retain the native summary fields their extension API exposes; hosts that do not expose a summary remain labelled as lifecycle-only. Set `memory.inject = "silent"` to disable automatic hook delivery.
|
|
117
119
|
|
|
118
120
|
The intended loop for agents is: get the project brief when it helps, inspect the suggested current files, use stale or unbound memory only as a lead, store durable outcomes after the work changes the project, and resolve obsolete memories.
|
|
119
121
|
|
|
@@ -138,6 +140,8 @@ memorix knowledge workflow preview --id <workflow-id> --agent codex
|
|
|
138
140
|
|
|
139
141
|
The advanced MCP action tool is `memorix_knowledge`. It is registered only in the `team` and `full` tool profiles so normal agents keep the compact micro/lite tool surface. Its actions are `workspace_init`, `status`, `claim_list`, `claim_review`, `compile`, `lint`, `proposal_apply`, `workflow_import`, `workflow_list`, `workflow_select`, `workflow_preview`, `workflow_apply`, and `workflow_run`. Explicit agent observations become `needs-review` claim candidates: check their source evidence, then use `claim_review` with a reason to approve or reject them. Only approved claims can be compiled into publishable Knowledge Workspace pages. Ordinary coding work should stay on `memorix_project_context`.
|
|
140
142
|
|
|
143
|
+
`memorix_compaction_checkpoint` is a separate advanced MCP action tool registered only in the `full` profile. Its `list`, `show`, `context`, and `archive` actions match `memorix checkpoint` for explicit continuity inspection. Normal agents should not call it during ordinary work; automatic recovery and `memorix_project_context` already handle the bounded path.
|
|
144
|
+
|
|
141
145
|
### Cross-Agent Handoff Receipt
|
|
142
146
|
|
|
143
147
|
`memorix receipt` creates a privacy-safe diagnostic artifact for cross-agent memory handoff debugging.
|
|
@@ -316,3 +316,26 @@
|
|
|
316
316
|
`memcode` version parity, all seven versioned plugin manifests, both Context
|
|
317
317
|
CLI forms, and a real stdio MCP handshake: 43 tools were discoverable and
|
|
318
318
|
`memorix_project_context` returned an Autopilot Brief.
|
|
319
|
+
|
|
320
|
+
## 1.2.7 Native Context Continuity
|
|
321
|
+
- Added a project-scoped SQLite checkpoint store that separates host-native
|
|
322
|
+
compaction evidence from Observations, claims, Knowledge Workspace pages,
|
|
323
|
+
and transcript storage. It captures preflight markers, native summaries
|
|
324
|
+
where the host exposes them, lifecycle-only completion where it does not,
|
|
325
|
+
idempotent retry handling, one-time delivery state, and archival.
|
|
326
|
+
- Pi and Oh-my-Pi extensions now pass through their real `compactionEntry`
|
|
327
|
+
fields. Codex and Claude Code use their documented compact lifecycle paths
|
|
328
|
+
without fabricating a host summary or changing the host compactor.
|
|
329
|
+
- Codex consumes one bounded checkpoint at compact `SessionStart`; Claude Code
|
|
330
|
+
consumes one on the next official `UserPromptSubmit` delivery point. Explicit
|
|
331
|
+
CLI/MCP continuation can carry at most one recent source-labelled checkpoint
|
|
332
|
+
across configured agents, while ordinary new tasks remain free of it.
|
|
333
|
+
- Added `memorix checkpoint list|show|context|archive` and the full-profile
|
|
334
|
+
`memorix_compaction_checkpoint` MCP action. The default MCP profile remains
|
|
335
|
+
unchanged to protect agent context budgets.
|
|
336
|
+
- Final verification passed: focused compaction, hook, Workset, CLI, and MCP
|
|
337
|
+
tests; the full root test suite; TypeScript check; production build; npm
|
|
338
|
+
package dry-run; an isolated installed-artifact Codex/CLI/MCP smoke; and an
|
|
339
|
+
isolated Claude Code handoff/continuation smoke. `npm publish --dry-run
|
|
340
|
+
--ignore-scripts` accepted the public 1.2.7 tarball; the full prepublish
|
|
341
|
+
build/test path is covered by the root release gates above.
|
|
@@ -68,7 +68,8 @@ memorix hook <normalized_event> [--agent <agent_name>]
|
|
|
68
68
|
| `post_edit` | 分析变更 → 记录 what-changed |
|
|
69
69
|
| `post_command` | 分析命令结果 → 记录 problem-solution (如有错误) |
|
|
70
70
|
| `post_tool` | 分析 MCP 工具调用 → 记录相关操作 |
|
|
71
|
-
| `pre_compact` |
|
|
71
|
+
| `pre_compact` | 记录压缩前检查点;不把宿主未提供的内容伪造成摘要 |
|
|
72
|
+
| `post_compact` | 完成检查点;仅在宿主真实提供原生摘要时保存该摘要 |
|
|
72
73
|
| `session_end` | 总结本次会话 → 记录决策和发现 |
|
|
73
74
|
| `user_prompt` | 模式检测 → 判断是否需要注入记忆 |
|
|
74
75
|
|
package/package.json
CHANGED
|
@@ -38,6 +38,20 @@ function latestAssistantText(messages) {
|
|
|
38
38
|
return '';
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
function compactionEntryPayload(entry) {
|
|
42
|
+
if (!entry || typeof entry !== 'object') return undefined;
|
|
43
|
+
const payload = {
|
|
44
|
+
id: typeof entry.id === 'string' ? entry.id : undefined,
|
|
45
|
+
summary: typeof entry.summary === 'string' ? entry.summary : undefined,
|
|
46
|
+
tokensBefore: typeof entry.tokensBefore === 'number' ? entry.tokensBefore : undefined,
|
|
47
|
+
firstKeptEntryId: typeof entry.firstKeptEntryId === 'string' ? entry.firstKeptEntryId : undefined,
|
|
48
|
+
};
|
|
49
|
+
if (entry.details && typeof entry.details === 'object') {
|
|
50
|
+
payload.details = entry.details;
|
|
51
|
+
}
|
|
52
|
+
return payload;
|
|
53
|
+
}
|
|
54
|
+
|
|
41
55
|
function runMemorix(args, input) {
|
|
42
56
|
const command = process.platform === 'win32' ? 'memorix.cmd' : 'memorix';
|
|
43
57
|
const result = spawnSync(command, args, {
|
|
@@ -147,6 +161,7 @@ export default function memorixOmpExtension(pi) {
|
|
|
147
161
|
runHook({
|
|
148
162
|
hook_event_name: 'omp.session_before_compact',
|
|
149
163
|
cwd: ctx.cwd,
|
|
164
|
+
compaction_reason: 'unknown',
|
|
150
165
|
});
|
|
151
166
|
});
|
|
152
167
|
|
|
@@ -154,6 +169,8 @@ export default function memorixOmpExtension(pi) {
|
|
|
154
169
|
runHook({
|
|
155
170
|
hook_event_name: 'omp.session_compact',
|
|
156
171
|
cwd: ctx.cwd,
|
|
172
|
+
compaction_entry: compactionEntryPayload(event.compactionEntry),
|
|
173
|
+
from_extension: event.fromExtension === true,
|
|
157
174
|
});
|
|
158
175
|
});
|
|
159
176
|
|
|
@@ -38,6 +38,20 @@ function latestAssistantText(messages) {
|
|
|
38
38
|
return '';
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
function compactionEntryPayload(entry) {
|
|
42
|
+
if (!entry || typeof entry !== 'object') return undefined;
|
|
43
|
+
const payload = {
|
|
44
|
+
id: typeof entry.id === 'string' ? entry.id : undefined,
|
|
45
|
+
summary: typeof entry.summary === 'string' ? entry.summary : undefined,
|
|
46
|
+
tokensBefore: typeof entry.tokensBefore === 'number' ? entry.tokensBefore : undefined,
|
|
47
|
+
firstKeptEntryId: typeof entry.firstKeptEntryId === 'string' ? entry.firstKeptEntryId : undefined,
|
|
48
|
+
};
|
|
49
|
+
if (entry.details && typeof entry.details === 'object') {
|
|
50
|
+
payload.details = entry.details;
|
|
51
|
+
}
|
|
52
|
+
return payload;
|
|
53
|
+
}
|
|
54
|
+
|
|
41
55
|
function runHook(payload) {
|
|
42
56
|
const data = JSON.stringify({
|
|
43
57
|
agent: 'pi',
|
|
@@ -137,6 +151,7 @@ export default function memorixPiExtension(pi) {
|
|
|
137
151
|
runHook({
|
|
138
152
|
hook_event_name: 'pi.session_before_compact',
|
|
139
153
|
cwd: ctx.cwd,
|
|
154
|
+
compaction_reason: 'unknown',
|
|
140
155
|
});
|
|
141
156
|
});
|
|
142
157
|
|
|
@@ -144,6 +159,8 @@ export default function memorixPiExtension(pi) {
|
|
|
144
159
|
runHook({
|
|
145
160
|
hook_event_name: 'pi.session_compact',
|
|
146
161
|
cwd: ctx.cwd,
|
|
162
|
+
compaction_entry: compactionEntryPayload(event.compactionEntry),
|
|
163
|
+
from_extension: event.fromExtension === true,
|
|
147
164
|
});
|
|
148
165
|
});
|
|
149
166
|
|
|
@@ -5,6 +5,7 @@ export const CLI_NATIVE_PARITY: Record<string, string> = Object.freeze({
|
|
|
5
5
|
memorix_graph_context: 'memorix memory graph-context',
|
|
6
6
|
memorix_project_context: 'memorix context|resume',
|
|
7
7
|
memorix_context_pack: 'memorix codegraph context-pack',
|
|
8
|
+
memorix_compaction_checkpoint: 'memorix checkpoint list|show|context|archive',
|
|
8
9
|
memorix_codegraph_status: 'memorix codegraph status',
|
|
9
10
|
memorix_knowledge: 'memorix knowledge init|status|compile|lint|apply|workflow',
|
|
10
11
|
memorix_resolve: 'memorix memory resolve',
|
package/src/cli/command-guide.ts
CHANGED
|
@@ -56,6 +56,16 @@ const GUIDES: Record<string, CliCommandGuide> = {
|
|
|
56
56
|
'memorix codegraph context-pack --task "trace the auth flow" [--limit 20]',
|
|
57
57
|
],
|
|
58
58
|
},
|
|
59
|
+
checkpoint: {
|
|
60
|
+
summary: 'Inspect bounded recovery checkpoints created around host-native context compaction.',
|
|
61
|
+
usage: [
|
|
62
|
+
'memorix checkpoint list [--session <id>] [--agent <name>]',
|
|
63
|
+
'memorix checkpoint show --id <checkpoint-id>',
|
|
64
|
+
'memorix checkpoint context [--id <checkpoint-id>] [--task "continue auth fix"]',
|
|
65
|
+
'memorix checkpoint archive --id <checkpoint-id>',
|
|
66
|
+
],
|
|
67
|
+
notes: ['Checkpoints are host lifecycle evidence, not durable project memory and not transcript backups.'],
|
|
68
|
+
},
|
|
59
69
|
knowledge: {
|
|
60
70
|
summary: 'Manage the reviewed, source-backed Knowledge Workspace and project workflows.',
|
|
61
71
|
usage: [
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { defineCommand } from 'citty';
|
|
2
|
+
import { buildCompactionWorkset } from '../../memory/compaction.js';
|
|
3
|
+
import { CompactionCheckpointStore } from '../../store/compaction-checkpoint-store.js';
|
|
4
|
+
import type { CompactionCheckpoint } from '../../types.js';
|
|
5
|
+
import {
|
|
6
|
+
emitError,
|
|
7
|
+
emitResult,
|
|
8
|
+
getCliProjectContext,
|
|
9
|
+
parsePositiveInt,
|
|
10
|
+
shortId,
|
|
11
|
+
} from './operator-shared.js';
|
|
12
|
+
|
|
13
|
+
async function getCheckpointContext() {
|
|
14
|
+
const context = await getCliProjectContext();
|
|
15
|
+
const { initAliasRegistry, registerAlias } = await import('../../project/aliases.js');
|
|
16
|
+
initAliasRegistry(context.dataDir);
|
|
17
|
+
const canonicalId = await registerAlias(context.project);
|
|
18
|
+
return {
|
|
19
|
+
...context,
|
|
20
|
+
project: { ...context.project, id: canonicalId },
|
|
21
|
+
store: new CompactionCheckpointStore(context.dataDir),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function assertProjectCheckpoint(
|
|
26
|
+
checkpoint: CompactionCheckpoint | undefined,
|
|
27
|
+
projectId: string,
|
|
28
|
+
id: string,
|
|
29
|
+
): CompactionCheckpoint {
|
|
30
|
+
if (!checkpoint || checkpoint.projectId !== projectId) {
|
|
31
|
+
throw new Error(`No compact checkpoint "${id}" exists for this project.`);
|
|
32
|
+
}
|
|
33
|
+
return checkpoint;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function formatCheckpoint(checkpoint: CompactionCheckpoint): string {
|
|
37
|
+
const completion = checkpoint.completedAt ? `, completed ${checkpoint.completedAt}` : '';
|
|
38
|
+
const delivery = checkpoint.deliveredAt ? `, delivered ${checkpoint.deliveryCount}x` : '';
|
|
39
|
+
return [
|
|
40
|
+
`${shortId(checkpoint.id)} ${checkpoint.phase} ${checkpoint.agent} (${checkpoint.captureKind}, ${checkpoint.reason})`,
|
|
41
|
+
` session: ${checkpoint.sessionId}`,
|
|
42
|
+
` source: ${checkpoint.sourceEvent}${completion}${delivery}`,
|
|
43
|
+
` status: ${checkpoint.status}${checkpoint.transcriptAvailable ? ', transcript marker available' : ''}`,
|
|
44
|
+
...(checkpoint.summary ? [` summary: ${checkpoint.summary.replace(/\s+/g, ' ').slice(0, 220)}`] : []),
|
|
45
|
+
].join('\n');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function usage(): void {
|
|
49
|
+
console.log('Memorix Compact Checkpoints');
|
|
50
|
+
console.log('');
|
|
51
|
+
console.log('Usage:');
|
|
52
|
+
console.log(' memorix checkpoint list [--session <id>] [--agent <name>] [--all]');
|
|
53
|
+
console.log(' memorix checkpoint show --id <checkpoint-id>');
|
|
54
|
+
console.log(' memorix checkpoint context [--id <checkpoint-id>] [--task "..."] [--budget 420]');
|
|
55
|
+
console.log(' memorix checkpoint archive --id <checkpoint-id>');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default defineCommand({
|
|
59
|
+
meta: {
|
|
60
|
+
name: 'checkpoint',
|
|
61
|
+
description: 'Inspect and manage native compact continuity checkpoints',
|
|
62
|
+
},
|
|
63
|
+
args: {
|
|
64
|
+
id: { type: 'string', description: 'Checkpoint ID' },
|
|
65
|
+
session: { type: 'string', description: 'Filter by host session ID' },
|
|
66
|
+
agent: { type: 'string', description: 'Filter by host agent name' },
|
|
67
|
+
task: { type: 'string', description: 'Current task for a bounded continuation workset' },
|
|
68
|
+
budget: { type: 'string', description: 'Maximum workset token budget (default: 420)' },
|
|
69
|
+
limit: { type: 'string', description: 'Maximum checkpoints to list (default: 20)' },
|
|
70
|
+
all: { type: 'boolean', description: 'Include archived checkpoints in list output' },
|
|
71
|
+
json: { type: 'boolean', description: 'Emit machine-readable JSON output' },
|
|
72
|
+
},
|
|
73
|
+
run: async ({ args }) => {
|
|
74
|
+
const positional = (args._ as string[]) ?? [];
|
|
75
|
+
const action = (positional[0] ?? 'list').toLowerCase();
|
|
76
|
+
const asJson = Boolean(args.json);
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const { project, store } = await getCheckpointContext();
|
|
80
|
+
const id = (args.id as string | undefined)?.trim();
|
|
81
|
+
|
|
82
|
+
switch (action) {
|
|
83
|
+
case 'list': {
|
|
84
|
+
const checkpoints = store.list({
|
|
85
|
+
projectId: project.id,
|
|
86
|
+
sessionId: (args.session as string | undefined)?.trim() || undefined,
|
|
87
|
+
agent: (args.agent as string | undefined)?.trim() || undefined,
|
|
88
|
+
includeArchived: Boolean(args.all),
|
|
89
|
+
limit: parsePositiveInt(args.limit as string | undefined, 20),
|
|
90
|
+
});
|
|
91
|
+
emitResult(
|
|
92
|
+
{ project, checkpoints },
|
|
93
|
+
checkpoints.length
|
|
94
|
+
? checkpoints.map(formatCheckpoint).join('\n\n')
|
|
95
|
+
: 'No compact checkpoints for this project.',
|
|
96
|
+
asJson,
|
|
97
|
+
);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
case 'show': {
|
|
102
|
+
if (!id) throw new Error('id is required for "memorix checkpoint show".');
|
|
103
|
+
const checkpoint = assertProjectCheckpoint(store.get(id), project.id, id);
|
|
104
|
+
emitResult({ project, checkpoint }, formatCheckpoint(checkpoint), asJson);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
case 'context': {
|
|
109
|
+
const checkpoint = id
|
|
110
|
+
? assertProjectCheckpoint(store.get(id), project.id, id)
|
|
111
|
+
: store.list({
|
|
112
|
+
projectId: project.id,
|
|
113
|
+
sessionId: (args.session as string | undefined)?.trim() || undefined,
|
|
114
|
+
agent: (args.agent as string | undefined)?.trim() || undefined,
|
|
115
|
+
limit: parsePositiveInt(args.limit as string | undefined, 20),
|
|
116
|
+
}).find((entry) => entry.phase === 'complete');
|
|
117
|
+
if (!checkpoint) {
|
|
118
|
+
throw new Error('No completed compact checkpoint is available for this project and filter.');
|
|
119
|
+
}
|
|
120
|
+
const workset = buildCompactionWorkset(checkpoint, {
|
|
121
|
+
task: (args.task as string | undefined)?.trim(),
|
|
122
|
+
maxTokens: parsePositiveInt(args.budget as string | undefined, 420),
|
|
123
|
+
});
|
|
124
|
+
emitResult({ project, checkpoint, workset }, workset.text, asJson);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
case 'archive': {
|
|
129
|
+
if (!id) throw new Error('id is required for "memorix checkpoint archive".');
|
|
130
|
+
assertProjectCheckpoint(store.get(id), project.id, id);
|
|
131
|
+
const checkpoint = store.archive(id);
|
|
132
|
+
if (!checkpoint) throw new Error(`Compact checkpoint "${id}" is already archived.`);
|
|
133
|
+
emitResult({ project, checkpoint }, `Archived compact checkpoint ${shortId(checkpoint.id)}.`, asJson);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
default:
|
|
138
|
+
usage();
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
emitError(error instanceof Error ? error.message : String(error), asJson);
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
});
|