export type TrackerBackendName = 'local' | 'markdown'; export type { RawTrackerConfig, TrackerConfig, TrackerSourceConfig } from './configSchema.js'; export interface TrackerCommandResult { stdout: string; stderr: string; } export interface TrackerBackend { readonly name: TrackerBackendName; command(args: string[], inputText?: string): Promise; } export interface TrackerIssueInput { title: string; body?: string; state?: string; assignee?: string; parent?: string; project?: string; labels?: string[]; } export interface TrackerIssueUpdate { title?: string; body?: string; state?: string; assignee?: string; addLabels?: string[]; removeLabels?: string[]; project?: string; removeProject?: boolean; parent?: string; removeParent?: boolean; /** Optimistic-concurrency precondition (ztrack#20): the sha256 hex of the issue body this * update was computed FROM. The backend re-reads the issue at the moment of the write and * refuses (precondition-failed, nothing written) if the current body's sha256 differs — so a * read-modify-write caller (`ac patch`, `fmt --write`) can never clobber a concurrent edit * with a wholesale body replacement computed from a stale snapshot. */ expectedBodySha?: string; /** ztrack#28: run the WHOLE edit path — every gate that can refuse the real write (not-found, * --state vocabulary, the expectedBodySha precondition, readonly-source, a document source's * structural/delta/staleness/integrity guards) — but stop short of the final filesystem * mutation. A dry run resolving without error is an honest prediction that the real write * would be accepted. */ dryRun?: boolean; } export interface TrackerClient { command(args: string[], inputText?: string): Promise; graphql(query: string, variables?: Record): Promise<{ data?: T; errors?: Array<{ message: string; }>; }>; issue: { list(options?: { state?: string; label?: string | string[]; search?: string; parent?: string; limit?: number; json?: string; jq?: string; /** ZTB-33: scope the read to the named declared source(s) (`--source`). A single selector or * a list; each matches a source by its `name` or its path basename. */ source?: string | string[]; }): Promise; view(identifier: string, options?: { comments?: boolean; json?: string; jq?: string; }): Promise>; create(input: TrackerIssueInput): Promise>; edit(identifier: string, input: TrackerIssueUpdate): Promise | null>; comment(identifier: string, body: string): Promise; close(identifier: string, options?: { reason?: 'completed' | 'canceled'; comment?: string; }): Promise; }; project: { list(options?: { status?: string; json?: string; jq?: string; }): Promise; view(identifier: string, options?: { json?: string; jq?: string; }): Promise>; }; snapshot(name?: string, options?: { format?: 'json' | 'text'; }): Promise; }