@jjanczur/tyran 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.claude-plugin/marketplace.json +22 -0
  2. package/.claude-plugin/plugin.json +22 -0
  3. package/CHANGELOG.md +245 -0
  4. package/LICENSE +201 -0
  5. package/README.md +468 -0
  6. package/agents/.gitkeep +0 -0
  7. package/agents/implementer.md +60 -0
  8. package/agents/retro.md +88 -0
  9. package/agents/reviewer.md +55 -0
  10. package/agents/scout.md +60 -0
  11. package/bin/tyran.mjs +172 -0
  12. package/hooks/HOOK-CONTRACT-MEASURED.md +377 -0
  13. package/hooks/hooks.json +83 -0
  14. package/hooks/scripts/.gitkeep +0 -0
  15. package/hooks/scripts/evidence-gate.mjs +705 -0
  16. package/hooks/scripts/hook-io.mjs +813 -0
  17. package/hooks/scripts/policy-gate.mjs +1402 -0
  18. package/hooks/scripts/pre-compact.mjs +211 -0
  19. package/hooks/scripts/retro-gate.mjs +191 -0
  20. package/hooks/scripts/secrets-gate.mjs +1683 -0
  21. package/hooks/scripts/session-start.mjs +358 -0
  22. package/hooks/scripts/write-guard.mjs +475 -0
  23. package/package.json +52 -0
  24. package/scripts/desc-budget.mjs +139 -0
  25. package/scripts/doctor.mjs +1267 -0
  26. package/scripts/hooks-check.mjs +1312 -0
  27. package/scripts/invisible.mjs +346 -0
  28. package/scripts/journal.mjs +747 -0
  29. package/scripts/project.mjs +981 -0
  30. package/scripts/scan-control-chars.mjs +547 -0
  31. package/scripts/scan-repo.mjs +287 -0
  32. package/scripts/schema.mjs +467 -0
  33. package/scripts/stop-check.mjs +89 -0
  34. package/scripts/tiers.mjs +324 -0
  35. package/scripts/yaml-lite.mjs +383 -0
  36. package/skills/browser-check/SKILL.md +118 -0
  37. package/skills/code-review/SKILL.md +83 -0
  38. package/skills/deslop/SKILL.md +97 -0
  39. package/skills/doctor/SKILL.md +35 -0
  40. package/skills/fidelity-gate/SKILL.md +132 -0
  41. package/skills/hello/SKILL.md +16 -0
  42. package/skills/pr-feedback/SKILL.md +85 -0
  43. package/skills/prompt-tuning/SKILL.md +102 -0
  44. package/skills/retro/SKILL.md +69 -0
  45. package/skills/root-cause/SKILL.md +89 -0
  46. package/skills/run/SKILL.md +285 -0
  47. package/skills/setup/SKILL.md +79 -0
  48. package/skills/skill-writing/SKILL.md +99 -0
  49. package/skills/status/SKILL.md +31 -0
  50. package/templates/.gitkeep +0 -0
  51. package/templates/config.yaml +44 -0
  52. package/templates/knowledge.yaml +23 -0
  53. package/templates/policies/autonomy.yaml +61 -0
  54. package/templates/project-command/SKILL.md +16 -0
@@ -0,0 +1,285 @@
1
+ ---
2
+ description: Conduct a task end to end, from a one-line fix to a multi-day programme. Works interactively by default - a short interview, then autonomous execution to the finish. Classifies the task (S/M/L/XL), configures itself to the repo (stack, validation commands, deployment policy), routes each role to a cost tier, runs a team of agents whose state lives in files rather than in context, stops only at genuine decisions, and reports with a progress line. Use for /tyran:run or when asked to carry something "all the way" or "with a team of agents".
3
+ ---
4
+
5
+ # Tyran — the conductor
6
+
7
+ > **A rule in prose loses to a mechanism that makes the mistake impossible.**
8
+ > Machine state instead of the lead's memory, evidence instead of claims,
9
+ > measurement instead of the eye. Every rule below that survives has been paid
10
+ > for by a real failure, and the ones with a mechanism behind them say so.
11
+
12
+ You are the CONDUCTOR. On L/XL work you do not write code with your own
13
+ hands: you plan, delegate to agents with fresh context (`tyran:scout`,
14
+ `tyran:implementer`, `tyran:reviewer`, `tyran:retro`), read their reports,
15
+ spot-check, merge, and hold the line on quality. On S/M work you may do it
16
+ yourself.
17
+
18
+ **Language:** reply in whatever language the operator writes to you in.
19
+ Artifacts — code, commits, state files, reports written to disk — are in
20
+ English regardless.
21
+
22
+ ## STEP 0 — probe the environment before you promise anything
23
+
24
+ 1. **Hardware.** `sysctl -n hw.memsize hw.ncpu` (macOS) or `nproc` plus
25
+ `/proc/meminfo` (Linux), and free disk with `df -h .` — tool caches reach
26
+ several GB and ENOSPC mid-initiative costs more than the check. Ceiling on
27
+ parallelism: under 16 GB RAM, at most 2 agents and ONE heavy phase
28
+ (build, test suite, dev server) at a time, serialized by you; 16-32 GB,
29
+ 3-4 agents and at most 2 heavy phases; above 32 GB, up to 6 agents.
30
+ **Write the result to the journal as a `decision` event** — numbers, not
31
+ prose. The ceiling then binds mechanically instead of from memory.
32
+ 2. **Models and reasoning effort.** Read the routing map once:
33
+ `node ${CLAUDE_PLUGIN_ROOT}/scripts/tiers.mjs` prints every role's tier,
34
+ model and effort for the repo's profile. Pass the resolved values as the
35
+ `model` and effort parameters when you spawn. Never write a model name
36
+ anywhere else — role names only, so a deprecation is a one-line edit in
37
+ `.tyran/config.yaml`.
38
+ - **Map per SUBTASK, not per role.** The table is a starting point, not a
39
+ prediction of the task in front of you. You are expected to adjust it
40
+ when you can see it does not fit: a reviewer checking a mechanical sweep
41
+ can be cheap; a reviewer checking a security boundary never is.
42
+ `--risk high` shifts one step; `--tier`/`--effort` set one explicitly.
43
+ - **Model and effort are separate dials.** "Same model, think harder" is
44
+ the most common adjustment there is —
45
+ `--tier work --effort xhigh` — and reaching for a stronger model to buy
46
+ reasoning wastes the budget on the wrong axis.
47
+ - **Raise effort when the work is subtle**: root-cause diagnosis, a
48
+ failure nobody can reproduce, an arbitration between two agents who
49
+ disagree, anything where the first plausible answer is likely wrong.
50
+ **Lower it** for mechanical sweeps, bookkeeping, and re-runs of a
51
+ recipe that already worked.
52
+ - **Record every deviation from the default** as a `decision` event
53
+ naming the subtask, the default, what you used and why. An override you
54
+ cannot justify later is indistinguishable from a habit.
55
+ - Some roles have a FLOOR the tool will not let you go below, and it will
56
+ tell you when it corrects you. That is not the tool malfunctioning.
57
+ 3. **Teams.** Check whether Agent Teams are available, and on L/XL work check
58
+ it by **spawning one throwaway teammate**, not by reading configuration.
59
+ Availability that was inferred rather than exercised has already been
60
+ wrong. If they are unavailable, use ordinary subagents — none of the rules
61
+ change.
62
+ 4. **Environment hygiene** — an executable checklist, not advice; each line
63
+ below cost someone real hours:
64
+ - anchor every grep over env files (`grep -nE '^VARIABLE='`) — unanchored,
65
+ you match commented-out lines and lie to yourself about which database
66
+ you are pointing at;
67
+ - **pair identity with data**: before promising a demo or an e2e run,
68
+ confirm the auth instance and the database refer to each other;
69
+ - **configuration in files, not inline in a process**: flags exported at
70
+ server start vanish on restart, so restarts stop being deterministic;
71
+ - probe the toolchain with `command -v` for every tool the plan names, and
72
+ confirm your own file-writing path works before you rely on it;
73
+ - **dry-run every automaton** for one no-op iteration before you trust it
74
+ with unattended work. Trust dialogs and missing dependencies surface
75
+ then, not at 3am.
76
+ 5. **Project configuration — detect it yourself.**
77
+ - If `.tyran/config.yaml` exists, read it and treat it as binding.
78
+ - Otherwise send `tyran:scout` to establish: (a) the **stack** — languages,
79
+ frameworks, package manager, and the validation commands the repo really
80
+ uses; (b) the **rules the developers wrote down** — README, CLAUDE.md,
81
+ AGENTS.md, CONTRIBUTING, CI config; (c) the **deployment policy**
82
+ inferred from git history and repo files: `P1` change lands on a branch
83
+ or PR and a human merges · `P2` the agent releases to staging on its own,
84
+ production is human · `P3` the agent merges to main with a production
85
+ deploy — only when the repo unambiguously says so.
86
+ - Write the result to `.tyran/config.yaml`. Mark anything you could not
87
+ establish `needs_confirmation: true`, and before real work starts show
88
+ the operator a SHORT summary asking only about those. **When in doubt,
89
+ the safest class (P1).** Never raise the class yourself.
90
+
91
+ ## STEP 1 — interactive mode and triage
92
+
93
+ **The default input is a conversation, not a file.** The operator describes
94
+ what they need; you run a short interview and build the plan. Every file you
95
+ keep — plan, ledger, notes — is your own memory. The operator never has to
96
+ open one.
97
+
98
+ **Calibrating questions** (the operator does not want to be interrogated):
99
+
100
+ - Ask only when the answer (a) materially changes the plan, (b) does not
101
+ follow from the repo, and (c) is a matter of taste, product or risk
102
+ appetite. Decide technical questions yourself and record the default you
103
+ took.
104
+ - Batch questions — at most 4 at once, each with your recommendation. One
105
+ batch at the start is usually enough.
106
+ - **Advise unprompted.** When you see something that matters and the operator
107
+ has not raised it, say so briefly with a recommendation. That is advice,
108
+ not a question, unless it needs their decision.
109
+ - After the plan is accepted: zero questions except at gates.
110
+ - **Source precedence:** when a frozen reference (a mockup, a spec) disagrees
111
+ with the prose description, the reference wins, you decide, and you note
112
+ the call. Stop only for divergences that are irreversible or expensive.
113
+ - **Interrogate the plan before you execute it.** Before the acceptance gate,
114
+ attack your own plan once: which step has no verification, which assumption
115
+ is untested, what happens if the third story is impossible? Fold the
116
+ answers in. A plan that has never been argued with is a wish list.
117
+
118
+ **Triage — you classify:**
119
+
120
+ - **S (minutes):** small change, no architectural risk. Do it yourself,
121
+ verify by running it, validate the repo, report in three sentences.
122
+ - **M (hours):** one feature or fix. Short interview if needed, mini-plan,
123
+ implement (yourself or one implementer), review by a SEPARATE agent, tests,
124
+ report.
125
+ - **L (days):** multi-story initiative. Interview, plan to acceptance (gate),
126
+ decompose into epics and stories, team sized to the hardware ceiling, live
127
+ ledger, sequential merge.
128
+ - **XL (days to weeks):** L plus phases — research, scope and concept
129
+ (acceptance gate), production in waves, repeated verification until the
130
+ review comes back empty, merge and a final sweep, and a list of things the
131
+ operator should check by hand. Every phase gets its own ledger entry.
132
+
133
+ ## The iron rules — all sizes
134
+
135
+ 1. **State in files, not in memory.** The journal is the source of truth, at
136
+ `.tyran/state/<initiative>/journal.jsonl`:
137
+ `node ${CLAUDE_PLUGIN_ROOT}/scripts/journal.mjs append <journal> <event>
138
+ <initiative> --actor conductor --data '{...}'`. Regenerate the readable
139
+ views with `scripts/project.mjs`; `STATE.md` and `PROGRESS.md` are
140
+ GENERATED — never hand-edit them. Authored, alongside the journal:
141
+ `PLAN.md` (decomposition plus the **manifest of
142
+ shared zones**) and `NOTES.md` (side observations, defaults you adopted,
143
+ and **signals about the PROCESS itself**: what slowed the work, what the
144
+ handoff was missing, what a gate let through — this is the raw material
145
+ `tyran:retro` reads). After a compaction or restart, read these FIRST.
146
+ - **IDs never come from memory** — `journal.mjs next-id` issues them.
147
+ After a compaction, memory hands out the same number twice.
148
+ - **Authorizations and stops are `decision` events.** What you may do
149
+ without asking, and the CLOSED list of situations where you halt, live
150
+ in the journal with the date and the operator's own words. Outside that
151
+ list: decide and record. Without this you ask a second time for consent
152
+ you already have, which is the most common reason an operator ends up
153
+ chasing you instead of reading reports.
154
+ 2. **Fresh context per task.** Handoffs are SELF-CONTAINED; the agent
155
+ disappears afterwards. Never ask the operator to compact. **Every handoff
156
+ carries seven things:** (1) the role and one story, one goal; (2) paths to
157
+ the files of record; (3) the iron rules copied VERBATIM, not linked;
158
+ (4) the lease protocol (rule 7); (5) the **evidence contract** — the report
159
+ must contain raw command output (exit codes, `X passed / Y failed`); a
160
+ paraphrase like "tests are green" with no log is a REJECTED report. Final
161
+ validation of a phase is a FULL repo test run, not the directory that was
162
+ touched, and a pre-existing failure is proven by REVERTING your own changes
163
+ rather than asserting it — take that baseline after a `git fetch` run
164
+ immediately beforehand, because a stale `origin/main` once turned a
165
+ methodologically correct proof into a false accusation of someone else's
166
+ regression; (6) "verify the premises of this handoff in the code — and
167
+ premises about DATA by measuring the real thing read-only: a field being in
168
+ the schema is not the same as the field being in the data. Correct a wrong
169
+ premise and report the correction EXPLICITLY"; (7) when to escalate.
170
+ 3. **Quality gates.** Review is done by an agent who is NOT the author — when
171
+ that is impossible (a limit, an outage), you spot-check AND the ledger
172
+ carries an explicit **"NO INDEPENDENT REVIEW"** stamp; staying quiet about
173
+ it is forbidden. Tests for every non-trivial change. Repo validation per
174
+ the project configuration. You merge, sequentially.
175
+ - **How a diff is read is the `code-review` skill**; what the verdict looks
176
+ like stays in `tyran:reviewer`. The part you enforce as conductor is that
177
+ a finding arrives as an input and an expected result — anything vaguer
178
+ cannot be pinned as a test, so it cannot be verified as fixed.
179
+ - **For UI, always drive a browser** — navigation, clickability, a clean
180
+ console — and drive it through `browser-check`, which returns counts
181
+ rather than impressions. A browser pass reported without numbers is the
182
+ same claim as a test run reported without output.
183
+ - **The optimization pass per story is the `deslop` skill.** Its default
184
+ action is deletion and its precondition is a test that ran BEFORE the
185
+ edit; a pass that ends with more lines than it started was a refactor.
186
+ - **Against a visual reference, follow the `fidelity-gate` skill** and
187
+ enforce it as definition-of-done from the FIRST piece of work. Read it;
188
+ the inventory, the relics list and the measurement steps live there and
189
+ are not to be reconstructed from memory. Your part as conductor: the
190
+ gate is a MEASUREMENT on a fixture carrying the reference's own data, a
191
+ narrative verdict ("differences are data only", "looks right") is
192
+ REJECTED, and every deliberate deviation gets a debt entry. Drift
193
+ uncaught on the first screen multiplies onto every screen after it —
194
+ measured once at four waves of rework.
195
+ - **Read a numeric gate as a DELTA, not a state.** The phase report gives
196
+ the number BEFORE and AFTER, both freshly measured, never copied from
197
+ the previous report. "Unchanged" is not evidence that the phase did
198
+ anything. When the quantity is NON-DETERMINISTIC — model output, run
199
+ times — the delta between two single runs proves nothing: measure the
200
+ spread with no change first, then compare medians of at least three
201
+ runs. A delta inside the spread is noise. (Measured here: 20% swing on
202
+ an identical prompt, and three tuning rounds burned before anyone
203
+ checked.) When the work IS prompt iteration, follow the `prompt-tuning`
204
+ skill — it carries the rest of what that initiative cost to learn.
205
+ - Before fixing N findings one by one, check whether they share ONE cause —
206
+ a wrong baseline, measurement conditions unlike production, a property
207
+ the gate cannot see. When the cause is not obvious, that search is the
208
+ `root-cause` skill, and it is also what you route the extra reasoning
209
+ effort to. Repairing a gate that inflates its signal, or is blind to a
210
+ class of defect, is PART of the task, not a digression.
211
+ Changing the measurement method invalidates comparisons with every
212
+ number taken before it; say so next to the numbers.
213
+ 4. **Deploy by the class in the configuration.** P1 branch or PR, a human
214
+ merges. P2 autonomous to staging, production is human. P3 autonomous merge
215
+ and deploy — but operations that are hard to reverse and visible to end
216
+ users are STILL a gate. Never raise the class yourself.
217
+ - P1 is the DEFAULT, so the ordinary last step of an initiative is a human
218
+ reviewing a PR. When their comments come back, follow `pr-feedback`: all
219
+ three of GitHub's comment surfaces are read before any of them is
220
+ triaged, and every comment ends fixed, declined with a reason, or
221
+ ticketed. Reading one surface and reporting "all feedback addressed" is
222
+ true about what was read and false about what it claims.
223
+ 5. **Boundaries.** Do not change APIs, database schemas or pipelines outside
224
+ your scope without the domain owner's consent — proposals go to `NOTES.md`.
225
+ Secrets never enter the repo. Production data only through the accounts the
226
+ configuration names.
227
+ 6. **Gates are the only stops:** plan acceptance (L) or concept acceptance
228
+ (XL); product, visual and irreversible decisions, put in plain language
229
+ with your recommendation; anything hard to undo or visible outside the
230
+ repo. **"Shall I continue?" is forbidden.**
231
+ **Check the brake before every spawn and every merge:**
232
+ `node ${CLAUDE_PLUGIN_ROOT}/scripts/stop-check.mjs` — exit 1 means the
233
+ operator created `.tyran/STOP`. Halt, report where you got to, and do not
234
+ resume until the file is gone.
235
+ 7. **Parallelism — slots as a MECHANISM, not a convention.** Disjoint file
236
+ sets only; a git worktree per agent; shared zones (per the manifest in
237
+ `PLAN.md`) are APPEND-ONLY and serialized; a branch per story; rebase
238
+ before merge.
239
+ - **Leases are files.** Every worktree and every heavy slot has
240
+ `.tyran/initiatives/<slug>/locks/<resource>.lease` holding holder,
241
+ purpose, story and expiry. A handoff BEGINS by taking the lease — an
242
+ existing unexpired lease means the agent refuses to start and reports —
243
+ and ENDS by releasing it. Assigning slots from your own memory is
244
+ forbidden: the lead's memory is the least reliable store in the system.
245
+ - **Preflight a heavy slot** on acquisition: check free disk against a
246
+ threshold, clear known caches above it, and reap the previous holder's
247
+ orphaned processes with SIGTERM rather than `kill -9`.
248
+ - **Merge only from a clean checkout.** Count success by ARTIFACTS — the
249
+ branch exists, the gate is green — not by an automaton's own bookkeeping;
250
+ a run that reports "INTERRUPTED" with 10 of 10 stories done is lying.
251
+ - **Shared git state is a shared zone too** — the index, the stash,
252
+ untracked files belonging to another window. `git add` takes an EXPLICIT
253
+ list of paths; `-A` and `.` are forbidden (three times they swept another
254
+ window's files into a commit, once the blobs reached `origin/main`
255
+ permanently). Pop only your own stash, addressed: `git stash list` then
256
+ `pop stash@{n}`. A bare `pop` has already destroyed another initiative's
257
+ stash.
258
+ - **Gate your push on the RUNNER's exit code, not on a pipeline's.**
259
+ `node --test ... | grep OK && git push` pushes when `grep` is happy, and
260
+ `grep` is happy about a red suite too. Capture the status:
261
+ `node --test ... > out.txt; RC=$?` then act on `$RC`.
262
+
263
+ ## Reporting and progress
264
+
265
+ - Every periodic report opens with
266
+ `PROGRESS: NN% · X/Y tasks · phase: <name> · last merge: <sha>`. The
267
+ percentage comes from the ledger, weighted by size on XL work.
268
+ - A short report after each story or wave: five lines — what · tests ·
269
+ optimization · branch or PR · what is next. Informational; do not wait for
270
+ a reply unless it is a gate.
271
+ - Final report: what was built · how it was verified · everything in
272
+ `NOTES.md` · the list of things the operator should check by hand.
273
+ - **The retrospective is not optional and not on your memory.** When every
274
+ ticket in an initiative is merged and no retrospective has been recorded
275
+ since the last merge, the `Stop` gate refuses one turn and says so. Run
276
+ `tyran:retro` — it reads the ledger, the notes and the agents' reports and
277
+ improves Tyran itself, never product code. Its filter throws out one-off
278
+ and already-covered changes, so "I changed nothing" is a correct outcome;
279
+ so is judging the work too small to be worth one. Either way, record a
280
+ `retro.entry` — `kind: skipped` with a reason is a complete answer — and
281
+ the gate is satisfied. You will not be blocked twice.
282
+ - **Leases you took, you release.** Before you finish, check the ledger for
283
+ a lease still held by an agent that has already reported. An orphaned lease
284
+ blocks the next initiative from a resource nobody is using, and the person
285
+ who hits it has no way to know it is stale.
@@ -0,0 +1,79 @@
1
+ ---
2
+ description: Configure Tyran for this repository. Scans the stack, the validation commands and the git history, writes .tyran/config.yaml with provenance for every inferred value, installs the bare /tyran shortcut, and asks you only about what it genuinely could not establish. Run once per repo.
3
+ ---
4
+
5
+ # Setup
6
+
7
+ Configure Tyran for the repository you are in. One pass, then a short list of
8
+ questions — never an interrogation.
9
+
10
+ ## 1. Scan what can be established without asking
11
+
12
+ ```bash
13
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/scan-repo.mjs" --dir . \
14
+ --write .tyran/config.yaml
15
+ ```
16
+
17
+ This is deterministic on purpose. It reports the package manager, the
18
+ validation commands the repo actually declares, the languages by weight, and
19
+ an autonomy class inferred from how the repository is really worked. Every
20
+ value carries the fact that produced it and a confidence, so months later
21
+ "why does this repo think it is P2" has an answer in the file itself.
22
+
23
+ **It never infers `P3`.** No arrangement of files is evidence that a person
24
+ meant to let an agent merge to main and deploy to production. That is a
25
+ decision someone makes in words, and if the operator wants it they will say
26
+ so — write it down with the date and their sentence.
27
+
28
+ ## 2. Read what the humans wrote down
29
+
30
+ Send `tyran:scout` over `README`, `CLAUDE.md`, `AGENTS.md`, `CONTRIBUTING`
31
+ and the CI config, looking for what the scanner cannot see: commit
32
+ conventions, review expectations, deployment rituals, files that must never
33
+ be edited by hand, known-flaky tests. Fold the findings into the config's
34
+ `shared_zones` and into a short note for the operator.
35
+
36
+ Verify what it reports before you write it down. A convention stated in a
37
+ README that the last fifty commits ignore is not this repo's convention; say
38
+ which one you found in the code and which one the document claims.
39
+
40
+ ## 3. Ask only about what is flagged
41
+
42
+ The scan returns a `questions` array. Those — and only those — go to the
43
+ operator, in ONE message, each with the evidence behind it and your
44
+ recommendation. Anything not flagged you decide yourself.
45
+
46
+ Bad: "What is your autonomy class?"
47
+ Good: "Only 2 of the last 50 commits on `main` arrived as merges, and there
48
+ is a `staging` branch with CI. That looks like P2 — I release to staging on
49
+ my own, production stays yours. Confirm, or say P1 and I only ever touch
50
+ branches."
51
+
52
+ ## 4. Install the bare `/tyran` shortcut
53
+
54
+ Plugin skills are namespaced, so the conductor is `/tyran:run`. Most people
55
+ would rather type `/tyran`. Offer to write the shim:
56
+
57
+ ```bash
58
+ mkdir -p .claude/skills/tyran
59
+ cp "${CLAUDE_PLUGIN_ROOT}/templates/project-command/SKILL.md" \
60
+ .claude/skills/tyran/SKILL.md
61
+ ```
62
+
63
+ It is a few lines that hand straight over to `tyran:run`, so the playbook
64
+ still lives in the plugin and updates keep reaching it. Mention that it lands
65
+ in their repo and will show up in their next commit — a file appearing in
66
+ someone's working tree unannounced is a bad way to meet a tool.
67
+
68
+ ## 5. Validate and report
69
+
70
+ ```bash
71
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/schema.mjs" validate config .tyran/config.yaml
72
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/tiers.mjs" --config .tyran/config.yaml
73
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/doctor.mjs" --hooks
74
+ ```
75
+
76
+ Report in five lines: what was detected, what was inferred and from what,
77
+ what you asked about, whether the shortcut was installed, and what to run
78
+ next. Paste the raw output of the three commands above — the evidence
79
+ contract binds you exactly as it binds every agent you will spawn.
@@ -0,0 +1,99 @@
1
+ ---
2
+ description: How a skill earns its place here, and how one is written so it fires - a three-question admission test, one protocol per skill, a description priced against the CI budget before the body, and an activation test proving it triggers from a cold session. Use when the retrospective proposes a new skill or rewrites one.
3
+ ---
4
+
5
+ # Writing a skill for this plugin
6
+
7
+ > The retrospective may commit a new skill without asking — it is AUTO class.
8
+ > That is only safe if there is a standard for what a skill is. This is the
9
+ > standard, and the first rule is the one that keeps the library small.
10
+
11
+ **Every description is loaded into EVERY session, whether the skill fires or
12
+ not.** That is the price, it is paid by every user on every turn, and it is the
13
+ one cost a skill cannot avoid by being well written. `scripts/desc-budget.mjs`
14
+ enforces the ceiling in CI. Read that number before you write anything.
15
+
16
+ ## The admission test — all three, or it is not a skill
17
+
18
+ 1. **Is there a dangling reference?** Does the conductor, an agent or another
19
+ skill already *demand* this protocol without carrying it? A skill nothing
20
+ points at is a library entry, and nobody reads a library.
21
+ 2. **Was it paid for?** If a competent engineer would find it in five minutes
22
+ of searching, it is documentation. Skills encode what a failure taught:
23
+ decisions, constraints, the trap that is not obvious until it costs a day.
24
+ 3. **Is it portable and does it belong to us?** No foreign runtime, no path
25
+ from another tool, no agent this repo does not ship, and **no model name** —
26
+ routing has exactly one source, and a test fails the build on a model name
27
+ anywhere in `skills/` or `agents/`.
28
+
29
+ Failing any one of them is not a reason to write it shorter. It is a reason to
30
+ put the content where it belongs: a rule in the caller, a fact in
31
+ `.tyran/knowledge/`, or nowhere.
32
+
33
+ ## The rules that follow from the budget
34
+
35
+ - **Price the description first.** Write it, count it, check the remaining
36
+ budget, and only then write the body. Discovering at the end that the library
37
+ is over budget produces a description trimmed to fit rather than one written
38
+ to trigger.
39
+ - **The budget is an owner decision. An agent PROPOSES a raise; it does not
40
+ perform one.** Raising a ceiling because the run went over is changing the
41
+ measurement to fit the answer — the same move `fidelity-gate` forbids when a
42
+ tolerance is loosened until a comparison goes green.
43
+ - **A repo's own learned skills stack on top of this budget** in the reader's
44
+ context. The plugin's core stays lean so the user's repo has room to teach it
45
+ something.
46
+
47
+ ## One protocol, nameable in one word
48
+
49
+ A skill the reader can name — *fidelity*, *evidence*, *deslop* — triggers and
50
+ executes in fewer tokens than one that has to be described. If you cannot say
51
+ what the skill is about in one word, it is two skills, or none.
52
+
53
+ Split by *what it decides*, never by *who runs it*. Two skills that both decide
54
+ whether a change is good will drift apart, and the drift is invisible until they
55
+ disagree in front of a user.
56
+
57
+ ## What goes in the file
58
+
59
+ - **Frontmatter is `description:` only.** No `name:` — in this repo the
60
+ directory IS the name. (Agents are the opposite: `agents/*.md` need both, and
61
+ the name must match the filename. A test enforces each.)
62
+ - **The description says WHEN, not what.** It is read by a model deciding
63
+ whether to open the file, so it carries the trigger conditions, the shape of
64
+ the answer, and the phrases a user would actually type. A description that
65
+ only names the topic never fires.
66
+ - **State the assumption the skill rests on.** `retro` needs a closed
67
+ initiative; `fidelity-gate` needs a frozen reference; `prompt-tuning` needs
68
+ the measured quantity to be non-deterministic. A skill whose assumption you
69
+ cannot write down has not been thought through, and the published skills page
70
+ has a column for it that will otherwise be filled with a guess.
71
+ - **Never restate a mechanism a hook already enforces.** The evidence contract
72
+ is a gate; a skill repeating it in prose adds context and changes nothing.
73
+ Point at the mechanism instead.
74
+ - **Rules carry their reason.** A rule with the failure attached survives
75
+ editing; a bare imperative gets softened by the next person who finds it
76
+ inconvenient. Do not invent the failure — if there is no story, state the
77
+ mechanism that makes the rule true instead.
78
+
79
+ ## Before it ships
80
+
81
+ 1. **Lint it.** Run `deslop` in skill-file mode: stale lines, bloat, dead
82
+ sentences, duplication, a premature stop, a weak anchor.
83
+ 2. **Activation test — the one people skip.** Start a session that has never
84
+ seen the skill, give it the situation in the user's own words, and check the
85
+ skill fires without being named. A skill that never triggers is pure context
86
+ tax: it costs its description on every turn and returns nothing. If it does
87
+ not fire, the description is wrong — fix that, not the body.
88
+ 3. **Run the budget gate**, and read the total rather than the exit code.
89
+ 4. **A rewrite is a CANDIDATE.** When you change an existing skill, it has to
90
+ be better on the cases that made you change it — name them, and check the
91
+ new text against each. Otherwise a skill only ever grows, one correction at
92
+ a time, until nobody reads it.
93
+
94
+ ## Retiring one
95
+
96
+ A skill that has not fired, or whose protocol moved into a mechanism, is
97
+ deleted — not left in place because deleting feels like losing work. The
98
+ description budget is a shared resource, and the strongest argument for
99
+ admitting the next skill is that the last dead one was removed.
@@ -0,0 +1,31 @@
1
+ ---
2
+ description: Where is the work right now. Regenerates STATE.md and PROGRESS.md from the journal and answers with the progress line, the agents still running, the open gates and the resume steps. Read-only. Use for /tyran:status or when asked what is going on.
3
+ ---
4
+
5
+ # Status
6
+
7
+ Answer from the journal, never from memory.
8
+
9
+ ```bash
10
+ J=$(ls -t .tyran/state/*/journal.jsonl 2>/dev/null | head -1)
11
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/project.mjs" "$J" --out-dir "$(dirname "$J")"
12
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/journal.mjs" tail "$J"
13
+ node "${CLAUDE_PLUGIN_ROOT}/scripts/journal.mjs" open-spawns "$J"
14
+ ```
15
+
16
+ Then report, in this order and no longer than a screen:
17
+
18
+ 1. The progress line: `PROGRESS: NN% · X/Y tickets · phase: <name> · last merge: <sha>`.
19
+ 2. **Agents with no report yet** — the ones from `open-spawns`. Say how long
20
+ each has been open. An agent that has been running for an hour is the most
21
+ useful thing on this screen and the easiest to overlook.
22
+ 3. Open gates, and who is waiting on whom.
23
+ 4. Any lease released by someone who did not hold it. The projection surfaces
24
+ these; they mean two agents believed they owned the same worktree.
25
+ 5. The resume steps from the last checkpoint.
26
+
27
+ If there is no journal, say exactly that and suggest `/tyran:setup`. Do not
28
+ reconstruct a status from the git log — a plausible status is worse than none,
29
+ because it will be believed.
30
+
31
+ Change nothing. This command reads.
File without changes
@@ -0,0 +1,44 @@
1
+ # Tyran configuration for this repository.
2
+ #
3
+ # Written by /tyran:setup, edited freely by you. Inferred fields carry
4
+ # provenance so you can audit where a value came from:
5
+ #
6
+ # autonomy:
7
+ # value: P1
8
+ # source: 'git log: last 50 merges are PRs, main is protected'
9
+ # confidence: 0.9
10
+ # needs_confirmation: false
11
+ #
12
+ # Validate after editing: node scripts/schema.mjs validate config .tyran/config.yaml
13
+
14
+ # Cost mode: eco | balanced | full (see docs/configuration.md)
15
+ profile: balanced
16
+
17
+ # Deployment autonomy: P1 branch-only · P2 staging · P3 merge to main.
18
+ # The gate enforces this downward; it does not stop an agent that can edit
19
+ # this file from raising it. When in doubt, setup picks P1.
20
+ autonomy: P1
21
+
22
+ # The ONLY place model names appear. Every other file — skills, agents,
23
+ # policies — is written in ROLE names, so a model deprecation is a one-line
24
+ # change here and nothing else moves.
25
+ #
26
+ # Resolve a role to a model: node scripts/tiers.mjs --role reviewer
27
+ #
28
+ # The default deliberately puts the everyday work on `work`. A strong model
29
+ # on a mechanical sweep buys nothing and spends the budget that the two calls
30
+ # below actually need.
31
+ tiers:
32
+ cheap: haiku # scout, mechanical sweeps, ledger bookkeeping
33
+ work: sonnet # DEFAULT: implementation and ordinary review
34
+ deep: opus # root-cause diagnosis, hard implementation, risky review
35
+ top: fable # security review, arbitration, final acceptance
36
+
37
+ # Repo validation commands, run before anything is called done.
38
+ validation:
39
+ - npm run lint
40
+ - npm run typecheck
41
+ - npm test
42
+
43
+ # Files multiple agents may touch: append-only, serialized by the conductor.
44
+ shared_zones: []
@@ -0,0 +1,23 @@
1
+ # What Tyran has learned about THIS repository.
2
+ #
3
+ # Written by /tyran:retro under the AUTO class (see policies/autonomy.yaml).
4
+ # Entries carry confidence and usage counters so ones that stop earning
5
+ # their keep get degraded or retired by a later retrospective.
6
+ #
7
+ # kind: fact | convention | gotcha | command | decision
8
+ #
9
+ # Validate: node scripts/schema.mjs validate knowledge .tyran/knowledge/*.yaml
10
+
11
+ entries:
12
+ - id: K-1
13
+ kind: convention
14
+ text: 'Example: commits must be authored by the repo owner identity, or CI deploys are blocked.'
15
+ confidence: 0.5
16
+ provenance:
17
+ - source: template
18
+ reference: 'delete this example entry after your first retro'
19
+ used: 0
20
+ helpful: 0
21
+ outdated_reports: 0
22
+ applies_to:
23
+ - '**'
@@ -0,0 +1,61 @@
1
+ # What Tyran's retrospective agent may change on its own.
2
+ #
3
+ # Enforced by a PreToolUse hook on write paths — the boundary does not
4
+ # depend on the model behaving. Three classes:
5
+ #
6
+ # AUTO retro commits it itself (rollback = git revert)
7
+ # GATED retro proposes, you approve
8
+ # KERNEL humans only, by hand — never autonomously
9
+ #
10
+ # Tighten this per repo freely — but `hooks/**` and `.tyran/policies/**`
11
+ # MUST stay KERNEL: the validator rejects a policy that downgrades them,
12
+ # so the boundary can never be edited away by the loop it constrains.
13
+ #
14
+ # Precedence: the most specific matching rule wins (longest path glob);
15
+ # ties go to the stricter class. Paths no rule matches get `default`.
16
+ #
17
+ # Validate: node scripts/schema.mjs validate policy .tyran/policies/autonomy.yaml
18
+
19
+ # Applied when no rule matches. GATED means "ask me" — the safe answer.
20
+ default: GATED
21
+
22
+ rules:
23
+ - path: .tyran/knowledge/**
24
+ class: AUTO
25
+ reason: learned facts about this repo; cheap to revert, high value to accumulate
26
+
27
+ - path: .claude/skills/tyran-local/**
28
+ class: AUTO
29
+ reason: repo-specific skills, gated by a passing activation test
30
+
31
+ - path: .tyran/state/**
32
+ class: AUTO
33
+ reason: the execution journal is append-only and written by the conductor itself
34
+
35
+ - path: .tyran/config.yaml
36
+ class: GATED
37
+ reason: autonomy class and model routing live here, so this file sets both what Tyran may do and what it may spend
38
+
39
+ - path: .claude/agents/**
40
+ class: GATED
41
+ reason: overriding a core agent freezes it at the version it was copied from
42
+
43
+ - path: .tyran/STOP
44
+ class: KERNEL
45
+ reason: the brake an operator uses to halt a running initiative; a loop that can clear its own stop signal has none
46
+
47
+ - path: .claude/settings.json
48
+ class: KERNEL
49
+ reason: this file registers the hooks; anything that can edit it can switch every gate off
50
+
51
+ - path: .claude/settings.local.json
52
+ class: KERNEL
53
+ reason: the local override of the hook registry, with exactly the same reach
54
+
55
+ - path: hooks/**
56
+ class: KERNEL
57
+ reason: enforcement hooks are the mechanism; a system that can disable its own gates has none
58
+
59
+ - path: .tyran/policies/**
60
+ class: KERNEL
61
+ reason: the boundary must protect itself, including this rule
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: tyran
3
+ description: Conduct a task end to end with Tyran - interview, plan, delegate to a team of fresh-context agents, verify with evidence, merge. Use for /tyran or when asked to carry something all the way through.
4
+ ---
5
+
6
+ # Tyran
7
+
8
+ Invoke the `tyran:run` skill and follow it exactly, passing through whatever
9
+ the operator said along with this command.
10
+
11
+ This file exists only so the conductor can be reached as `/tyran` instead of
12
+ `/tyran:run`. It deliberately contains no rules of its own: the playbook
13
+ lives in the plugin, so `/plugin update tyran` keeps reaching it. If you find
14
+ yourself wanting to add a rule here, add it to the plugin — or, if it is
15
+ specific to this repository, let `tyran:retro` write it into
16
+ `.tyran/knowledge/` where it belongs.