Event-sourced orchestration logging: JSONL events with parent relationships form a DAG for causal reconstruction of agent flows. Includes bash event emitter (jq-based) and markdown report generator.
73 lines
2.2 KiB
Bash
Executable File
73 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# archeflow-event.sh — Append a structured event to an ArcheFlow run's JSONL log.
|
|
#
|
|
# Usage: ./lib/archeflow-event.sh <run_id> <type> <phase> <agent> '<json_data>' [parent_seqs]
|
|
#
|
|
# Examples:
|
|
# ./lib/archeflow-event.sh 2026-04-03-der-huster run.start plan "" '{"task":"Write Der Huster"}'
|
|
# ./lib/archeflow-event.sh 2026-04-03-der-huster agent.complete plan creator '{"duration_ms":167522}' 2
|
|
# ./lib/archeflow-event.sh 2026-04-03-der-huster phase.transition do "" '{"from":"plan","to":"do"}' 3,4
|
|
# ./lib/archeflow-event.sh 2026-04-03-der-huster fix.applied act "" '{"source":"guardian"}' 8
|
|
#
|
|
# Parent seqs: comma-separated seq numbers of causal parent events (DAG).
|
|
# "2" → single parent [2]
|
|
# "3,4" → multiple parents [3,4] (fan-in)
|
|
# "" → root event []
|
|
#
|
|
# Events are appended to .archeflow/events/<run_id>.jsonl
|
|
# If the events directory doesn't exist, it is created automatically.
|
|
|
|
set -euo pipefail
|
|
|
|
if [[ $# -lt 4 ]]; then
|
|
echo "Usage: $0 <run_id> <type> <phase> <agent> [json_data] [parent_seqs]" >&2
|
|
exit 1
|
|
fi
|
|
|
|
RUN_ID="$1"
|
|
TYPE="$2"
|
|
PHASE="$3"
|
|
AGENT="$4"
|
|
DATA="${5:-"{}"}"
|
|
PARENT_RAW="${6:-}"
|
|
|
|
EVENTS_DIR=".archeflow/events"
|
|
EVENT_FILE="${EVENTS_DIR}/${RUN_ID}.jsonl"
|
|
|
|
mkdir -p "$EVENTS_DIR"
|
|
|
|
# Determine sequence number (count existing lines + 1)
|
|
if [[ -f "$EVENT_FILE" ]]; then
|
|
SEQ=$(( $(wc -l < "$EVENT_FILE") + 1 ))
|
|
else
|
|
SEQ=1
|
|
fi
|
|
|
|
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
|
|
# Build parent array from comma-separated seq numbers
|
|
if [[ -z "$PARENT_RAW" ]]; then
|
|
PARENT_JSON="[]"
|
|
else
|
|
PARENT_JSON="[${PARENT_RAW}]"
|
|
fi
|
|
|
|
# Construct the event using jq for reliable JSON assembly
|
|
# Agent is passed as --arg (string), then converted to null if empty via jq expression
|
|
EVENT=$(jq -cn \
|
|
--arg ts "$TS" \
|
|
--arg run_id "$RUN_ID" \
|
|
--argjson seq "$SEQ" \
|
|
--argjson parent "$PARENT_JSON" \
|
|
--arg type "$TYPE" \
|
|
--arg phase "$PHASE" \
|
|
--arg agent_raw "$AGENT" \
|
|
--argjson data "$DATA" \
|
|
'{ts:$ts, run_id:$run_id, seq:$seq, parent:$parent, type:$type, phase:$phase, agent:(if $agent_raw == "" then null else $agent_raw end), data:$data}'
|
|
)
|
|
|
|
echo "$EVENT" >> "$EVENT_FILE"
|
|
|
|
# Print confirmation to stderr (non-intrusive)
|
|
echo "[archeflow-event] #${SEQ} ${TYPE} (${PHASE}/${AGENT:-_})" >&2
|