- Core: Replaced 10-stage pipeline system with flat status model (backlog, ready, open, done, closed)
- Core: Simplified ticket types to epic, feature, bug (removed task, chore)
- Core: Removed pipeline, gates, workflow, risk levels, and formal review system
- Core: Central store is now the only storage mode (removed local .tickets/ support)
- CLI: Removed commands: advance, skip, revert, pipeline, migrate, workflow, review
- CLI:
tk servealways uses MultiStore (removed --central flag) - CLI:
tk initalways uses central store (removed --store flag) - CLI: Filter flag
--stagereplaced with--status - CLI: Default ticket type changed from task to feature
- MCP: Removed tools: ticket_advance, ticket_skip, ticket_revert, ticket_migrate, ticket_pipelines, ticket_review, ticket_workflow
- MCP: JSON output uses
statusfield instead ofstage; removedreview,risk,skippedfields - TUI: Simplified tabs to Inbox, Backlog, Epics, Done, All (removed Triage tab)
- TUI: Removed review overlay
- Journal: Auto-close uses direct status update instead of pipeline Skip()
- CLI:
tk initnow handles first-run setup (folded in from removedtk setup)
- CLI commands: backlog, ready, blocked, done, log, inbox, next, stats, timeline, setup, review, dep cycle
pkg/ticket/pipeline.go,pipelines.json,gates.go,config.go,workflow.go,migrate.go- Ticket fields: Stage, Review, Risk, Skipped, Reviews, Assignee, Conversations
- ReviewState, RiskLevel, ReviewRecord types
- Stage type and all stage constants
- Create/edit flags:
--design,--acceptance,--assignee
- TUI: Search/filter mode no longer triggers global shortcuts (quit, create, open) on overlapping key presses
- TUI: Epics tab hides done epics and sorts by stage (pipeline order); header count excludes done
- TUI: Two-tab layout (Epics / Tickets) replacing old dashboard/pipeline views
- TUI: Header with project name and ticket count stats
- TUI: Command bar (Ctrl+K) with search and /command stub
- TUI: Overlay infrastructure for detail, form, and review views
- TUI: Epics tab placeholder with progress bars
tk init --store centralwrote project directories to central store root instead oftickets/subdirectory
- TUI: Detail, form, and review views now open as overlays instead of full view switches
- TUI: Pipeline view removed (replaced by Epics tab)
- Journal:
pkg/journalpackage for commit-to-ticket linking via JSONL append-only journal - CLI:
tk watch start|stop|status|logs— background daemon that polls git log and links commits to tickets via[ticket-id]bracket refs - CLI:
tk recompute [--project=NAME]— rebuild commit journal from full git history - Journal: Auto-close tickets when commits contain
Closes: [id]orFixes: [id] - Journal: Diff stats tracking (lines added/removed, files changed) per commit
- Journal: Work duration estimation for live commits
- Journal: Watch cycle runs automatically inside
tk servealongside sync
- TUI: Form cursor highlights character at position instead of inserting block that displaced text
- TUI: Picker selection uses background highlight instead of brackets
- MCP:
ticket_store_infotool returns central store root and per-project ticket directory paths
- MCP:
NewServeracceptscentralRootparameter for store info tool
- Core: Move
PropagateStageintoAdvance()— epics now auto-close via MCP when all children reach done - CLI/MCP:
--repoflag and MCPrepoparameter now resolve central store projects instead of only looking for.tickets/directories
- Core:
AdvanceResultincludesPropagated []StageChangefor parent stage changes
- Core:
Storeinterface extracted fromFileStore— MCP server and all ticket operations now accept the interface - Core:
MultiStorefor multi-project ticket storage with namespaced IDs (project/ticket-id) and cross-project resolution - Core:
ParseNamespacedIDandFormatNamespacedIDutilities for namespaced ticket ID handling - MCP: Optional
projectparameter onticket_create,ticket_list,ticket_ready,ticket_inboxfor multi-project filtering - MCP: Default project scoping in
--centralmode — resolves from CWD when in a repo, all projects when not - CLI:
tk serve --centralflag to serve all projects from the central ticket store via MultiStore - Dev:
.mcp.jsonwithtk-devandtk-dev-centralentries for local MCP testing - Tests:
UpdateSectionround-trip regression tests - Tests:
Serializenotes duplication regression test
- CLI: Removed dead notes body-stripping workaround in
tk edit --note(Parse already handles this)
- MCP:
NewServeraccepts adefaultProjectparameter for CWD-based project scoping
- CLI:
tk setupcommand for first-run configuration — sets central store path, creates ~/.ticket/config.yaml - CLI:
tk statuscommand — system health overview with version, config paths, data repo state, sync status, and per-project ticket counts - Core: Config gate — all commands (except setup/help/version) require valid config with central_root set
- Core: Ticket directories at
<central_root>/tickets/<project>(not directly under central root)
- Core:
CentralStoreRoot()no longer falls back to~/.tickets— requires explicit config viatk setup - Core: Git sync scoped to
tickets/andconfig.yamlonly (won't commit unrelated files in data repo) - Core: Git bootstrap skips
git initwhen central store is inside an existing repo
- Core: Background git sync in
tk serve— automatically stages, commits, and pushes ticket changes every 5s (configurable viasync_interval) - Core: Sync-blocked marker file (
.tk-sync-blocked) persists across restarts when rebase conflicts occur - Core:
git_email,git_name,default_store,sync_intervalconfig fields in~/.ticket/config.yaml - Core: Split config into shared (
<central_root>/config.yaml) and local (~/.ticket/config.yaml) layers for multi-machine support - CLI:
tk synccommand for manual one-shot ticket git sync - CLI:
tk setupcommand for first-run configuration — sets central store path, creates ~/.ticket/config.yaml - Core: Config gate — all commands (except setup/help/version) require valid config with central_root set
- Core: Central store fallback changed from
~/code/forge-data/ticketsto~/.tickets(generic default) - Core:
bootstrapCentralStoreGitreads git identity from config before falling back totk@local
- CLI:
tk initcommand for central store configuration — register projects with--store central|local, auto-detect project names from git remote, bootstrap central store as git repo - Core: Config-based ticket directory resolution via
~/.ticket/config.yaml—TicketsDir()now checks project config betweenTICKETS_DIRenv and walk-up fallback - Core:
central_rootconfig field to override default central store location - Core: Project name sanitization to prevent path traversal
- CLI:
tk show --metadataflag to display only frontmatter fields and description (omits notes, reviews, relationships)
- TUI: Review flow for verify-stage tickets — press
rin dashboard to open full review view with git checkout command, PR URL, and acceptance criteria; approve with optional notes or reject with feedback and stage picker - CLI: Renamed
tk closedtotk doneto match pipeline stage terminology
- Pipeline: default variant now equals normal for all ticket types (adds review stages)
- Pipeline: high/critical-risk bugs get the full feature pipeline (spec, design, design-review, code-review)
- Pipeline: chores now follow feature risk pipelines (were previously flat)
- Pipeline: tasks simplified to backlog → triage → done (research only, no code stages)
- TUI: Dashboard now shows active type filter on a dedicated filter line (matches pipeline view)
- TUI: Dashboard supports pgup/pgdn for page navigation and mouse scroll wheel
- Pipeline: Add
verifystage to bug/low, task/low, and all chore pipeline variants that previously went directly from implement to done - Pipeline: Remove dead
implement>donegate (no pipeline variant uses this transition)
- TUI: Dashboard tabs redesigned from
all|triage|verify|reviewtobacklog|triage|inbox|done|all - TUI: Default tab is now
triage(wasall) - TUI:
alltab shows all active tickets, not just human-actionable ones - TUI: Verify/review keybindings now context-sensitive based on ticket state, not tab
- Pipeline:
backlogstage beforetriagefor all ticket types. Full pipeline: backlog → triage → spec → design → implement → test → verify → done - Pipeline:
backlog>triagegate requiring description, priority, and risk before promotion - CLI:
tk backlogcommand to list tickets in backlog stage - CLI:
tk edit --stageflag to directly set a ticket's stage (bypassing pipeline ordering) - MCP:
ticket_editsupportsstageparameter for direct stage assignment - Gates:
priority_setandrisk_setstructural checks
- Default initial stage for new tickets is now
backlog(wastriage) tk lsexcludes backlog tickets by default (use--stage backlogto see them)ticket_listMCP tool excludes backlog tickets by default (usestage: "backlog"to see them)ticket_readyandticket_inboxexclude backlog tickets- TUI dashboard excludes backlog tickets from inbox view
- Generic extra fields: arbitrary key/value metadata on tickets via
Extra map[string]stringin YAML frontmatter - CLI:
--set key=valueflag oncreateandeditcommands (repeatable, blank value removes field) - CLI:
tk queryJSONL output includesextrafield for custom metadata - MCP:
setparameter onticket_createandticket_editfor extra field CRUD - Extra fields flattened to top level in all JSON output (CLI query, MCP show/list/create/edit) — no
.extra.prefix needed - TUI: Extra fields rendered in detail view after known metadata fields
- Validation: extra field keys allow only
[a-zA-Z0-9_-]; values reject all YAML indicator characters (%,!,&,*,@,`,|,>,',",:,#,[,],{,}) and control characters to prevent YAML parse corruption
- MCP:
ticket_createsupportsrepoparameter for cross-repo ticket creation. Walks up from given path to find.tickets/directory, matching CLI--repoflag behavior. FindTicketsDirexported frompkg/ticketfor shared use by CLI and MCP.- CLI: Dynamic column widths in
ls,ready,blocked,pipeline, andclosedoutput — columns align based on actual data - CLI: Color output for headers (bold), priority (P0=red, P1=yellow), and group headers (bold cyan). Respects
NO_COLORand non-TTY detection. - CLI: Redundant column suppression — STAGE hidden when grouped by stage, TYPE hidden when grouped by type, P hidden when grouped by priority
- CLI: "STATUS" column renamed to "STAGE" in all list output
- MCP:
ticket_listreturns summary fields only (id, title, stage, review, risk, type, priority, assignee, parent, tags, deps, links, created). Body content (description, design, acceptance_criteria, test_results, notes, reviews) moved toticket_showonly. Response shape changed from array to{tickets, total, offset, limit}object.
- MCP:
ticket_listnow paginates results (default limit 50) to prevent responses exceeding MCP client token limits. Newoffsetandlimitparameters control pagination.
revertCLI command andticket_revertMCP tool to move tickets backward in the pipeline (e.g., verify → implement when rework is needed). Requires--toand--reasonflags; appends audit note.
statusfield: replaced entirely bystagepipeline field. Legacy tickets withstatusauto-migrate on read.tk start,tk close,tk reopencommands removed. Usetk advanceand pipeline stages instead.--statusfilter flag removed fromtk ls. Use--stageinstead.statusgroup-by option removed fromtk ls --group-by.statusfield removed from MCPticket_create,ticket_edit, andticket_showresponses.
- MCP:
ticket_list,ticket_ready, andticket_blockedreturn[]instead ofnullwhen no tickets match filters - TUI: Detail view now word-wraps body text, review log entries, and notes to fit terminal width
- TUI: Unified visual layout across open, edit, and create screens (consistent header style, fixed-width labels, matching indentation)
- TUI: ctrl+j inserts newlines in multi-line form fields (description, note)
- TUI: ctrl+s saves/submits form in edit and create mode (works from any field, including choice fields)
- MCP: design/acceptance/test_results fields with
##markdown headings no longer get truncated on read-back - Scanner buffer increased from 64KB to 1MB per line in ticket parser, preventing silent failures on large fields
- MCP:
ticket_editno longer silently swallows re-read errors after update
ticket_createandticket_editMCP tools now supportriskparameter for setting risk level (low, normal, high, critical)
- Pipeline configuration externalized to embedded JSON (
pkg/ticket/pipelines.json) - New pipeline stages:
design-reviewandcode-reviewfor explicit review phases - Risk-based pipeline variants: each ticket type can have different stage sequences per risk level (low, normal, high, critical)
PipelineFor()now accepts optional risk level parameter to select variant pipelines- Hybrid gate model: structural gates (checked server-side) and agentic gates (declared in config, returned as requirements)
EvaluateGates()returns structured gate results with type, status, and descriptionsAllStages(),DisplayStages(),GateInfoFor()config accessor functionsPipelineDescription()generates workflow text from config data- TUI pipeline view colors for new
design-reviewandcode-reviewstages ticket_pipelinesMCP tool: returns full pipeline config (stages with roles, variants, gates) as structured JSON for orchestrator consumption- Stage roles in pipeline config:
intake,definition,work,review,terminal— enables orchestrators to dispatch based on stage type ticket_advanceMCP tool now returns structured gate results (name, type, status, description) and acceptsevidenceparameter for agentic gate attestation
- Stage validation is now config-driven instead of hardcoded map
cmd/pipeline.goreads stages from config instead of hardcoded list- TUI pipeline columns read from config instead of hardcoded
allStages tk workflowcommand generates output from pipeline configticket_workflowMCP tool generates output from pipeline config- Risk-based gate scaling (
applyRiskScaling) removed; replaced by pipeline variants - Help text updated to reflect new stages and risk-based pipeline variants
tk workflowandticket_workflownow show normal pipeline variants alongside defaults
- TUI
dkey to delete ticket from dashboard with y/n confirmation prompt branchfrontmatter field to track git branch associated with a ticket--branchflag ontk editto set/clear the branch field- MCP
ticket_createandticket_editsupportbranchparameter
MoveTicketnow shallow-copies the full struct instead of manually listing fields, preserving Stage, Review, Risk, Branch, Skipped, and Conversations; resets Stage to triage and clears Review on move- Ticket body accumulated extra blank lines on each save (parse→serialize round-trip)
- TUI dashboard ID column dynamically sized to widest ticket ID instead of hardcoded 24 chars
- TUI
vkey on verify tab advances ticket to next stage;Ron review tab approves review - TUI file watcher — auto-reloads tickets when
.tickets/directory changes (fsnotify with 200ms debounce) - TUI edit mode (
e) — edit title, description, type, priority, assignee, stage, and add notes from the form view - TUI
okey as alias forenterto open ticket detail
- TUI default view is now a single-pane inbox with tabbed filters: all, triage, verify, review
- Removed status-based list view and pipeline kanban as default — focused on human decision points
- Pipeline view now supports text search (
/), priority cycling (p), and create (c) - TUI detail view help bar uses consistent
(k)eyformat with│separators
- TUI form text fields wrap long text across multiple lines instead of scrolling horizontally off-screen
- TUI form text fields overflowed past terminal width — now truncated with cursor-aware viewport, left/right arrow movement, and home/end support
- MCP
ticket_createdidn't setcreatedtimestamp — tickets created via MCP had zero-value dates - TUI list view ID column truncated slug-based IDs — column width now computed dynamically from visible tickets
- TUI pipeline view missing
ckeybinding for create — now matches list view behavior
- TUI create form failed with "ticket ID is required" —
handleCreateTicketwas missingGenerateID()andCreatedtimestamp
- Encouraging messages on empty listing output — ls, ready, blocked, inbox, closed, pipeline, and next show a random message from a pool of 20 when results are empty.
--jsonreturns[].
- MCP
ticket_createfailed with "ticket ID is required" — handler was missing ID generation, status, and stage initialization - Notes with
**bold**markdown lines were split into multiple notes during parsing —parseNotesnow validates timestamp before flushing - MCP
ticket_editsilently dropped description, design, and acceptance fields — handler now usesUpdateSectionto persist body fields - MCP gate checks required body sections unreachable via
ticket_edit— addedtest_resultsfield and exposed## Test Resultsin show output
- Homebrew install — use formula (
brews) instead of cask (homebrew_casks) in GoReleaser config
--repoglobal flag — operate on any repo from anywhere (tk ls --repo ~/code/other-project). Walks up from the given path to find.tickets/, same as CWD resolution. Errors if no.tickets/found.- Stage pipeline system — type-dependent stage pipelines replace flat status enum
- 7 stages: triage → spec → design → implement → test → verify → done
- Type-dependent pipelines: feature (7), bug (5), task (5), chore (3), epic (4)
- Gate enforcement — structural preconditions for stage transitions
- Risk-scaled gates (low=advisory, normal=standard, high/critical=strict)
- Mandatory code + impl review gates at implement → test
- Review system — ReviewState tracking (pending/approved/rejected) with ReviewRecord audit log
- Pipeline workflow functions —
Advance(),Skip(),SetReview()in pkg/ticket - Stage propagation —
PropagateStage()for parent stage advancement based on children - Migration —
MigrateTicket()/MigrateAll()for status → stage conversion- Mapping: open→triage, in_progress→implement, needs_testing→test, closed→done
- Inbox/next-action derivation —
Inbox(),NextAction(),Projects()for workflow visibility - New Ticket struct fields: Stage, Review, Risk, Skipped, Conversations, Reviews
- Review Log section parsing and serialization in ticket markdown format
ValidateStageForType(),ValidateGates()validation functions- Pipeline helpers:
NextStage(),PrevStage(),HasStage(),StageIndex(),IsFinalStage() - CLI commands:
advance,skip,review,log,pipeline,inbox,next,migrate - Edit flags:
--stage,--review,--riskfor direct field editing - ls --group-by=pipeline groups tickets by pipeline stage
- Backward compatibility:
start/close/reopenmap to stage equivalents with hint - MCP tools:
ticket_advance,ticket_review,ticket_skip,ticket_migrate,ticket_inbox - New tickets default to
stage: triageon creation - Integration tests for all pipeline commands (188 assertions total)
- Human-readable ticket IDs — IDs now use up to 3 meaningful words from the title instead of directory-name prefix (e.g.,
fix-login-page-fe32instead oftic-fe32). Existing tickets keep their IDs unchanged. GenerateID()now requires a title argument; stop words (articles, prepositions, etc.) are stripped from the slugStore.Create()returns an explicit duplicate error instead of relying on hash collision retrylsdefaults to workflow grouping (In Progress / Ready / Blocked). Use--flatfor the old flat list.lsshows dep count ((2 deps)) instead of full dep ID list (<- [t-1234, t-5678])- Ticket validation accepts either
status(legacy) orstage(pipeline) — dual support for migration - format.go writes stage/review/risk/skipped/conversations fields when present
showchecks both status and stage for blocker/blocking displaylsexcludesstage: donetickets from default viewprintRowshows stage when available, falls back to status- Help text updated with pipeline commands and options
- MCP
toJSONincludes stage/review/risk/skipped/conversations/reviews fields
Go rewrite. Full CLI parity with bash version plus new capabilities. Both implementations remain supported and read/write the same ticket format.
- Go binary — cross-platform, single binary distribution via Homebrew and AUR
- TUI (
tk ui) — interactive ticket browser with list/detail views, inline editing, ticket creation - MCP server (
tk serve) — stdio MCP server for Claude Code integration --jsonglobal flag on all output commands--version/-vflag (version injected at build time via GoReleaser)statscommand — project health dashboard (status/type/priority breakdowns, open ticket age)timelinecommand — bar chart of tickets closed by week with--weeks=Nflagmovecommand — move tickets between repos with--recursivefor full subtree moves--group-byflag forls(workflow, type, status, priority) with--groupshorthand--noteflag foreditas alias foradd-note--design,--acceptanceflags support multiline text (bash awk limitation fixed)- GoReleaser config for darwin/linux arm64/amd64 builds
- Comprehensive test suite (144 assertions)
- ID generation uses nanosecond timestamps + atomic counter (eliminates rapid-create collisions)
createretries with new ID on collision (up to 5 attempts)
ls --parentnow correctly filters to children only- Multiline
--designand--acceptanceflags work correctly (bash awk limitation) - ID collisions when creating multiple tickets per second
listalias forlscommandneeds_testingstatus-s, --statusflag foreditcommand to change ticket status- Hierarchy gating:
readyonly shows tickets whose parent isin_progress --openflag forreadyto bypass hierarchy checks- Status propagation:
needs_testing/closedauto-bubble up parent chain workflowcommand outputs guide for LLM context-t, --typefilter flag forlscommand- Interactive prompts when
tk createis run with no arguments - Support
TICKETS_DIRenvironment variable for custom tickets directory location dep cyclecommand to detect dependency cycles in open ticketsadd-notecommand for appending timestamped notes to tickets-a, --assigneefilter flag forls,ready,blocked, andclosedcommands--tagsflag forcreatecommand to add comma-separated tags-T, --tagfilter flag forls,ready,blocked, andclosedcommands-P, --priorityfilter flag forlscommanddeletecommand to remove ticket files
createcommand now displays full ticket details on success instead of just the IDeditcommand now uses CLI flags instead of opening $EDITOR
start,testing,close,reopen,statuscommands (useedit -sinstead)
update_yaml_fieldnow works on BSD/macOS (was using GNU sed syntax)
--parentflag forcreatecommand to set parent ticketlink/unlinkcommands for symmetric ticket relationshipsshowcommand displays parent title and linked ticketsmigrate-beadsnow imports parent-child and related dependencies
editcommand no longer hangs when run in non-TTY environments
Initial release.