@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.
- package/.claude-plugin/marketplace.json +22 -0
- package/.claude-plugin/plugin.json +22 -0
- package/CHANGELOG.md +245 -0
- package/LICENSE +201 -0
- package/README.md +468 -0
- package/agents/.gitkeep +0 -0
- package/agents/implementer.md +60 -0
- package/agents/retro.md +88 -0
- package/agents/reviewer.md +55 -0
- package/agents/scout.md +60 -0
- package/bin/tyran.mjs +172 -0
- package/hooks/HOOK-CONTRACT-MEASURED.md +377 -0
- package/hooks/hooks.json +83 -0
- package/hooks/scripts/.gitkeep +0 -0
- package/hooks/scripts/evidence-gate.mjs +705 -0
- package/hooks/scripts/hook-io.mjs +813 -0
- package/hooks/scripts/policy-gate.mjs +1402 -0
- package/hooks/scripts/pre-compact.mjs +211 -0
- package/hooks/scripts/retro-gate.mjs +191 -0
- package/hooks/scripts/secrets-gate.mjs +1683 -0
- package/hooks/scripts/session-start.mjs +358 -0
- package/hooks/scripts/write-guard.mjs +475 -0
- package/package.json +52 -0
- package/scripts/desc-budget.mjs +139 -0
- package/scripts/doctor.mjs +1267 -0
- package/scripts/hooks-check.mjs +1312 -0
- package/scripts/invisible.mjs +346 -0
- package/scripts/journal.mjs +747 -0
- package/scripts/project.mjs +981 -0
- package/scripts/scan-control-chars.mjs +547 -0
- package/scripts/scan-repo.mjs +287 -0
- package/scripts/schema.mjs +467 -0
- package/scripts/stop-check.mjs +89 -0
- package/scripts/tiers.mjs +324 -0
- package/scripts/yaml-lite.mjs +383 -0
- package/skills/browser-check/SKILL.md +118 -0
- package/skills/code-review/SKILL.md +83 -0
- package/skills/deslop/SKILL.md +97 -0
- package/skills/doctor/SKILL.md +35 -0
- package/skills/fidelity-gate/SKILL.md +132 -0
- package/skills/hello/SKILL.md +16 -0
- package/skills/pr-feedback/SKILL.md +85 -0
- package/skills/prompt-tuning/SKILL.md +102 -0
- package/skills/retro/SKILL.md +69 -0
- package/skills/root-cause/SKILL.md +89 -0
- package/skills/run/SKILL.md +285 -0
- package/skills/setup/SKILL.md +79 -0
- package/skills/skill-writing/SKILL.md +99 -0
- package/skills/status/SKILL.md +31 -0
- package/templates/.gitkeep +0 -0
- package/templates/config.yaml +44 -0
- package/templates/knowledge.yaml +23 -0
- package/templates/policies/autonomy.yaml +61 -0
- 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.
|