completion

package
v0.3.21 Latest Latest
Warning

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

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package completion holds the one authoritative implementation of "this task is finished".

Completing a task is not a status write — it is a decision tree with real consequences: an evidence gate that can REJECT the completion, a human-gate step that must park for review instead of advancing the workflow DAG, and a PR-bearing task that must wait for a human merge rather than being buried in Done. That logic used to live inside the taskyou_complete MCP handler, which made the MCP transport the only way to finish a task correctly — when it was unavailable, agents reached for `ty close`, which is a plain status write and silently skips every one of those rules.

Both the MCP tool and the `ty complete` CLI now call Complete, so the two cannot drift and neither can bypass a gate.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LookupPR

func LookupPR(database *db.DB, task *db.Task) (int, string)

LookupPR returns the PR number and URL for a task's branch, or (0, "").

It prefers a live `gh` lookup — an agent typically opens the PR moments before completing, so the DB copy is stale — and persists a fresh result so the board and the daemon reconciler both see it. Falls back to stored PR info.

Types

type Kind

type Kind string

Kind is what completion actually did — the caller renders its own wording, but the decision itself is made here, once.

const (
	// KindVerifyFailed means the step's `verify:` command exited non-zero, so the
	// completion was REJECTED and the task deliberately left running.
	KindVerifyFailed Kind = "verify_failed"
	// KindGateParked means a human-review gate finished and parked in 'blocked'
	// awaiting approval, holding its dependents.
	KindGateParked Kind = "gate_parked"
	// KindPRReview means the task produced a PR and parked in 'blocked' awaiting a
	// human merge (the daemon promotes it to 'done' once the PR closes).
	KindPRReview Kind = "pr_review"
	// KindDone means the task is genuinely finished and moved to 'done'.
	KindDone Kind = "done"
)

type Options

type Options struct {
	// AsyncSummary runs activity-summary generation in a background goroutine.
	// The long-lived MCP server wants this (it must not block the agent); a
	// short-lived CLI process must NOT, because the process exits and kills the
	// goroutine before it can store anything.
	AsyncSummary bool
}

Options tunes side effects that differ between callers.

type Outcome

type Outcome struct {
	Kind          Kind
	VerifyCommand string // set when Kind == KindVerifyFailed
	VerifyOutput  string // tail of the failing command's output
	PRNumber      int    // set when Kind == KindPRReview
	PRURL         string
}

Outcome describes what Complete did, with the details a caller needs to explain it.

func Complete

func Complete(database *db.DB, taskID int64, summary string, opts Options) (*Outcome, error)

Complete runs the full completion decision for a task and applies its effects.

The order matters and is load-bearing:

  1. Evidence gate — a configured `verify:` command runs FIRST. Non-zero exit rejects the completion and leaves the task running so the agent can fix it. This is the backstop against completion-by-assertion; nothing below runs.
  2. A non-terminal human gate parks 'blocked' (its dependents stay held).
  3. A terminal task with a PR parks 'blocked' for the human merge.
  4. Otherwise the task is done.

Jump to

Keyboard shortcuts

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