runlog

package
v0.0.40 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 5, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package runlog writes the four PLAN-5 / C6 streams that surround the pipeline manifest:

hook-events.jsonl    one JSON per ape-notify forward
bridge-calls.jsonl   one JSON per MCP tool call seen by the bridge
checkpoints.jsonl    ape stage events + skill reply() calls
transcripts/         symlinks into ~/.claude/projects/<hash>/<sid>.jsonl

Pipeline runs use the existing PLAN-3 layout (<project>/_output/pipelines/<name>/<run_id>/) — runlog does not move the directory, it adds files alongside manifest.yaml.

`ape chat` writes to a separate convention (<project>/_output/ape/chats/<chat-id>/) with session.yaml in place of the PLAN-3 manifest.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ChatDir

func ChatDir(projectRoot, chatID string) string

ChatDir returns <project>/_output/ape/chats/<chat-id>/. PLAN-5 / C6.

func CopyFileAtomic added in v0.0.32

func CopyFileAtomic(dst, src string) error

CopyFileAtomic copies src to dst via a tmp file + rename. Replaces a pre-existing symlink at dst with a real file. Exported so `ape notify` can perform the hook-side transcript capture with the same primitive the run-dir snapshots use.

func EnsureGitignore

func EnsureGitignore(projectRoot string, askPrompt func(question string) bool, warnTo io.Writer) (bool, error)

EnsureGitignore looks for `_output/` in <projectRoot>/.gitignore. If absent and stdin is a TTY (askPrompt provided), it asks the user; otherwise it warns to stderr but does not modify the file. PLAN-5 / C6 — first-run policy.

Returns true if the line was appended (or already present), false if the user declined or non-TTY warn path was taken.

func EnsureNoCollision

func EnsureNoCollision(dir string) error

EnsureNoCollision returns an error if dir already exists. PLAN-5 / C6: "fail loud" — no auto-disambiguate, no overwrite.

func NewChatID

func NewChatID(now time.Time, cwd string, pid int) string

NewChatID generates a chat-id of the shape YYYYMMDD-HHMMSS-<7-char hash>. Hash mixes timestamp + cwd + pid for cross-process uniqueness. PLAN-5 / C6.

func PipelineRunDir

func PipelineRunDir(projectRoot, pipelineName, runID string) string

PipelineRunDir returns <project>/_output/pipelines/<name>/<run_id>/. PLAN-3's path, extended in place by PLAN-5.

func WriteSessionYAML

func WriteSessionYAML(dir string, m SessionMeta) error

WriteSessionYAML emits session.yaml at <dir>/session.yaml. Hand-rolled because the file is tiny and the rest of ape doesn't pull a YAML encoder for trivial structs.

Types

type CallEntry

type CallEntry struct {
	Timestamp time.Time
	Method    string // "tools/call", "tools/list", "ping", "initialize"
	Tool      string
	Params    json.RawMessage
	Result    json.RawMessage
	SessionID string
	ID        string
}

CallEntry mirrors an MCP tool call.

type CheckpointEntry

type CheckpointEntry struct {
	Timestamp time.Time
	Kind      string // stage-start, stage-end, commit-made, pipeline-end, reply, stopped, chat-start, chat-end
	Step      string
	Payload   any
}

CheckpointEntry is the typed input to Writer.Checkpoint.

type HookEntry

type HookEntry struct {
	Timestamp time.Time
	Event     string
	Step      string // empty → "step":null on the wire
	SessionID string
	AgentID   string
	Payload   json.RawMessage
}

HookEntry is the typed input to Writer.Hook. The on-wire shape is stable but assembled by hookOnWire to keep nil pointers from producing `null` for fields PLAN-5 specifies as empty strings.

type SessionMeta

type SessionMeta struct {
	ChatID    string
	StartedAt time.Time
	EndedAt   time.Time
	Model     string
	CostUSD   float64
	TokensIn  int64
	TokensOut int64
}

SessionMeta is the minimal chat-session record written to session.yaml when an `ape chat` run ends. PLAN-5 / C6 — chats are not pipelines, so no PLAN-3 manifest equivalent.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer is one open run-dir. Methods are safe for concurrent use.

func New

func New(dir string) (*Writer, error)

New opens (or creates) the four streams under dir. Fails loud if the dir already exists and contains a non-empty manifest — that is the PLAN-5 / C6 run-id collision contract.

func (*Writer) Call

func (w *Writer) Call(entry CallEntry) error

Call writes one bridge-calls.jsonl entry. Captures every MCP tool call seen at the bridge stdio layer (including tools/list, ping, initialize, and await_message's deferred-entry + flush pair).

func (*Writer) Checkpoint

func (w *Writer) Checkpoint(entry CheckpointEntry) error

Checkpoint writes one checkpoints.jsonl entry. Kinds: stage-start, stage-end, commit-made, pipeline-end, reply, stopped. PLAN-5 / C6.

func (*Writer) CheckpointKindStep

func (w *Writer) CheckpointKindStep(kind, step string, payload any, at time.Time)

CheckpointKindStep is the pipeline.RunLogger adapter shape: (kind, step, payload, at) → CheckpointEntry. Defined here so the runlog package owns its own wire shape; pipeline calls this via its narrow RunLogger interface to avoid a runlog import.

func (*Writer) Close

func (w *Writer) Close() error

Close flushes and closes every stream. Safe to call multiple times.

func (*Writer) Dir

func (w *Writer) Dir() string

Dir returns the run-dir path.

func (*Writer) Hook

func (w *Writer) Hook(entry HookEntry) error

Hook writes one hook-events.jsonl entry. ts defaults to time.Now().UTC() if zero.

Schema (PLAN-5 / C6): {"ts","event","step","session_id","agent_id","payload"}. `step` is null for events whose session_id is not yet bound.

func (*Writer) LinkTranscript

func (w *Writer) LinkTranscript(name, target string) error

LinkTranscript creates the symlink <dir>/transcripts/<name> → target. Best-effort: returns nil if the link already exists at the same target, errors otherwise so the caller can decide. PLAN-5 / C6 — symlinks (not copies) keep the canonical ~/.claude/projects/ path authoritative.

func (*Writer) SnapshotTranscript added in v0.0.28

func (w *Writer) SnapshotTranscript(name, src string) (string, error)

SnapshotTranscript copies src's bytes to <dir>/transcripts/<name> and returns the destination path. Unlike LinkTranscript, the result survives the source session file being rotated or removed — claude session .jsonl files under ~/.claude/projects/ have been observed gone by post-Stop scan time, which zeroed interactive telemetry. Idempotent: repeat calls refresh the copy (the session file is append-only, so a later copy strictly supersedes an earlier one). Replaces a pre-existing symlink of the same name.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL