Skip to content

Concepts

Troth has five kinds of object. Four of them nest; the fifth cuts across everything.

A spec is an area of the codebase, not a plan or a ticket. A spec named cli represents the CLI part of the system, and it persists for as long as that part exists. Tasks come and go inside it; the spec stays.

The test for whether something is a spec is: what files does it own that no other spec owns? If you cannot answer that, it is not a spec.

  • Sub-specs subdivide structure, not effort. A sub-spec exists because that part of the code is a real subdivision, not because it was phase two of a project. Set a parent with troth spec new <name> --parent <parent> or change one later with troth spec reparent.
  • Layers classify a spec as platform, services, or surface.
  • Statuses are new, decomposed, in-progress, done, and failed, recomputed from task completion by troth spec refresh.

Before creating a spec, run troth spec list and find where the work belongs in the existing structure. New top-level specs are rare. An enhancement to a directory a spec already owns is a task on that spec. A cross-cutting concern is tasks distributed across the affected specs, not a new spec. An idea with no code behind it is a finding, not a spec.

A spec body is markdown with these sections:

Section Contents
Intent What this subsystem does and why, in a paragraph of plain language
Architecture Data flow and key abstractions
Key Files A table of important files and their roles
Patterns Recurring conventions in this subsystem
Constraints Hard boundaries: security, performance, compatibility. Human-authored
Open Questions Unresolved decisions, so agents do not invent answers
Acceptance Criteria Testable completion conditions

A task is a unit of work inside a spec. troth decompose <spec> generates them from the spec, or troth task create <spec> <task> writes one directly.

A well-formed task carries:

  • objective: what to do, in one sentence
  • intent: why it exists, including the current state and expected impact, not a restatement of the objective
  • file_scope: the one to five files it touches
  • verification: shell commands plus what each proves, with at least one behavioral check rather than only a typecheck
  • guardrails: what not to do, as specific boundaries
  • acceptance_criteria: binary pass or fail conditions
  • dependencies: task names that must complete first
  • complexity: simple, moderate, or complex

Task status moves through new or pending, in-progress, and then one of passed, failed, blocked, or canceled. Two intermediate states appear during execution: local-verified means the code is correct against local gates, and passed means it also satisfied production criteria where the task declared any.

Every task ends with an explicit status update carrying notes. troth task done runs the verification gates before it will mark anything passed.

Acceptance criteria that a machine can check

Section titled “Acceptance criteria that a machine can check”

Anything mechanically verifiable should be a structured criterion rather than a sentence. A structured criterion names a subject (a file, endpoint, or table), a property (contains_string, file_exists, http_status, column_exists, and others), an expected value, and a method that checks it. troth test <task> runs them without interpretation.

Criteria can be tagged with an environment. Local criteria prove the code is correct; production criteria prove the deployed thing works. Tasks involving migrations or deployments should carry both. Plain English criteria are reserved for things that genuinely need human judgment.

Proving something is absent is the one case that trips people up. A gate that greps for a forbidden string exits zero when it finds the string, which is backwards. Set proves_absence: true on the gate instead of hand-writing a negation; the runner inverts the check for you.

A request records intent, and it sits above specs and tasks. It is the trace from an original ask through to the work that answered it. A bug report, a feature suggestion, or an idea that came out of a conversation all start as requests.

Terminal window
troth request create "Refunds fail on partial captures" --description "..."
troth request link <id> --task payments/add-refund-endpoint
troth request resolve <id> --outcome resolved --learning "..."
troth request search "refund"
troth learnings

One request can spawn several specs and tasks, or be answered by work that already exists. Resolving one requires a learning, which is what makes troth learnings worth reading later. Search before creating, so intent does not get filed twice.

A finding is the intake pile: something noticed mid-flight that should not derail the current task. There are two types, bugs and ideas.

Terminal window
troth bug "Webhook retries forever on 409"
troth idea "Cache the spec index between invocations"
troth findings

Findings move through new, triaged, planned, and dismissed. Confirming a finding triages it; promoting it turns it into a task or a request; dismissing it takes it out of the default listing. Findings are deliberately cheap to create, because the alternative is losing them.

Foundations are the constraints that apply across every spec, automatically. They are not specs and they do not belong to one area of the code.

Foundation What it holds
Constitution Values, constraints, and positioning, as markdown prose
Design bible Visual language, component patterns, typography, color, UX conventions
Design tokens The machine-readable values behind the bible, validated against a schema
Design assets Logos, swatches, and reference images

Each has a scope. Project scope writes into the repository’s own .troth/foundations/ directory. Workspace scope writes into your home directory and applies across projects.

Terminal window
troth foundations show
troth constitution set constitution.md
troth bible set design-bible.md
troth tokens set tokens.json
troth asset add logo.svg

Pull foundations before design or UI work. Over MCP, start_session returns them without a separate call.

Requests explain why work exists. Specs say where in the code it belongs. Tasks are the work itself, scoped to files and gated by verification. Findings are the queue of things not yet promoted into either. Foundations constrain all of it.

The storage layout under .troth/ mirrors that:

.troth/
specs/ feature specifications, one markdown file each
tasks/<spec-name>/ task breakdowns, one YAML file each
runs/<spec-name>/ execution logs and results
foundations/ constitution, design bible, tokens, assets

Specs are named in kebab-case. Run troth guide for the complete workflow reference, including the full task YAML format and the structured criteria specification.