
    4i                        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 ddl	m
Z
mZ  eh d      ZdZd	Z G d
 d      Zy)u  SwarmSagaWriter — Saga Lifecycle Recorder for the Genesis Cold Ledger.

Manages the full lifecycle of multi-agent swarm executions:
  1. open_saga()             — create a RUNNING saga record
  2. record_proposed_delta() — append one agent's delta (SQL-level JSONB append)
  3. close_saga()            — finalise with resolved_state and terminal status
  4. get_saga()              — delegate to ColdLedger.get_saga()

Design decisions:
  - record_proposed_delta uses a single UPDATE … SET proposed_deltas = proposed_deltas || ?
    so concurrent appends from multiple agents are safe without a read-modify-write race.
  - SwarmSaga is created via ColdLedger.write_saga() so the pool/commit/release
    pattern is centralised in one place.
  - All status validation happens here, not in the ledger — writer owns the lifecycle contract.

Rules enforced (Genesis hardwired):
  - NO SQLite
  - All SQL uses parameterised %s placeholders — never f-strings
  - Connection pool getconn/putconn in try/finally (no leaks) — delegated to ledger
    )annotationsN)datetimetimezone)Optional)
ColdLedger	SwarmSaga>   FAILED	COMPLETEDPARTIAL_FAILz^UPDATE swarm_sagas SET proposed_deltas = proposed_deltas || %s::jsonb WHERE saga_id = %s::uuidzTUPDATE swarm_sagas SET resolved_state = %s,     status = %s WHERE saga_id = %s::uuidc                  X    e Zd ZdZddZd	dZ	 	 	 	 	 	 	 	 d
dZ	 	 	 	 	 	 	 	 ddZddZy)SwarmSagaWriterzLifecycle manager for swarm sagas stored in the Genesis Cold Ledger.

    Args:
        cold_ledger: A fully initialised :class:`ColdLedger` instance.
    c                    || _         y )N)ledger)selfcold_ledgers     1/mnt/e/genesis-system/core/storage/saga_writer.py__init__zSwarmSagaWriter.__init__:   s	    !    c           	         t        t        j                               }t        j                  t
        j                        }t        |||g dd|      }| j                  j                  |       |S )a)  Create a new saga record with status RUNNING and empty proposed_deltas.

        Args:
            session_id:       UUID string of the owning session.
            orchestrator_dag: DAG descriptor produced by the orchestrator.

        Returns:
            The new saga_id (UUID4 string).
        tzNRUNNING)saga_id
session_idorchestrator_dagproposed_deltasresolved_statestatus
created_at)
struuiduuid4r   nowr   utcr   r   
write_saga)r   r   r   r   r#   sagas         r   	open_sagazSwarmSagaWriter.open_sagaA   s^     djjl#llhll+!-
 	t$r   c                   t        j                  t        j                        j	                         }t        j                  |||dg      }| j                  j                         }	 |j                         5 }|j                  t        ||f       ddd       |j                          | j                  j                  |       y# 1 sw Y   5xY w# | j                  j                  |       w xY w)aD  Append one agent's proposed delta to the saga's proposed_deltas JSONB array.

        Uses a single SQL UPDATE with JSONB concatenation (``||``) so concurrent
        calls from multiple agents are safe without a client-side read-modify-write.

        Each stored element is:
        ``{"agent_id": <str>, "delta": <dict>, "submitted_at": <ISO 8601 str>}``

        Args:
            saga_id:  UUID string of the target saga.
            agent_id: Identifier of the submitting agent.
            delta:    Arbitrary JSON-serialisable dict describing the proposed change.
        r   )agent_iddeltasubmitted_atN)r   r#   r   r$   	isoformatjsondumpsr   _acquirecursorexecute_APPEND_DELTA_SQLcommit_release)r   r   r)   r*   r+   elementconncurs           r   record_proposed_deltaz%SwarmSagaWriter.record_proposed_deltaZ   s       ||x||4>>@**"ULQR
 {{##%	' C#-/ABCKKMKK  &	C C KK  &s$   (C 8CC C
C C.c                   |t         vrt        d|dt        t                      t        j                  |      }| j
                  j                         }	 |j                         5 }|j                  t        |||f       ddd       |j                          | j
                  j                  |       y# 1 sw Y   5xY w# | j
                  j                  |       w xY w)a  Finalise a saga with its resolved state and terminal status.

        Args:
            saga_id:        UUID string of the saga to close.
            resolved_state: Final merged state dict (JSON-serialisable).
            status:         One of ``"COMPLETED"``, ``"PARTIAL_FAIL"``, ``"FAILED"``.

        Raises:
            ValueError: If *status* is not one of the three valid values.
        zInvalid saga status z. Must be one of: N)_VALID_CLOSE_STATUSES
ValueErrorsortedr-   r.   r   r/   r0   r1   _CLOSE_SAGA_SQLr3   r4   )r   r   r   r   resolved_jsonr6   r7   s          r   
close_sagazSwarmSagaWriter.close_sagaw   s     ..&vj 1##)*?#@"AC 
 

>2{{##%	' O#OmVW-MNOKKMKK  &	O O KK  &s$   C 'B5C 5B>:C Cc                8    | j                   j                  |      S )zRetrieve a saga by ID. Delegates to ColdLedger.get_saga().

        Args:
            saga_id: UUID string of the saga to retrieve.

        Returns:
            A :class:`SwarmSaga` instance, or ``None`` if not found.
        )r   get_saga)r   r   s     r   rA   zSwarmSagaWriter.get_saga   s     {{##G,,r   N)r   r   returnNone)r   r    r   dictrB   r    )r   r    r)   r    r*   rD   rB   rC   )r   r    r   rD   r   r    rB   rC   )r   r    rB   zOptional[SwarmSaga])	__name__
__module____qualname____doc__r   r'   r8   r?   rA    r   r   r   r   3   s`    "2''&)'26'	':'',0':='	':	-r   r   )rH   
__future__r   r-   r!   r   r   typingr   core.storage.cold_ledgerr   r   	frozensetr:   r2   r=   r   rI   r   r   <module>rN      sL   * #   '  : ""IJ 
    j- j-r   