Workspaces¶
Everything a person reads or edits lives at the top level of the workspace; machine state lives under .triage/, which init adds to .gitignore.
triage.toml project definition: repo, checkout, env, categories, fields, rules, skills, models, sandbox
settings.json agent defaults saved from the app's Settings page (overrides [agents])
AGENTS.md the procedure agents follow
NOTES.md reusable techniques agents add as they learn them
issues/<N>.md one writeup per issue, the source of truth
repros/<N>*.py reproducers, their logs and screenshots
INDEX.md generated overview of all writeups
prs/policy.md the contribution policy PR review checks against
skills/ agent skills (directories with a SKILL.md)
prompts/ role prompts for triage and review
templates/ the writeup template
triage.py entry point: ./triage.py <command>
.triage/ issue list, caches, claims, jobs, transcripts, label and PR review results
Writeups¶
A writeup is markdown with YAML frontmatter:
---
issue: 386
title: "MultiSelect marks first item in options when values match"
category: confirmed
confidence: high
reproduced: yes
repro: repros/386_app.py
recommendation: keep
summary: "Selecting a later option with a duplicate label still marks the first one"
verified: no
---
## Diagnosis
...
## Proposed GitHub comment
...
./triage.py validate checks writeups against the categories, fields and rules in triage.toml. ./triage.py finish <N> stamps the tested-on versions, validates the file, releases the claim and regenerates INDEX.md. When you edit a writeup in the app it is validated before saving, and the editor warns you if the file changed on disk in the meantime.
Categories and fields¶
[[categories]] lists the outcomes agents can choose from, in decision order; the order is part of the procedure in AGENTS.md. [fields] adds project-specific frontmatter fields, each with a type (str, bool, enum, list), optional values, default and required, and a column title to show it in INDEX.md.
[fields]
classic_ui = { type = "bool", default = false, required = true, column = "Classic" }
pmui_reproduces = { type = "enum", values = ["yes", "no", "untested", "n/a"], default = "n/a" }
Rules¶
Rules encode project knowledge that would otherwise live in a prompt. There are three stages:
validaterules (the default stage) check finished writeups.whenmatches frontmatter values, andrequirelists fields that must then be filled, orexpectlists the values they may have.scaffoldrules set fields when a writeup is created, based on what the issue mentions.contextrules add hints next to components detected in the issue text, shown in./triage.py context.
Scaffold and context rules can test attributes of detected components with "component.<attr>" = true. The component map comes from [components], typically generated by a script in the project.
# Panel: classic widgets with a panel-material-ui counterpart
[[rules]]
stage = "scaffold"
when = { "component.modern" = true }
set = { classic_ui = true }
[[rules]]
stage = "context"
when = { "component.modern" = true }
hint = "modern counterpart: `{modern}`; test it too"
[[rules]]
when = { category = "classic-ui" }
expect = { pmui_reproduces = ["no", "untested"] }
message = "classic-ui requires `pmui_reproduces: no` or `untested`"
Skills¶
Skills are directories with a SKILL.md (name, description and instructions). [skills] paths lists where to look; each entry can be a skill or a directory of skills. The built-in agent sees every enabled skill's name and description and loads the full instructions only when it needs them. Disable skills with [skills] disabled or from the Settings page, and list them with ./triage.py skills.
Syncing¶
./triage.py sync fetches the open issue list (title, labels, issue type, update time). --details also refreshes the cached body, comments and timeline of every issue, and --stale only those that changed since they were triaged. ./triage.py stale lists writeups whose issue has new activity. The Sync page in the app shows the same information with a history of past syncs.