@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,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Check that Tyran itself is healthy in this repo - gates that cannot fire, journal and projection drift, orphaned leases, dead policy rules, config that fails its schema. Reports findings with the fix for each. Use for /tyran:doctor or when a gate seems not to be working.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Doctor
|
|
6
|
+
|
|
7
|
+
Three checks, in this order. Run all three even if the first is clean — they
|
|
8
|
+
fail independently.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
node "${CLAUDE_PLUGIN_ROOT}/scripts/doctor.mjs" --hooks
|
|
12
|
+
node "${CLAUDE_PLUGIN_ROOT}/scripts/doctor.mjs" --state
|
|
13
|
+
node "${CLAUDE_PLUGIN_ROOT}/scripts/schema.mjs" validate config .tyran/config.yaml
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**`--hooks` is the one that matters most**, and it is worth saying why. Hooks
|
|
17
|
+
fail OPEN: a gate whose file is missing, whose execute bit was lost, or whose
|
|
18
|
+
matcher can never match does not degrade into a weaker check — the action it
|
|
19
|
+
was meant to stop simply proceeds, with nothing printed anywhere. A dead gate
|
|
20
|
+
and a healthy gate look identical from inside a session. This check is the
|
|
21
|
+
only thing that can tell them apart.
|
|
22
|
+
|
|
23
|
+
**`--state` compares the journal against its projections** and finds drift,
|
|
24
|
+
leases held by agents that have long since reported, and policy rules that
|
|
25
|
+
match no path in the repo.
|
|
26
|
+
|
|
27
|
+
## Reporting
|
|
28
|
+
|
|
29
|
+
Paste the raw output. For each finding give the fix the tool named, and say
|
|
30
|
+
plainly which findings are errors and which are informational — a report that
|
|
31
|
+
blurs the two trains the operator to skim the next one.
|
|
32
|
+
|
|
33
|
+
If everything is clean, say so in one line with the counts, and resist adding
|
|
34
|
+
advice. A clean doctor run that arrives with a list of suggestions reads as a
|
|
35
|
+
failed one.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Build a UI against a frozen visual reference without drift. An inventory extracted from the reference before any code, a relics list for what exists but should not, and a gate that MEASURES rather than judges - computed styles on a fixture carrying the reference's own data. Use when a mockup, design spec or screenshot is the contract.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Fidelity gate — building against a frozen visual reference
|
|
6
|
+
|
|
7
|
+
> Drift that goes uncaught on the first screen multiplies onto every screen
|
|
8
|
+
> after it. Measured on one initiative that skipped this: four waves of
|
|
9
|
+
> rework plus a reconciliation audit, because "looks right" had been accepted
|
|
10
|
+
> as a verdict fourteen times.
|
|
11
|
+
|
|
12
|
+
## The division of labour, which is the whole idea
|
|
13
|
+
|
|
14
|
+
**Appearance is read by a MACHINE. Intent is described in WORDS.**
|
|
15
|
+
|
|
16
|
+
Text, typography, colour, geometry and icons are extracted from the
|
|
17
|
+
reference *mechanically*. Never let a model retype them into prose: every
|
|
18
|
+
restatement is a **lossy copy**, and the source is more precise than any
|
|
19
|
+
description of it — `22px/700/#0a2540` has exactly one interpretation, and
|
|
20
|
+
"large bold dark-blue heading" has hundreds.
|
|
21
|
+
|
|
22
|
+
Words describe only what a static reference cannot contain: which content is
|
|
23
|
+
an example and which is binding, where the data comes from, visibility
|
|
24
|
+
conditions, the empty state, and the states that do not render (hover, focus,
|
|
25
|
+
error).
|
|
26
|
+
|
|
27
|
+
## The overriding rule
|
|
28
|
+
|
|
29
|
+
**The reference is the only source of visual truth.** Handoffs, tickets and
|
|
30
|
+
prose describe BEHAVIOUR; appearance is settled by the reference alone. When
|
|
31
|
+
prose disagrees with the reference about how something looks, **the reference
|
|
32
|
+
wins**, you decide without asking, and you record the divergence.
|
|
33
|
+
|
|
34
|
+
- An element **not** in the reference **does not exist**. Relics of older
|
|
35
|
+
code are not carried over without an owner's decision.
|
|
36
|
+
- An element **in** the reference **must be built** — if necessary as an
|
|
37
|
+
honest-empty version in the reference's own geometry.
|
|
38
|
+
|
|
39
|
+
## Step 0 — the reference lives in the repo, verified
|
|
40
|
+
|
|
41
|
+
Pull it into the repo and check it is whole before trusting it: size, the
|
|
42
|
+
file actually ends where it should, and it renders. Work only from the
|
|
43
|
+
in-repo copy. An incomplete reference is a STOP and a report, not something
|
|
44
|
+
to work around — half a contract silently becomes "use your judgement".
|
|
45
|
+
|
|
46
|
+
## Step 1 — the inventory, before the first line of code
|
|
47
|
+
|
|
48
|
+
Extract a machine-readable checklist from the reference. One row per element:
|
|
49
|
+
|
|
50
|
+
| # | Element | Literal text (with capitalisation) | Typography | Colours | Geometry | Icon | States and conditions |
|
|
51
|
+
|
|
52
|
+
Hard requirements, each of which has been violated at real cost:
|
|
53
|
+
|
|
54
|
+
- **Literal text**, including format, capitalisation and separators. A 1px
|
|
55
|
+
rule between two phrases is an element and gets a row.
|
|
56
|
+
- **Icons are carried over VERBATIM** — the reference's own markup or asset.
|
|
57
|
+
Substituting an icon library because a glyph "looks the same" is
|
|
58
|
+
forbidden. A similar icon is not that icon.
|
|
59
|
+
- **Every surface with a specific colour, and every line with its extent** —
|
|
60
|
+
where it starts and where it stops.
|
|
61
|
+
- **Conditional elements carry the condition** in the row.
|
|
62
|
+
|
|
63
|
+
If the repo has a comparator, it GENERATES the inventory and you only add the
|
|
64
|
+
states column. Write it by hand only where no tool exists yet.
|
|
65
|
+
|
|
66
|
+
The conductor spot-checks five rows against the rendered reference before the
|
|
67
|
+
work starts. A wrong inventory produces a confidently wrong screen.
|
|
68
|
+
|
|
69
|
+
## Step 2 — the diff, when the view already exists
|
|
70
|
+
|
|
71
|
+
Before writing code, every inventory row gets **MATCHES / DRIFT / MISSING**,
|
|
72
|
+
and every element present in the code but absent from the reference goes on a
|
|
73
|
+
**RELICS** list with a disposition: remove (the default) or an owner gate when
|
|
74
|
+
it is load-bearing.
|
|
75
|
+
|
|
76
|
+
"Apply the differences" without a list of the differences is forbidden. That
|
|
77
|
+
list *is* the plan for the work.
|
|
78
|
+
|
|
79
|
+
## Step 3 — implement the inventory, and only the inventory
|
|
80
|
+
|
|
81
|
+
If the reference uses a token, the code uses **that** token. If the reference
|
|
82
|
+
defines a token and never uses it, the code does not use it either. A
|
|
83
|
+
deviation from the reference is only ever a recorded owner decision, never an
|
|
84
|
+
implementer's taste.
|
|
85
|
+
|
|
86
|
+
## Step 4 — the gate is a MEASUREMENT, not an opinion
|
|
87
|
+
|
|
88
|
+
1. **A fixture carrying the reference's own data.** Same entity, same period,
|
|
89
|
+
same numbers. Then every difference in a screenshot is a difference of
|
|
90
|
+
appearance, not of content — which is the entire reason this step exists.
|
|
91
|
+
2. **Side-by-side captures** at the reference's own widths.
|
|
92
|
+
3. **Computed styles dumped to JSON** for the inventory's selectors and
|
|
93
|
+
compared against the inventory's values. A disagreement about whether
|
|
94
|
+
something is 9px or 10.5px is settled by the dump, never by looking.
|
|
95
|
+
`browser-check` carries how — the capture, the dump, the deterministic
|
|
96
|
+
waits, and the rule that a zero-size box is a failure rather than a pass.
|
|
97
|
+
This gate owns the inventory and the verdict; it does not own the browser.
|
|
98
|
+
4. **The verdict is the filled-in checklist**, row by row, attached to the
|
|
99
|
+
report. A narrative verdict — *"looks consistent"*, *"differences are
|
|
100
|
+
data-only"* — is REJECTED without it. This is the single rule that decides
|
|
101
|
+
whether the gate stays a gate.
|
|
102
|
+
5. Failures are fixed in the same piece of work. It does not merge with
|
|
103
|
+
failures unless the owner says so.
|
|
104
|
+
|
|
105
|
+
Three things that turn this gate back into an opinion, all observed:
|
|
106
|
+
|
|
107
|
+
- **A deliberate skip is not a match.** Every deviation carries a reason and
|
|
108
|
+
lands in an explicit **debt** section of the report.
|
|
109
|
+
- **Raising a tolerance until the run goes green** is forbidden. That is
|
|
110
|
+
changing the measurement to fit the answer.
|
|
111
|
+
- **A structural selector without a text assertion** silently measures the
|
|
112
|
+
wrong element when the markup is renumbered. Anchor by an explicit
|
|
113
|
+
attribute where you can, and always assert the text — a renumbering must
|
|
114
|
+
produce a loud MISSING, never a quiet wrong reading.
|
|
115
|
+
|
|
116
|
+
Warm the routes up before a batch run. A cold compile produces failures that
|
|
117
|
+
have nothing to do with fidelity, and chasing them costs a round.
|
|
118
|
+
|
|
119
|
+
## Step 5 — when the data cannot fill the design
|
|
120
|
+
|
|
121
|
+
- The element **stays**, honest-empty, in the reference's geometry and style.
|
|
122
|
+
Hiding a whole section because data is missing needs an **owner decision** —
|
|
123
|
+
a hidden section is indistinguishable from drift.
|
|
124
|
+
- Missing data is a backend item raised in the report. "Pretty" versus raw
|
|
125
|
+
values is also a data question; the front end must not hardcode a mask over
|
|
126
|
+
it without a decision.
|
|
127
|
+
|
|
128
|
+
## Step 6 — owner acceptance
|
|
129
|
+
|
|
130
|
+
At the phase gate the owner sees paired captures of full views. The checklist
|
|
131
|
+
catches what is measurable; the owner catches the rest. Neither replaces the
|
|
132
|
+
other, and offering only one of them is how a gate becomes a formality.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Smoke-test skill that verifies the Tyran plugin is installed and namespaced correctly. Invoke with /tyran:hello.
|
|
3
|
+
disable-model-invocation: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hello (installation smoke test)
|
|
7
|
+
|
|
8
|
+
Reply with exactly one short paragraph:
|
|
9
|
+
|
|
10
|
+
1. Confirm the Tyran plugin is loaded and state its version by reading
|
|
11
|
+
`${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json`.
|
|
12
|
+
2. State the resolved value of `${CLAUDE_PLUGIN_ROOT}` so the user can see
|
|
13
|
+
where the plugin is installed from.
|
|
14
|
+
|
|
15
|
+
Do not perform any other action. This skill exists only to verify
|
|
16
|
+
installation, namespacing, and path resolution.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Work a reviewer's comments on a pull request to the end. Enumerate all three comment surfaces before triaging any, give every comment a disposition - fixed, declined with a reason, or ticketed - push before you reply, and resolve only what you addressed. Use when a PR comes back with review feedback or a red check.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# PR feedback — closing the loop with a human reviewer
|
|
6
|
+
|
|
7
|
+
> The safest autonomy class, and the default, ends with a change on a branch
|
|
8
|
+
> and a person merging it. So the ordinary last step of this plugin's work is a
|
|
9
|
+
> pull request somebody reviews — and it was the one step with no protocol.
|
|
10
|
+
> `tyran:reviewer` governs our own internal review; this governs theirs.
|
|
11
|
+
|
|
12
|
+
## The three surfaces, and why one of them is a trap
|
|
13
|
+
|
|
14
|
+
GitHub keeps pull-request feedback in three separate resources:
|
|
15
|
+
|
|
16
|
+
| Surface | Endpoint | What lives there |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| Conversation | `/issues/{n}/comments` | Plain comments on the PR |
|
|
19
|
+
| Inline review comments | `/pulls/{n}/comments` | Anchored to a line of the diff |
|
|
20
|
+
| Reviews | `/pulls/{n}/reviews` | The submitted verdict **and its body text** |
|
|
21
|
+
|
|
22
|
+
**A review's body is not in the inline-comments collection.** Reviewers write
|
|
23
|
+
their summary there, and bots put whole findings there — anything that could not
|
|
24
|
+
be anchored to a changed line, which is exactly the "outside diff range" class.
|
|
25
|
+
|
|
26
|
+
Measured, against a public repository: `cli/cli` PR **#13944** has one review
|
|
27
|
+
carrying a written body and **zero** inline comments. An agent that reads only
|
|
28
|
+
`/pulls/{n}/comments` sees nothing on that PR and reports that there was nothing
|
|
29
|
+
to address. The report is true about what it looked at and false about what it
|
|
30
|
+
claims, which is the failure shape this whole plugin exists to refuse.
|
|
31
|
+
|
|
32
|
+
So: **fetch all three, paginated, before triaging any of them.** Print the
|
|
33
|
+
counts. `3 inline · 2 review bodies · 1 conversation` is the first line of the
|
|
34
|
+
work, and it is what makes a missed surface visible.
|
|
35
|
+
|
|
36
|
+
## Every comment gets a disposition
|
|
37
|
+
|
|
38
|
+
No comment is silently dropped. Each one ends as exactly one of:
|
|
39
|
+
|
|
40
|
+
- **Fixed** — with the commit that did it.
|
|
41
|
+
- **Declined** — with the reason, in one sentence. Disagreeing is allowed;
|
|
42
|
+
disagreeing silently is not. If it is a product or scope decision rather than
|
|
43
|
+
a technical one, it goes to the conductor instead of being decided here.
|
|
44
|
+
- **Ticketed** — real, out of this PR's scope, captured where it will be found
|
|
45
|
+
again. A promise in a thread is not a ticket.
|
|
46
|
+
|
|
47
|
+
Nitpicks are answered too, briefly. An unanswered comment reads as unread, and
|
|
48
|
+
the reviewer's next move is to check whether you read the others.
|
|
49
|
+
|
|
50
|
+
**A comment that names a defect gets pinned as a test**, not just patched. The
|
|
51
|
+
same rule the reviewer applies internally: a finding that cannot be verified as
|
|
52
|
+
fixed will be found again by someone else, later, at more cost.
|
|
53
|
+
|
|
54
|
+
## Order of operations
|
|
55
|
+
|
|
56
|
+
1. **Fix, then push, then reply.** "Fixed in `abc1234`" posted before the push
|
|
57
|
+
is a claim about a commit the reviewer cannot fetch. Push first; quote the
|
|
58
|
+
real sha.
|
|
59
|
+
2. **Resolve only threads you actually addressed.** Resolving a thread you
|
|
60
|
+
declined hides the disagreement — say why, and leave it for them to close.
|
|
61
|
+
Never resolve someone else's open question to tidy the view.
|
|
62
|
+
3. **A red check is feedback.** Read the failing job's own output, not the
|
|
63
|
+
summary. And gate on the runner's exit code: a pipeline that pipes a test
|
|
64
|
+
run into `grep` and pushes on success pushes on a red suite too, because
|
|
65
|
+
`grep` was satisfied.
|
|
66
|
+
4. **Re-check the three surfaces after you push.** Reviews arrive while you
|
|
67
|
+
work, and CI posts after it finishes. A loop that reads once at the start
|
|
68
|
+
ends by declaring victory over a snapshot.
|
|
69
|
+
|
|
70
|
+
## When to stop and ask
|
|
71
|
+
|
|
72
|
+
- The comment asks for a change that crosses a boundary the story did not own —
|
|
73
|
+
an API shape, a schema, someone else's module.
|
|
74
|
+
- Two reviewers ask for opposite things. Do not pick; put both in front of the
|
|
75
|
+
conductor with a recommendation.
|
|
76
|
+
- The review asks for a rewrite large enough to be its own story. Say so with a
|
|
77
|
+
size, rather than quietly starting it inside a feedback round.
|
|
78
|
+
|
|
79
|
+
## The report
|
|
80
|
+
|
|
81
|
+
Counts per surface, the disposition of every comment with its thread, the shas
|
|
82
|
+
that carry the fixes, the checks that are now green with their raw output, and
|
|
83
|
+
anything still open with the reason. If you declined something, that line is the
|
|
84
|
+
most important one in the report — it is the only part the reviewer cannot see
|
|
85
|
+
by looking at the diff.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Iterate on a prompt, or on anything whose quality is measured by non-deterministic model output, without chasing noise. A noise baseline before the first edit, medians over repeated runs, enforcement AFTER generation rather than in the wording, and detectors that surface candidates rather than defects.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Prompt tuning — working with non-deterministic output
|
|
6
|
+
|
|
7
|
+
> Every rule here has a measured cost behind it. The first one alone accounts
|
|
8
|
+
> for three tuning rounds spent moving a number that had never moved.
|
|
9
|
+
|
|
10
|
+
## Measure before you change anything
|
|
11
|
+
|
|
12
|
+
**1. Take a noise baseline BEFORE the first edit.** Same prompt, same inputs,
|
|
13
|
+
at least two runs; record the spread of every metric you care about. A delta
|
|
14
|
+
smaller than the spread is noise, not the effect of your change. To compare
|
|
15
|
+
two versions, run each at least three times per input and compare **medians**.
|
|
16
|
+
|
|
17
|
+
Measured: ±20% output length and a jumping paragraph count **with no change
|
|
18
|
+
to the prompt at all**. Three rounds of tuning were spent chasing that before
|
|
19
|
+
anyone ran the same prompt twice.
|
|
20
|
+
|
|
21
|
+
**2. Measure conversion factors between representations; never assume them.**
|
|
22
|
+
One initiative assumed a 1.15× expansion between two languages and measured
|
|
23
|
+
1.3–1.4×. The assumption would have invalidated the entire budget built on
|
|
24
|
+
it. When a factor's spread is wider than your target band, no source-side
|
|
25
|
+
budget can guarantee the target — catch the tail with a gate **after** the
|
|
26
|
+
transformation instead of tightening the budget before it.
|
|
27
|
+
|
|
28
|
+
**3. After three failed rewordings of the same defect on the same case, name
|
|
29
|
+
it a KNOWN LIMITATION** and hand it to a human. A fourth blind iteration is
|
|
30
|
+
chasing noise with extra steps.
|
|
31
|
+
|
|
32
|
+
## Writing the prompt
|
|
33
|
+
|
|
34
|
+
**4. Every numeric example becomes a quota; every template phrase becomes a
|
|
35
|
+
verbatim anchor.** Describe the CRITERION, not the illustration. "Two threads
|
|
36
|
+
means two paragraphs" produced two-paragraph output in six samples out of
|
|
37
|
+
six, where an example of a two-paragraph answer had not. State criteria in
|
|
38
|
+
**both directions** — a one-sided formulation works only in the direction you
|
|
39
|
+
named.
|
|
40
|
+
|
|
41
|
+
**5. A rule in a prompt is a request. Enforcement is a mechanism that runs
|
|
42
|
+
AFTER generation** — a gate plus regeneration with a targeted nudge.
|
|
43
|
+
Confirmed on four separate properties: length ceiling, presence of figures,
|
|
44
|
+
language of a recommendation, and post-translation condensation.
|
|
45
|
+
|
|
46
|
+
Put a safety catch on the source side: when the source genuinely lacks the
|
|
47
|
+
property you are demanding, do not demand it. A gate that requires figures
|
|
48
|
+
from a source containing none is an instruction to fabricate.
|
|
49
|
+
|
|
50
|
+
**6. Volume minimums are SOFT (log them), ceilings are hard.** Regenerating
|
|
51
|
+
because output was "too short" produces padding, reliably.
|
|
52
|
+
|
|
53
|
+
**7. The target quoted to the model sits below the threshold the gate
|
|
54
|
+
enforces.** A sample two characters over the ceiling cost two paid
|
|
55
|
+
regenerations. Both numbers come from ONE constants module — every hand-copy
|
|
56
|
+
of a constant into a script, a prompt, a test or a message to the model is a
|
|
57
|
+
future lie, and it will be discovered by the number that did not get updated.
|
|
58
|
+
|
|
59
|
+
## Building the gate
|
|
60
|
+
|
|
61
|
+
**8. On fail-open, return the BEST candidate — not the last one, and not the
|
|
62
|
+
current one.** Rank by *weighted* severity: regulatory beats content beats
|
|
63
|
+
length, ties broken by length. Counting violations without weights is a fake
|
|
64
|
+
ranking, and it has a predictable failure: text with no figures is shorter,
|
|
65
|
+
so it wins. The accepted sample must be exactly what reaches the payload
|
|
66
|
+
**and** the cache; watch for "last one wins" when steps are written, or you
|
|
67
|
+
poison the cache with a candidate you rejected.
|
|
68
|
+
|
|
69
|
+
**9. Measure the gate's own cost before wiring it in.** A regex reading a
|
|
70
|
+
whole source was a hot path at 835 ms; fixing its quantifiers took it to
|
|
71
|
+
0.2 ms. Add a performance test with a threshold, or the next one will not be
|
|
72
|
+
noticed either.
|
|
73
|
+
|
|
74
|
+
**10. A prompt in a database plus code with placeholders forces a deployment
|
|
75
|
+
ORDER**: the code that supplies the variables ships first, the prompt second.
|
|
76
|
+
Add a version guard so the gate is inert until the prompt reaches the version
|
|
77
|
+
that feeds it, and log any placeholder the build did not supply.
|
|
78
|
+
|
|
79
|
+
## Judging output, and detectors
|
|
80
|
+
|
|
81
|
+
**11. A detector finds CANDIDATES, not defects.** Especially across languages
|
|
82
|
+
or formats. Confront every hit with the source before reporting it, or you
|
|
83
|
+
will report your own regex's shortcomings as the product's. Three false
|
|
84
|
+
alarms were avoided exactly this way. Choose the direction of the check with
|
|
85
|
+
the lower false-positive background: for translations, look for *invented*
|
|
86
|
+
content rather than *lost* content.
|
|
87
|
+
|
|
88
|
+
**12. Judge against the SOURCE, not against world knowledge.** "Correcting" a
|
|
89
|
+
fact to match what you know is a grounding violation, not a fix. One
|
|
90
|
+
fabrication charge collapsed when the source turned out to use the disputed
|
|
91
|
+
name 63 times.
|
|
92
|
+
|
|
93
|
+
**13. Audit samples with the strongest tier available.** A cheap tier
|
|
94
|
+
produced false negatives and demanded content the prompt explicitly forbade.
|
|
95
|
+
And remember the audit is itself non-deterministic: a borderline rejection is
|
|
96
|
+
a signal for a HUMAN auditor, not a trigger for another prompt iteration.
|
|
97
|
+
|
|
98
|
+
**14. Sweep for residue by CLASS, not by known spellings.** Search for the
|
|
99
|
+
value — the old ceiling `35` — not for the wording of a label. Check also
|
|
100
|
+
whether a test is PINNING an incorrect label into place. Pin a reviewer's
|
|
101
|
+
counterexamples as MUST-PASS tests: one such test caught a fix that was only
|
|
102
|
+
half done, before it came back around.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Close an initiative by learning from it. Spawns the retrospective agent over the ledger, the notes and the agents reports, records what it changed and what it rejected, and writes durable facts about this repo into .tyran/knowledge/. Runs automatically at the end of an initiative; also available as /tyran:retro.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Retro
|
|
6
|
+
|
|
7
|
+
The only loop through which Tyran gets better at *this* repo instead of
|
|
8
|
+
repeating the same mistake every initiative.
|
|
9
|
+
|
|
10
|
+
**You normally do not have to invoke this.** The `Stop` gate refuses one turn
|
|
11
|
+
when an initiative has all its tickets merged and no retrospective recorded
|
|
12
|
+
since the last merge. This skill is what you run when it does — or when you
|
|
13
|
+
want one early.
|
|
14
|
+
|
|
15
|
+
## 1. Spawn the retrospector
|
|
16
|
+
|
|
17
|
+
Spawn `tyran:retro` at the tier `node "${CLAUDE_PLUGIN_ROOT}/scripts/tiers.mjs"
|
|
18
|
+
--role retro` resolves, over the initiative's `PLAN.md`, `NOTES.md`, the
|
|
19
|
+
agents' reports, and the initiative's git log.
|
|
20
|
+
|
|
21
|
+
Do not do this work yourself in the conducting session. The retrospector's
|
|
22
|
+
value comes from reading the record cold; a conductor reviewing its own
|
|
23
|
+
initiative rates its own decisions, and rates them well.
|
|
24
|
+
|
|
25
|
+
## 2. Record the outcome — including "nothing"
|
|
26
|
+
|
|
27
|
+
Every retro ends with a journal entry, whatever it concluded:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
node "${CLAUDE_PLUGIN_ROOT}/scripts/journal.mjs" append "$J" retro.entry "$INIT" \
|
|
31
|
+
--actor retro --data '{"kind":"skill","target":"skills/run/SKILL.md","confidence":"medium"}'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`kind` is `skill`, `agent`, `script`, `doc`, `knowledge` — or **`skipped`**
|
|
35
|
+
with the reason, when the judgement is that this initiative has nothing worth
|
|
36
|
+
changing. That is a correct outcome and it settles the gate exactly like any
|
|
37
|
+
other. A retro that always finds something is not learning, it is padding.
|
|
38
|
+
|
|
39
|
+
**When `kind` is `skill`, follow `skill-writing`.** New skills are AUTO class —
|
|
40
|
+
you may commit one without asking — and that is only safe against a standard.
|
|
41
|
+
It carries the admission test (a skill nothing already points at is a library
|
|
42
|
+
entry), the description budget you are spending on every future session, and
|
|
43
|
+
the activation test that proves the thing fires at all. A skill that never
|
|
44
|
+
triggers costs its description on every turn and returns nothing.
|
|
45
|
+
|
|
46
|
+
## 3. Write down what is true about THIS repo
|
|
47
|
+
|
|
48
|
+
Durable facts go to `.tyran/knowledge/<topic>.yaml`, which is AUTO class —
|
|
49
|
+
the retrospector may write it without asking:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
node "${CLAUDE_PLUGIN_ROOT}/scripts/schema.mjs" validate knowledge .tyran/knowledge/<topic>.yaml
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
An entry is a fact, convention, gotcha, command or decision, with a
|
|
56
|
+
confidence, its provenance, and the paths it applies to. The counters
|
|
57
|
+
(`used`, `helpful`, `outdated_reports`) exist so a later retrospective can
|
|
58
|
+
retire an entry that stopped earning its keep — knowledge that only ever
|
|
59
|
+
grows is a context tax with a good story attached.
|
|
60
|
+
|
|
61
|
+
Write what a competent newcomer would get wrong, not what the code already
|
|
62
|
+
says. "The test suite takes 9 minutes, so do not run it per file" is worth an
|
|
63
|
+
entry. "This is a Next.js app" is not: the next agent can see that.
|
|
64
|
+
|
|
65
|
+
## 4. Report
|
|
66
|
+
|
|
67
|
+
Five lines: candidates considered, implemented, rejected and why, what was
|
|
68
|
+
deleted or merged, what is left for next time. Rejections are as valuable as
|
|
69
|
+
changes — they stop the next retrospective relitigating the same idea.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Find the mechanism behind a failure instead of patching its symptom. Reproduce first, change one variable per experiment with the prediction written before the run, bisect rather than re-read, and exit by naming the mechanism and pinning it with a failing test. Use for a bug, an unexplained red test, or a failure that will not reproduce.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Root cause — working a failure down to its mechanism
|
|
6
|
+
|
|
7
|
+
> This is the situation the conductor is told to spend its most expensive
|
|
8
|
+
> reasoning on: a diagnosis, a failure nobody can reproduce, two agents who
|
|
9
|
+
> disagree. Spending more thinking on an undisciplined search just produces a
|
|
10
|
+
> more confident wrong answer, so here is the discipline.
|
|
11
|
+
|
|
12
|
+
## Reproduce first. Everything else is downstream of this
|
|
13
|
+
|
|
14
|
+
**A fix for a bug you cannot reproduce is a guess with a diff attached.** You
|
|
15
|
+
cannot tell whether it worked, and neither can the reviewer — the bug's absence
|
|
16
|
+
after the change is indistinguishable from the bug's absence before it.
|
|
17
|
+
|
|
18
|
+
Get to the smallest reliable reproduction you can, and write down the exact
|
|
19
|
+
command, input and environment. If it reproduces only sometimes, capture the
|
|
20
|
+
rate — "3 of 20 runs" is a fact you can measure against later, "it is flaky" is
|
|
21
|
+
not. If it will not reproduce at all, that is now the task: what does the
|
|
22
|
+
failing environment have that yours does not — version, data, timezone,
|
|
23
|
+
concurrency, permissions, a warm cache?
|
|
24
|
+
|
|
25
|
+
## Read the whole error
|
|
26
|
+
|
|
27
|
+
The first line names where it surfaced, not where it went wrong. Read the full
|
|
28
|
+
stack, the frames from your own code in particular, and everything logged in the
|
|
29
|
+
seconds before. The answer is stated outright more often than anyone expects,
|
|
30
|
+
which is why "I read the error" and "I read the first line of the error" have to
|
|
31
|
+
be different sentences.
|
|
32
|
+
|
|
33
|
+
## One variable, and write the prediction first
|
|
34
|
+
|
|
35
|
+
Change ONE thing per experiment, and **write down what you expect to happen
|
|
36
|
+
before you run it.** An experiment whose outcome you did not predict teaches
|
|
37
|
+
almost nothing: whatever comes back, it confirms something you already believed.
|
|
38
|
+
A prediction that turns out wrong is the single most informative event available
|
|
39
|
+
to you, and you only get it by committing first.
|
|
40
|
+
|
|
41
|
+
Two changes at once and you have learned nothing about either.
|
|
42
|
+
|
|
43
|
+
## Halve the surface
|
|
44
|
+
|
|
45
|
+
Do not re-read the code hoping to spot it. **Bisect.**
|
|
46
|
+
|
|
47
|
+
- Over time: `git bisect` against a command that exits non-zero on the failure.
|
|
48
|
+
A scriptable check turns an afternoon into a few minutes.
|
|
49
|
+
- Over the input: cut it in half, keep the half that still fails, repeat.
|
|
50
|
+
- Over the system: disable, stub or bypass half the pipeline. Where does the
|
|
51
|
+
value stop being correct? Instrument at the boundary between two components
|
|
52
|
+
before you go inside either.
|
|
53
|
+
|
|
54
|
+
## It is your code before it is the library
|
|
55
|
+
|
|
56
|
+
The base rate favours the code changed most recently by the fewest people —
|
|
57
|
+
yours. Suspect the dependency only after the evidence points there, and then
|
|
58
|
+
**read the installed version's source**, not your memory of the API and not the
|
|
59
|
+
documentation for a version you might not have. `node_modules` is on disk; the
|
|
60
|
+
answer is a `grep` away, and a remembered signature has already sent people
|
|
61
|
+
down a day of the wrong road.
|
|
62
|
+
|
|
63
|
+
## When three hypotheses have died
|
|
64
|
+
|
|
65
|
+
The wrong assumption is one you have not written down. Stop testing and list
|
|
66
|
+
what you believe is true about the system — which file is loaded, which branch
|
|
67
|
+
is running, which build is deployed, which database you are pointed at, that the
|
|
68
|
+
change you made is even in the process you are running. Then test the cheapest
|
|
69
|
+
item on that list.
|
|
70
|
+
|
|
71
|
+
Almost every long debugging session ends here: something everyone was certain
|
|
72
|
+
of was not true. `prompt-tuning` has the sibling rule for non-deterministic
|
|
73
|
+
work — after three failed attempts at the same defect, name it a known
|
|
74
|
+
limitation and hand it to a person rather than taking a fourth blind swing.
|
|
75
|
+
|
|
76
|
+
## Exiting
|
|
77
|
+
|
|
78
|
+
1. **Name the MECHANISM, not the symptom.** "The cache key omits the locale, so
|
|
79
|
+
the second request serves the first request's body" is a root cause. "The
|
|
80
|
+
page showed the wrong language" is the symptom you started with.
|
|
81
|
+
2. **Pin it with a failing test before the fix.** Written after the fix, a test
|
|
82
|
+
only proves the code's current behaviour; written before, it proves the bug
|
|
83
|
+
existed and is gone. This is also what the reviewer will ask for.
|
|
84
|
+
3. **Check for siblings.** The same mechanism usually has other victims —
|
|
85
|
+
another cache key, another unhandled path. Find them now, while you
|
|
86
|
+
understand it.
|
|
87
|
+
4. **Report the mechanism, the evidence, the fix and the blast radius**, plus
|
|
88
|
+
the hypotheses you killed. Those save the next person from re-running your
|
|
89
|
+
dead ends, and they are the part everyone omits.
|