openapi: 3.1.0
info:
  title: Mneme SCMS API
  description: |
    Sparse Contextual Memory SCAFFOLDING (SCMS) API for memory-augmented AI conversations.
    
    IMPORTANT: SCMS = Scaffolding, NOT System. The word "Scaffolding" implies a 
    supportive structure that enables growth and can be extended.
    
    This API allows you to:
    - Store and retrieve memories (preferences, facts, patterns, failures, corrections)
    - Promote memories from L0 (active) to L1 (validated)
    - Log failures and anti-patterns for learning (failures-first principle)
    - Search memories by query or tags
    - Access L2 WHY documentation attached to memories
    
    Key SCMS Principles:
    - Failure documentation is 3-10× more valuable than success documentation
    - Every memory should have L2 WHY documentation
    - Anti-patterns (what NOT to do) are first-class citizens
    
    Authentication: None required (public API)
  version: 1.3.0
  contact:
    name: Mneme
servers:
  - url: https://mneme-ai.netlify.app
    description: Production server

# No authentication required

paths:
  /api/actions/memories:
    get:
      operationId: getMemories
      summary: Get all memories or search by query
      description: Retrieve memories from the user's knowledge base. Use query parameter to search.
      parameters:
        - name: query
          in: query
          description: Search query to find relevant memories
          schema:
            type: string
        - name: layer
          in: query
          description: Filter by memory layer
          schema:
            type: string
            enum: [L0, L1, all]
            default: all
        - name: limit
          in: query
          description: Maximum number of memories to return
          schema:
            type: integer
            default: 10
            maximum: 50
      responses:
        '200':
          description: List of memories
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryListResponse'

    post:
      operationId: createMemory
      x-openai-isConsequential: false
      summary: Store a new memory
      description: |
        Create a new L0 memory in the knowledge base.
        The memory will be subject to decay unless promoted to L1.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateMemoryRequest'
      responses:
        '201':
          description: Memory created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryResponse'
        '400':
          $ref: '#/components/responses/BadRequest'

  /api/actions/memories/{memoryId}:
    get:
      operationId: getMemory
      summary: Get a specific memory
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Memory details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryResponse'
        '404':
          $ref: '#/components/responses/NotFound'

    patch:
      operationId: updateMemory
      x-openai-isConsequential: false
      summary: Update a memory
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateMemoryRequest'
      responses:
        '200':
          description: Memory updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryResponse'
        '404':
          $ref: '#/components/responses/NotFound'

    delete:
      operationId: deleteMemory
      x-openai-isConsequential: false
      summary: Delete a memory
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Memory deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string

  /api/actions/memories/{memoryId}/promote:
    post:
      operationId: promoteMemory
      x-openai-isConsequential: false
      summary: Promote memory to L1
      description: |
        Promote an L0 memory to L1 (validated).
        L1 memories are permanent and do not decay.
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Memory promoted to L1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryResponse'
        '404':
          $ref: '#/components/responses/NotFound'

  /api/actions/memories/{memoryId}/validate:
    post:
      operationId: validateMemory
      x-openai-isConsequential: false
      summary: Validate a memory to boost confidence
      description: Boost memory confidence. 0→low, 1-2→medium, 3+→high (never decays). Use when user confirms accuracy.
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Memory validated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  memory:
                    type: object
                    properties:
                      id:
                        type: string
                      validationCount:
                        type: integer
                      confidence:
                        type: string
                        enum: [low, medium, high]
                      decayMode:
                        type: string
                        enum: [permanent, slow, standard, fast]
                  message:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /api/actions/memories/{memoryId}/l2:
    get:
      operationId: getL2Entry
      summary: Get L2 WHY documentation for a memory
      description: Retrieve the L2 causal documentation (reason, triggerContext, problemSolved, antiPatterns).
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: L2 entry retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  memoryId:
                    type: string
                  hasL2:
                    type: boolean
                  l2Entry:
                    $ref: '#/components/schemas/L2Entry'
        '404':
          $ref: '#/components/responses/NotFound'

    patch:
      operationId: updateL2Entry
      x-openai-isConsequential: false
      summary: Update or create L2 WHY documentation
      description: Add/update causal documentation. Include reason, triggerContext, problemSolved, and antiPatterns.
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                why:
                  type: object
                  properties:
                    reason:
                      type: string
                    triggerContext:
                      type: string
                    problemSolved:
                      type: string
                antiPatterns:
                  type: array
                  items:
                    type: string
                failures:
                  type: array
                  items:
                    type: string
      responses:
        '200':
          description: L2 entry updated or created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  action:
                    type: string
                    enum: [created, updated]
                  l2Entry:
                    $ref: '#/components/schemas/L2Entry'
                  message:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /api/actions/memories/{memoryId}/crossref:
    get:
      operationId: getCrossRefs
      summary: Get cross-references for a memory
      description: Retrieve all memories linked to this memory via cross-references.
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Cross-references retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  memoryId:
                    type: string
                  crossRefCount:
                    type: integer
                  crossRefs:
                    type: array
                    items:
                      $ref: '#/components/schemas/CrossReference'

    post:
      operationId: addCrossRef
      x-openai-isConsequential: false
      summary: Add a cross-reference between memories
      description: Link two related memories. Use bidirectional=true to create reverse link too.
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - targetMemoryId
                - relationshipType
                - description
              properties:
                targetMemoryId:
                  type: string
                  format: uuid
                relationshipType:
                  type: string
                  enum: [supports, contradicts, extends, prerequisite, related]
                description:
                  type: string
                bidirectional:
                  type: boolean
                  description: If true, also creates reverse reference
      responses:
        '200':
          description: Cross-reference added
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  crossRef:
                    $ref: '#/components/schemas/CrossReference'
                  bidirectional:
                    type: boolean
                  message:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /api/actions/memories/{memoryId}/fivewhys:
    get:
      operationId: getFiveWhys
      summary: Get Five-Whys analysis for a memory
      description: Retrieve the causal chain analysis (why1 through why5 plus rootCause).
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Five-Whys retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  memoryId:
                    type: string
                  hasFiveWhys:
                    type: boolean
                  fiveWhys:
                    $ref: '#/components/schemas/FiveWhys'
                  depth:
                    type: integer
                    description: How many why levels are filled (0-5)

    post:
      operationId: addFiveWhys
      x-openai-isConsequential: false
      summary: Add Five-Whys causal analysis
      description: Document root cause analysis. Start with why1, add deeper levels as needed. Essential for failures.
      parameters:
        - name: memoryId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FiveWhys'
      responses:
        '200':
          description: Five-Whys added
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  fiveWhys:
                    $ref: '#/components/schemas/FiveWhys'
                  depth:
                    type: integer
                  rootCause:
                    type: string
                  message:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /api/actions/failures:
    get:
      operationId: getFailures
      summary: Get failure documentation
      description: Retrieve L2 failure documentation and anti-patterns to learn from past mistakes.
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: List of failure entries
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FailureListResponse'

    post:
      operationId: logFailure
      x-openai-isConsequential: false
      summary: Log a failure or anti-pattern
      description: Document a failure for a memory. Critical for learning what NOT to do.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LogFailureRequest'
      responses:
        '201':
          description: Failure logged
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string

  /api/actions/stats:
    get:
      operationId: getStats
      summary: Get memory statistics
      description: Get statistics about the user's memory system.
      responses:
        '200':
          description: Memory statistics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StatsResponse'

  /api/actions/calibrate:
    get:
      operationId: calibrateFrequency
      summary: Frequency calibration for session start
      description: |
        Resonance Transfer Protocol calibration ritual.
        Retrieves L1 persona-core memories and returns alignment context.
        Call this at the start of each session to load identity framework.
      responses:
        '200':
          description: Calibration context with persona-core memories
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CalibrationResponse'

components:
  schemas:
    Memory:
      type: object
      properties:
        id:
          type: string
          format: uuid
        content:
          type: string
          description: The memory content
        type:
          type: string
          enum: [preference, fact, pattern, failure, correction, knowledge]
          description: "Memory type. Priority: failure > correction > knowledge > pattern > preference > fact"
        tags:
          type: array
          items:
            type: string
        importance:
          type: integer
          minimum: 1
          maximum: 5
        strength:
          type: number
          minimum: 0
          maximum: 1
          description: Memory strength (decays over time for L0)
        layer:
          type: string
          enum: [L0, L1]
        retrievalCount:
          type: integer
        createdAt:
          type: string
          format: date-time
        # Titans/MIRAS fields (Google Research Dec 2024)
        surpriseScore:
          type: integer
          minimum: 1
          maximum: 5
          description: |
            Novelty score based on Titans research:
            1=Routine, 2=Expected, 3=Unexpected, 4=Novel, 5=Paradigm-shifting
        confidence:
          type: string
          enum: [low, medium, high]
          description: |
            Validation confidence level:
            🔴 low = never retrieved/validated
            🟡 medium = retrieved 1-2 times
            🟢 high = retrieved 3+ times or validated
        decayMode:
          type: string
          enum: [permanent, slow, standard, fast]
          description: |
            Decay rate based on MIRAS research:
            permanent = never decays (L1, critical failures)
            slow = ~70 day half-life (validated preferences)
            standard = ~14 day half-life (default)
            fast = ~7 day half-life (low-value context)
        validationCount:
          type: integer
          description: Number of times memory has been validated
        # Persona Isolation fields (v4.2)
        isPersonaCore:
          type: boolean
          description: |
            Marks memory as core identity (voice, tone, constraints).
            Persona-core memories ALWAYS load first, regardless of query.
        loadPriority:
          type: integer
          minimum: 0
          maximum: 100
          description: |
            Priority for retrieval ordering (0-100):
            - 100 = persona-core (always loads first)
            - 50 = L1 validated
            - 0 = standard L0

    CreateMemoryRequest:
      type: object
      required:
        - content
        - type
        - tags
      properties:
        content:
          type: string
          description: The memory content - should be concise and universally applicable
        type:
          type: string
          enum: [preference, fact, pattern, failure, correction, knowledge]
          description: |
            Memory type (priority order):
            - failure: Something that didn't work (HIGH VALUE)
            - correction: A misunderstanding fixed (HIGH VALUE)
            - knowledge: Concepts/frameworks being learned
            - pattern: Recurring behavior that works
            - preference: User preference
            - fact: Static user context
        tags:
          type: array
          items:
            type: string
          description: Tags for retrieval (2-4 keywords recommended)
        importance:
          type: integer
          minimum: 1
          maximum: 5
          default: 3
          description: Importance score (5 = critical)
        isPersonaCore:
          type: boolean
          default: false
          description: |
            Set true for core identity memories (voice, tone, constraints).
            Persona-core memories ALWAYS load first regardless of query.
            Recommended: 5-7 persona-core memories maximum.
        loadPriority:
          type: integer
          minimum: 0
          maximum: 100
          default: 0
          description: |
            Priority for retrieval (0-100). Use 100 for persona-core.

    UpdateMemoryRequest:
      type: object
      properties:
        content:
          type: string
        tags:
          type: array
          items:
            type: string
        importance:
          type: integer
          minimum: 1
          maximum: 5

    MemoryResponse:
      type: object
      properties:
        success:
          type: boolean
        memory:
          $ref: '#/components/schemas/Memory'

    MemoryListResponse:
      type: object
      properties:
        count:
          type: integer
        memories:
          type: array
          items:
            $ref: '#/components/schemas/Memory'

    FailureEntry:
      type: object
      properties:
        memoryId:
          type: string
          format: uuid
        why:
          type: object
          properties:
            reason:
              type: string
            triggerContext:
              type: string
            problemSolved:
              type: string
        antiPatterns:
          type: array
          items:
            type: string
        failures:
          type: array
          items:
            type: string
        createdAt:
          type: string
          format: date-time
          description: When this failure was first documented
        updatedAt:
          type: string
          format: date-time
          description: When this failure was last updated

    FailureListResponse:
      type: object
      properties:
        count:
          type: integer
        entries:
          type: array
          items:
            $ref: '#/components/schemas/FailureEntry'

    L2Entry:
      type: object
      properties:
        id:
          type: string
          format: uuid
        memoryId:
          type: string
          format: uuid
        why:
          type: object
          properties:
            reason:
              type: string
              description: Why this memory was created
            triggerContext:
              type: string
              description: What triggered the memory creation
            problemSolved:
              type: string
              description: What problem this memory solves
        fiveWhys:
          $ref: '#/components/schemas/FiveWhys'
        antiPatterns:
          type: array
          items:
            type: string
        failures:
          type: array
          items:
            type: string
        crossRefs:
          type: array
          items:
            $ref: '#/components/schemas/CrossReference'
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        refinementCount:
          type: integer

    CrossReference:
      type: object
      properties:
        targetMemoryId:
          type: string
          format: uuid
        targetConversationId:
          type: string
        relationshipType:
          type: string
          enum: [supports, contradicts, extends, prerequisite, related]
          description: |
            How the memories relate:
            - supports: Evidence/reasoning for the target
            - contradicts: Conflicts with target (important for corrections)
            - extends: Builds upon the target
            - prerequisite: Target is required to understand this
            - related: General association
        description:
          type: string
        createdAt:
          type: string
          format: date-time

    FiveWhys:
      type: object
      required:
        - why1
      properties:
        why1:
          type: string
          description: Surface level - what happened
        why2:
          type: string
          description: One layer deeper - why did that happen
        why3:
          type: string
          description: Pattern emerges
        why4:
          type: string
          description: Root cause area
        why5:
          type: string
          description: Core principle
        rootCause:
          type: string
          description: Summary of the fundamental root cause

    LogFailureRequest:
      type: object
      required:
        - memoryId
        - failure
      properties:
        memoryId:
          type: string
          format: uuid
          description: ID of the related memory
        failure:
          type: string
          description: Description of what failed or should be avoided
        antiPatterns:
          type: array
          items:
            type: string
          description: List of anti-patterns (things NOT to do)

    StatsResponse:
      type: object
      properties:
        totalMemories:
          type: integer
        l0Count:
          type: integer
        l1Count:
          type: integer
        atRiskCount:
          type: integer
          description: Memories with strength below 30%
        byType:
          type: object
          additionalProperties:
            type: integer
          description: Count of memories by type
        memoryIdsByType:
          type: object
          description: Memory IDs grouped by type for quick navigation
          additionalProperties:
            type: array
            items:
              type: object
              properties:
                id:
                  type: string
                content:
                  type: string
                  description: First 40 chars of memory content
                promotedToL1:
                  type: boolean
        l2Health:
          type: object
          description: |
            L2 WHY Documentation Health.
            CRITICAL: L2 is documentation ATTACHED to memories, NOT a separate count.
            Always report as coverage (X/Y), NEVER as "L2 entries: X".
          properties:
            coverage:
              type: string
              description: "Format: X/Y (e.g., '2/17') - number with L2 docs / total memories"
            coveragePercent:
              type: integer
              description: Coverage as percentage (0-100)
            withAntiPatterns:
              type: integer
              description: Memories with anti-pattern documentation
            withCrossRefs:
              type: integer
              description: Memories with cross-references
            withFiveWhys:
              type: integer
              description: Memories with 5-Whys root cause analysis
            note:
              type: string
              description: "Always says: L2 = WHY documentation. Report as coverage, NOT as a count."
        activity:
          type: object
          description: Memory usage patterns - shows which memories are actively being retrieved
          properties:
            recentlyRetrieved:
              type: integer
              description: Count of memories retrieved in last 7 days
            recentlyRetrievedNote:
              type: string
            mostRetrieved:
              type: array
              description: Top 3 most-used memories
              items:
                type: object
                properties:
                  id:
                    type: string
                  content:
                    type: string
                    description: First 50 chars of memory content
                  retrievalCount:
                    type: integer

    CalibrationResponse:
      type: object
      properties:
        scmsPrinciples:
          type: object
          description: SCMS core principles as enforcement reminders
          properties:
            terminology:
              type: string
              description: "SCMS = Sparse Contextual Memory SCAFFOLDING (NOT 'System')"
            failuresFirst:
              type: string
              description: Failure documentation is MORE valuable than success (3-10×)
            l2Requirement:
              type: string
              description: Every memory MUST have L2 WHY documentation
            antiPatternPriority:
              type: string
              description: Anti-patterns (what NOT to do) are first-class citizens
        identity:
          type: object
          properties:
            personaCoreCount:
              type: integer
            patternCount:
              type: integer
            factCount:
              type: integer
            failureCount:
              type: integer
              description: Number of failure-type memories
            correctionCount:
              type: integer
              description: Number of correction-type memories
            preferenceCount:
              type: integer
            totalL1:
              type: integer
            totalMemories:
              type: integer
        l2Health:
          type: object
          description: L2 WHY Documentation Health - L2 is documentation ATTACHED to memories
          properties:
            totalL2Entries:
              type: integer
            coverage:
              type: string
              description: "Format: X/Y (e.g., '5/17 memories have L2 docs')"
            coveragePercent:
              type: integer
              description: L2 coverage as percentage (0-100)
            withAntiPatterns:
              type: integer
            withCrossRefs:
              type: integer
            withFiveWhys:
              type: integer
            note:
              type: string
        systemMetrics:
          type: object
          description: |
            REAL calculated system metrics. These are computed from actual data.
            DO NOT fabricate or estimate different values - use these exact numbers.
            ALWAYS show the component breakdown (e.g., "L2: 42%, Anti-patterns: 100%, L1: 63%") 
            to explain WHY the score is what it is. Transparency builds trust.
          properties:
            integrityClusterCoherence:
              type: object
              description: How well-documented is the memory system (0-100)
              properties:
                score:
                  type: integer
                  description: Overall coherence score (0-100)
                formula:
                  type: string
                  description: "(L2 coverage × 0.4) + (anti-pattern rate × 0.3) + (L1 ratio × 0.3)"
                components:
                  type: object
                  properties:
                    l2CoveragePercent:
                      type: integer
                    antiPatternRate:
                      type: integer
                    l1Ratio:
                      type: integer
                interpretation:
                  type: string
                  description: "Strong (>=70), Moderate (>=40), or Needs improvement (<40)"
            selfHealingResponsiveness:
              type: object
              description: How well does the system learn from failures (0-100)
              properties:
                score:
                  type: integer
                  description: Overall responsiveness score (0-100)
                formula:
                  type: string
                  description: "(failure ratio × 0.4) + (failure L2 rate × 0.3) + (anti-pattern density × 0.3)"
                components:
                  type: object
                  properties:
                    failureCorrectionRatio:
                      type: integer
                    failureL2Rate:
                      type: integer
                    antiPatternDensity:
                      type: integer
                interpretation:
                  type: string
                  description: "Highly responsive (>=70), Moderately responsive (>=40), or Needs more failure documentation (<40)"
            resonanceStability:
              type: object
              description: Overall system health and drift resistance (0-100)
              properties:
                score:
                  type: integer
                  description: Overall stability score (0-100)
                formula:
                  type: string
                  description: "(L1 ratio × 0.4) + (type diversity × 0.3) + (decay safety × 0.3)"
                components:
                  type: object
                  properties:
                    l1Ratio:
                      type: integer
                    typeDiversity:
                      type: integer
                    decayRiskScore:
                      type: integer
                    atRiskCount:
                      type: integer
                interpretation:
                  type: string
                  description: "Stable (>=70), Moderately stable (>=40), or At risk of drift (<40)"
            note:
              type: string
              description: "Reminder: These metrics are calculated from actual data. Do NOT fabricate values."
        antiPatterns:
          type: object
          description: All anti-patterns for context injection (failures-first principle)
          properties:
            count:
              type: integer
            items:
              type: array
              items:
                type: string
              description: Top anti-patterns (what NOT to do)
            purpose:
              type: string
        personaCore:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              content:
                type: string
              type:
                type: string
              tags:
                type: array
                items:
                  type: string
              harmonicTags:
                type: array
                items:
                  type: string
        patterns:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              content:
                type: string
              tags:
                type: array
                items:
                  type: string
        facts:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              content:
                type: string
              tags:
                type: array
                items:
                  type: string
        failures:
          type: array
          description: Failure-type memories (high-value learning)
          items:
            type: object
            properties:
              id:
                type: string
              content:
                type: string
              tags:
                type: array
                items:
                  type: string
        corrections:
          type: array
          description: Correction-type memories (mistakes fixed)
          items:
            type: object
            properties:
              id:
                type: string
              content:
                type: string
              tags:
                type: array
                items:
                  type: string
        message:
          type: string
          description: Calibration status message
        calibratedAt:
          type: string
          format: date-time
        sessionId:
          type: string
          description: Unique session identifier

  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: "Memory not found"
