
    #iY5                        d Z ddlmZ ddlZddlZddlmZmZ ddlmZm	Z	 ddl
mZ ddlmZmZ ddlmZ e G d	 d
             Z G d d      Zy)u  
core/evolution/tier1_autonomous_updater.py

Story 8.08: Tier1AutonomousUpdater — Epistemic Self-Updates

Applies epistemic changes (KG entities, Qdrant scars, prompt templates,
and GLOBAL_GENESIS_RULES.md rule additions) without requiring a PR.

Tier 1 = NO code changes. None of the methods here create or modify .py files.
All updates are audit-logged to data/observability/tier1_updates.jsonl.

VERIFICATION_STAMP
Story: 8.08
Verified By: parallel-builder
Verified At: 2026-02-25
Tests: 8/8 (BB1–BB4, WB1–WB4)
Coverage: 100%
    )annotationsN)	dataclassasdict)datetimetimezone)Path)AnyOptional)ArchitectureAnalysisc                  :    e Zd ZU dZded<   ded<   ded<   ded<   y)Tier1Resultz:Summary counts from a single Tier 1 autonomous update run.intkg_entities_addedscars_updatedprompts_updatedrules_updatedN)__name__
__module____qualname____doc____annotations__     @/mnt/e/genesis-system/core/evolution/tier1_autonomous_updater.pyr   r   %   s    Dr   r   c                      e Zd ZdZ	 	 	 	 	 d
	 	 	 	 	 	 	 	 	 	 	 ddZ	 d	 	 	 	 	 ddZ	 	 	 	 	 	 ddZddZddZddZ	dd	Z
y)Tier1AutonomousUpdateru  
    Applies Tier 1 (epistemic) self-updates derived from an ArchitectureAnalysis.

    Tier 1 updates are safe to apply without a PR because they never touch
    Python source files.  The four update categories are:

      1. KG entities  — write new axiom/entity JSONL files under kg_base_path
      2. Qdrant scars — upsert consolidated scar records into genesis_scars
      3. Prompt templates — create/update .md or .txt files in prompts_dir
      4. Rules additions — append new guardrail text to rules_file

    Every successful run writes one audit line to audit_log_path (JSONL).

    Parameters
    ----------
    qdrant_client:
        Any object with an ``upsert(collection_name, points)`` method.
        When None, scar updates are skipped gracefully.
    kg_base_path:
        Root directory for KG entity files.
        Default: "KNOWLEDGE_GRAPH/entities"
    prompts_dir:
        Directory where prompt template files live.
        Default: "config/prompts"
    rules_file:
        Path to GLOBAL_GENESIS_RULES.md (or equivalent).
        Default: ".claude/rules/GLOBAL_GENESIS_RULES.md"
    audit_log_path:
        JSONL file for Tier 1 update audit entries.
        Default: "data/observability/tier1_updates.jsonl"
    Nc                    || _         t        |xs d      | _        t        |xs d      | _        t        |xs d      | _        t        |xs d      | _        y )NzKNOWLEDGE_GRAPH/entitieszconfig/promptsz%.claude/rules/GLOBAL_GENESIS_RULES.mdz&data/observability/tier1_updates.jsonl)qdrantr   kg_baseprompts_dir
rules_file	audit_log)selfqdrant_clientkg_base_pathr    r!   audit_log_paths         r   __init__zTier1AutonomousUpdater.__init__U   sT     $LF,FG ?/?@zT-TUnX0XYr   c                    | j                  ||      }| j                  |      }| j                  |      }| j                  |      }t	        ||||      }| j                  ||       |S )a  
        Apply all Tier 1 updates derived from the given ArchitectureAnalysis.

        Parameters
        ----------
        analysis:
            The result of a MetaArchitect.analyze() call with scope="epistemic".
        epoch_id:
            A string identifier for the current epoch (e.g. "epoch_042").
            Used to name the KG entity file and tag the audit log.

        Returns
        -------
        Tier1Result
            Counts of items updated in each category.
        )r   r   r   r   )_write_kg_entities_update_scars_update_prompts_append_rulesr   _write_audit)r#   analysisepoch_idkg_count
scar_countprompt_count
rule_countresults           r   apply_tier1z"Tier1AutonomousUpdater.apply_tier1g   ss    * **8X>''1
++H5''1
&$($	
 	(F+r   c                   |j                   s|j                  sy| j                  j                  dd       | j                  d| dz  }g }|j                   D ]s  }|j	                  d|t        j                  t        j                        j                         |j                  |j                  |j                  |j                  d       u |j                  D ]  }|j                  j                  d	      r|j	                  d
|t        j                  t        j                        j                         |j                  |j                   |j"                  d        |sy|j%                  dd      5 }|D ])  }|j'                  t)        j*                  |      dz          + 	 ddd       t-        |      S # 1 sw Y   t-        |      S xY w)a  
        Write one JSONL line per bottleneck/fix into
        {kg_base}/epoch_{epoch_id}_learnings.jsonl.

        Creates the directory if it does not exist.
        Returns the number of entities written.

        CRITICAL: Does NOT create or modify any .py files.
        r   Tparentsexist_okepoch_z_learnings.jsonl
bottlenecktz)typer/   	timestampdescription	frequencyaffected_saga_idsscar_idsz.pyfix_proposal)r>   r/   r?   target_filechange_type	rationaleautf-8encoding
N)bottlenecksrecommended_fixesr   mkdirappendr   nowr   utc	isoformatr@   rA   rB   rC   rE   endswithrF   rG   openwritejsondumpslen)	r#   r.   r/   targetentitiesr;   fixfhentitys	            r   r)   z)Tier1AutonomousUpdater._write_kg_entities   s    ##H,F,F4$7&
2B CC! #.. 		JOO$$%\\X\\:DDF)55'11%/%A%A&// 		 -- 	C''.OO&$%\\X\\:DDF"" ]] 		 [[w[/ 	42" 4F+d234	4 8}		4 8}s   7/F::Gc           
        | j                   y|j                  syg }t        |j                        D ]  \  }}d| d|j                  dd j	                  dd       |j                  |j
                  |j                  |j                  dt        j                  t        j                        j                         d	d
gdz  d}|j                  |        	 | j                   j                  d|       t        |      S # t         $ r Y yw xY w)u   
        Upsert consolidated scar records into the ``genesis_scars`` Qdrant
        collection — one point per bottleneck.

        When qdrant_client is None, returns 0 without raising.
        Returns the number of points upserted.
        Nr   t1_scar__    tier1_autonomous_updaterr<   )r@   rA   rB   rC   sourcer?   g           )idpayloadvectorgenesis_scars)collection_namepoints)r   rM   	enumerater@   replacerA   rB   rC   r   rQ   r   rR   rS   rP   upsertrY   	Exception)r#   r.   rl   ir;   points         r   r*   z$Tier1AutonomousUpdater._update_scars   s    ;;##&x';';< 	!MAz !1Z%;%;CR%@%H%Hc%R$ST#-#9#9!+!5!5)3)E)E * 3 38!)!>!H!H!J %!)E MM% !	!$	KK /   v; 		s   'D   	DDc                Z   |j                   sy| j                  j                  dd       d}|j                   D ]V  }t        |j                        }|j
                  j                         }|dvr8| j                  |j                  z  }dt        j                  t        j                        j                          d|j                   d|j                   d	}|j                         r.|j!                  d
d      5 }|j#                  |       ddd       nsd|j$                   dt        j                  t        j                        j'                          d	}	|j!                  dd      5 }|j#                  |	|z          ddd       |dz  }Y |S # 1 sw Y   xY w# 1 sw Y   xY w)u  
        Create or update prompt template files in prompts_dir.

        Only creates .md or .txt files — NEVER .py files.
        One file per recommended fix whose target_file path ends with .md or .txt.

        Returns the number of prompt files created/updated.
        r   Tr7   )z.mdz.txtu   

---
# Tier 1 Update — r<   z
## Rationale
z
## Change type
rL   rH   rI   rJ   Nz# Prompt Template: z7
# Auto-generated by Tier1AutonomousUpdater
# Created: w   )rN   r    rO   r   rE   suffixlowernamer   rQ   r   rR   daterG   rF   existsrU   rV   stemrS   )
r#   r.   countr\   rZ   rv   destcontent_blockr]   headers
             r   r+   z&Tier1AutonomousUpdater._update_prompts   s    ))td;-- !	C#//*F]]((*F _, ##fkk1D''/||x||'D'I'I'K&L M!!$ 0##&??"327  {{}YYsWY5 ,HH]+, ,
 *&++ 7""*,,(,,"?"I"I"K!LBP 
 YYsWY5 5HHVm345 QJEC!	F , ,5 5s   =F.F!F	!F*	c                   |j                   sy|j                  dk7  ryt        j                  t        j
                        j                         }dj                  d |j                   dd D              }d| d	| d
}| j                  j                  j                  dd       | j                  j                  dd      5 }|j                  |       ddd       y# 1 sw Y   yxY w)u^  
        Append a new guardrail rule to rules_file when the analysis identifies
        a missing guardrail (i.e. any bottleneck exists with scope='epistemic').

        Rules are TEXT-ONLY additions — never modifies existing content.
        Returns 1 if a rule was appended, 0 otherwise.

        CRITICAL: Does NOT modify any .py files.
        r   	epistemicr<   z; c              3  4   K   | ]  }|j                     y w)N)r@   ).0bs     r   	<genexpr>z7Tier1AutonomousUpdater._append_rules.<locals>.<genexpr>B  s      Q1 Qs   N   u)   

---

## AUTO-APPENDED RULE (Tier 1 — z3)

> Recurring epistemic bottleneck(s) detected:
> z

**Guardrail**: When the above patterns recur, re-run MetaArchitect analysis and escalate if frequency exceeds 3 within a 7-day window.
Tr7   rH   rI   rJ   ru   )rM   scoper   rQ   r   rR   rS   joinr!   parentrO   rU   rV   )r#   r.   tsdescriptions	rule_textr]   s         r   r,   z$Tier1AutonomousUpdater._append_rules0  s     ##>>[( \\X\\*446yy Q8L8LRa8P QQ113 5 TU 	 	$$TD$A __!!#!8 	 BHHY	  	  s   CC&c                   t        j                  t        j                        j	                         ||j
                  |j                  |j                  |j                  d}| j                  j                  j                  dd       | j                  j                  dd      5 }|j                  t        j                  |      dz          d	d	d	       y	# 1 sw Y   y	xY w)
a1  
        Append one JSON audit line to the audit_log JSONL file.

        Audit entry schema:
            timestamp      ISO-8601 UTC
            epoch_id       string
            kg_entities_added  int
            scars_updated  int
            prompts_updated int
            rules_updated  int
        r<   )r?   r/   r   r   r   r   Tr7   rH   rI   rJ   rL   N)r   rQ   r   rR   rS   r   r   r   r   r"   r   rO   rU   rV   rW   rX   )r#   r/   r4   entryr]   s        r   r-   z#Tier1AutonomousUpdater._write_auditY  s     "6@@B !'!9!9#11%55#11
 	##D4#@^^  w 7 	/2HHTZZ&-.	/ 	/ 	/s   &(CC )NNNNN)r$   r	   r%   Optional[str]r    r   r!   r   r&   r   returnNone)unknown)r.   r   r/   strr   r   )r.   r   r/   r   r   r   )r.   r   r   r   )r/   r   r4   r   r   r   )r   r   r   r   r'   r5   r)   r*   r+   r,   r-   r   r   r   r   r   4   s    D "&*%)$((,ZZ $Z #	Z
 "Z &Z 
Z* "!&! ! 
	!N7&7 7 
	7z'Z2p#R/r   r   )r   
__future__r   rW   osdataclassesr   r   r   r   pathlibr   typingr	   r
   core.evolution.meta_architectr   r   r   r   r   r   <module>r      sI   & #  	 ) '    >   ~/ ~/r   