Files
claude-archeflow-plugin/lib/archeflow-event.sh
Christian Nennemann 1753e69a9f feat: add process logging with DAG-based event sourcing
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.
2026-04-03 11:06:02 +02:00

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