session

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package session bridges INTERACTIVE crush sessions into the same close-out pipeline pool agents get. Pool work is reviewed and reported on because the journal sees its completions; interactive sessions leave no task trail, so their commits could silently skip the second opinion. The bridge closes that gap: `tq session begin` records the session's opening in the journal, and `tq session close` attributes the session's commits (a `Crush-Session: <id>` git footer written by the committer), then directly enqueues ONE review task over the attributed commit range and ONE done-prompt status task. Both ride the ordinary pool: they are ordinary "review"/"status" tasks, drained by whichever agent-capable pool shares the database, dedup-keyed so re-closing a session never duplicates work.

Close is deliberately enqueue-only (the crush SessionEnd hook budget is ~2s): git attribution scan, two idempotent enqueues, one journal fact. The pool does everything else.

Loop safety is structural: session facts carry the synthetic "session:<id>" task identity, which no task row ever uses, so sweepers and workers cannot mistake session lifecycle for task state; the minted review is type "review" and the status task type "status", both exempt from re-review by the sweeper's agent-only rule.

Index

Constants

View Source
const Trailer = "Crush-Session"

Trailer is the git-footer key that attributes a commit to an interactive session: committers end their commit message with `Crush-Session: <id>` (same convention as the Task-Queue-ID footer pool agents write). Close attributes exactly the commits whose trailer value equals the session id.

Variables

This section is empty.

Functions

func Begin

func Begin(ctx context.Context, s Store, id, repo, project string) error

Begin records the session's opening as a session.opened fact. Refusing a double begin keeps one open epoch per id: begin, work, close — re-running begin for an already-open session is a mistake, not idempotent noise.

func SyntheticTaskID

func SyntheticTaskID(id string) task.ID

SyntheticTaskID returns the session's task-ID-shaped lineage key: the TaskID on session facts and the ReviewedTask / Completed.TaskID lineage in the minted review and status payloads. It is namespaced so it can never collide with a real task ID ("session:" is not a hex ULID prefix).

Types

type CloseDetail

type CloseDetail struct {
	SessionID  string   `json:"session_id"`
	Repo       string   `json:"repo"`
	Project    string   `json:"project,omitempty"`
	Summary    string   `json:"summary,omitempty"`
	Commits    []Commit `json:"commits"`
	ReviewTask string   `json:"review_task,omitempty"`
	StatusTask string   `json:"status_task,omitempty"`
}

CloseDetail is the session.closed fact's detail: what the session committed (as far as attribution can see) and what close minted.

type CloseInput

type CloseInput struct {
	// ID is the interactive session's id (CRUSH_SESSION_ID). Required.
	ID string
	// Repo is the absolute repository path the session worked in. Required.
	Repo string
	// Project is the queue project the minted tasks belong to (convention:
	// the repo directory's base name).
	Project string
	// Summary is the operator's one-paragraph account of what the session
	// did; it becomes the review's bar and the status entry's item. Empty
	// falls back to a default text.
	Summary string
	// AllowDirty mirrors the pool's --allow-dirty stance into the minted
	// payloads' RequireClean: a multi-agent repo is effectively always
	// dirty, and a clean-tree-required task there requeues forever.
	AllowDirty bool
}

CloseInput carries one Close invocation's parameters.

type CloseResult

type CloseResult struct {
	// Commits are the session-attributed commits, oldest first.
	Commits []Commit
	// ReviewTask / StatusTask are the minted tasks; zero TaskIDs when no
	// commits were attributed (nothing minted).
	ReviewTask task.Task
	StatusTask task.Task
	// ReviewFresh / StatusFresh are false when the enqueue hit the dedup
	// key (the task already existed from an earlier close of this session).
	ReviewFresh bool
	StatusFresh bool
}

CloseResult reports what Close recorded and minted.

func Close

func Close(ctx context.Context, s Store, scanner GitScanner, in CloseInput) (CloseResult, error)

Close attributes the session's commits, records the session.closed fact, and directly enqueues the close-out: ONE review over the attributed range and ONE status report, both idempotent by dedup key. A session with no attributed commits records only the fact — there is nothing to review and nothing to report.

type Commit

type Commit struct {
	SHA     string `json:"sha"`
	Subject string `json:"subject"`
}

Commit is one session-attributed commit.

type GitLogScanner

type GitLogScanner struct {
	// Bin is the git binary; empty means "git" from PATH.
	Bin string
}

GitLogScanner attributes commits by scanning `git log` for the footer trailer. Commits come back oldest first. Requires git >= 2.15 (%(trailers) format); every supported environment clears that floor by years.

func (GitLogScanner) CommitsByTrailer

func (s GitLogScanner) CommitsByTrailer(ctx context.Context, repo, key, value string) ([]Commit, error)

CommitsByTrailer implements GitScanner. A repository without any commit yet (unborn HEAD) attributes nothing — that is an empty session, not an error.

type GitScanner

type GitScanner interface {
	CommitsByTrailer(ctx context.Context, repo, key, value string) ([]Commit, error)
}

GitScanner attributes commits: which commits in repo carry the git footer `key: value`. The interface keeps Close hermetic to test; GitLogScanner is the real implementation.

type GitScannerFunc

type GitScannerFunc func(ctx context.Context, repo, key, value string) ([]Commit, error)

GitScannerFunc adapts a function to GitScanner.

func (GitScannerFunc) CommitsByTrailer

func (f GitScannerFunc) CommitsByTrailer(ctx context.Context, repo, key, value string) ([]Commit, error)

CommitsByTrailer implements GitScanner.

type OpenDetail

type OpenDetail struct {
	SessionID string `json:"session_id"`
	Repo      string `json:"repo"`
	Project   string `json:"project,omitempty"`
}

OpenDetail is the session.opened fact's detail.

type Store

type Store interface {
	Enqueue(ctx context.Context, n task.New) (task.Task, error)
	AppendFact(ctx context.Context, f journal.Fact) error
	FactsForTask(ctx context.Context, id string, limit int) ([]journal.Fact, error)
}

Store is the bridge's view of the queue core: mint tasks, append the session's lifecycle facts, and read one identity's facts (the double-begin guard).

Jump to

Keyboard shortcuts

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