ralphctl 0.26.0 → 0.28.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/README.md +11 -4
- package/THIRD-PARTY-NOTICES.md +65 -2
- package/dist/agent-definitions/ralphctl-generator.md +3 -2
- package/dist/{cli-P7D6G5NI.mjs → chunk-WAHQPVTG.mjs} +16782 -40661
- package/dist/cli-W3M7L4TP.mjs +2772 -0
- package/dist/cli.mjs +1 -1
- package/dist/launch-VBRTQP4L.mjs +20602 -0
- package/dist/manifest.json +16 -3
- package/dist/prompts/_partials/autonomous-operation.md +18 -7
- package/dist/prompts/_partials/conventions-agents-md.md +2 -2
- package/dist/prompts/_partials/conventions-claude-md.md +2 -0
- package/dist/prompts/_partials/decisions.md +0 -1
- package/dist/prompts/_partials/evaluator-failure-modes.md +8 -5
- package/dist/prompts/_partials/evaluator-grading-rules.md +9 -5
- package/dist/prompts/_partials/one-shot-operation.md +6 -0
- package/dist/prompts/apply-feedback/template.md +5 -4
- package/dist/prompts/create-pr/template.md +10 -8
- package/dist/prompts/detect-scripts/template.md +7 -4
- package/dist/prompts/detect-skills/template.md +2 -0
- package/dist/prompts/evaluate/template.md +4 -2
- package/dist/prompts/evaluate-continuation/template.md +1 -1
- package/dist/prompts/ideate/template.md +2 -3
- package/dist/prompts/implement/template.md +21 -14
- package/dist/prompts/plan/template.md +3 -4
- package/dist/prompts/readiness/template.md +9 -4
- package/dist/prompts/refine/template.md +3 -6
- package/dist/prompts/reproduce/template.md +7 -0
- package/dist/skills/ralphctl-api-and-interface-design/SKILL.md +117 -0
- package/dist/skills/ralphctl-code-review-and-quality/SKILL.md +119 -8
- package/dist/skills/ralphctl-code-simplification/SKILL.md +100 -0
- package/dist/skills/ralphctl-codebase-design/SKILL.md +82 -0
- package/dist/skills/ralphctl-debugging-and-error-recovery/SKILL.md +23 -5
- package/dist/skills/ralphctl-deprecation-and-migration/SKILL.md +106 -0
- package/dist/skills/ralphctl-frontend-ui-engineering/SKILL.md +94 -0
- package/dist/skills/ralphctl-humanizer/SKILL.md +137 -0
- package/dist/skills/ralphctl-idea-refinement/SKILL.md +2 -0
- package/dist/skills/ralphctl-iterative-review/SKILL.md +10 -4
- package/dist/skills/ralphctl-observability-and-instrumentation/SKILL.md +104 -0
- package/dist/skills/ralphctl-performance-optimization/SKILL.md +123 -0
- package/dist/skills/ralphctl-ponytail/SKILL.md +38 -28
- package/dist/skills/ralphctl-security-and-hardening/SKILL.md +259 -0
- package/dist/skills/ralphctl-source-driven-development/SKILL.md +103 -0
- package/dist/skills/ralphctl-spec-driven-development/SKILL.md +148 -0
- package/dist/skills/ralphctl-test-driven-development/SKILL.md +29 -2
- package/dist/skills/ralphctl-writing-for-agents/SKILL.md +113 -0
- package/package.json +10 -10
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ralphctl-frontend-ui-engineering
|
|
3
|
+
description: UI engineering discipline for user-facing interfaces — follow the project's design system and tokens instead of a generic look, handle loading, empty, error, and permission states, meet accessibility basics (keyboard access, labels, focus, contrast, never colour alone), and keep components focused with data loading separate from presentation. Use when building or changing screens, components, layouts, or interaction states in any UI stack.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Frontend UI Engineering
|
|
8
|
+
|
|
9
|
+
> Adapted from [addyosmani/agent-skills — "Frontend UI Engineering"](https://github.com/addyosmani/agent-skills)
|
|
10
|
+
> (MIT). Adapted for ralphctl's harness contract.
|
|
11
|
+
|
|
12
|
+
Build interfaces that look like a design-aware engineer made them for this product: the project's own
|
|
13
|
+
design system, every state handled, usable from a keyboard and a screen reader. The specifics differ by
|
|
14
|
+
stack — a component framework, server-rendered templates, a native toolkit — so learn this project's
|
|
15
|
+
before writing any UI.
|
|
16
|
+
|
|
17
|
+
## When this applies
|
|
18
|
+
|
|
19
|
+
- **Execute** — whenever the task builds or changes something a user sees or operates. When reviewing a
|
|
20
|
+
UI change, use the self-check below as the lens: a missing state or an inaccessible control is a
|
|
21
|
+
finding, not a nit.
|
|
22
|
+
|
|
23
|
+
## Discover the UI stack first
|
|
24
|
+
|
|
25
|
+
Find the component library, the theme or token file (colour, spacing, type, radius), the existing
|
|
26
|
+
components that already solve part of the task, and how the project tests UI (component tests,
|
|
27
|
+
accessibility checks, visual or browser tests). Reuse a house component before writing a new one.
|
|
28
|
+
|
|
29
|
+
## Components
|
|
30
|
+
|
|
31
|
+
- **One job per component.** A component that fetches, transforms, and renders is three things.
|
|
32
|
+
- **Composition over configuration.** A growing list of layout and variant flags signals a component
|
|
33
|
+
that should accept children or slots instead.
|
|
34
|
+
- **Data apart from presentation.** A container loads data and decides which state to show; a
|
|
35
|
+
presentational piece renders what it is given. The presentational piece is then trivial to test.
|
|
36
|
+
- **The simplest state that works.** Local state first; lift it only when siblings share it; a shared
|
|
37
|
+
context for read-mostly app-wide values; the URL for shareable view state (filters, pagination); the
|
|
38
|
+
project's server-data layer for remote data; a global store only for complex client state many places
|
|
39
|
+
share. Use the mechanisms the project already has.
|
|
40
|
+
|
|
41
|
+
## Follow the design system
|
|
42
|
+
|
|
43
|
+
- Use the project's tokens for colour, spacing, type, and radius — never a raw value off the scale.
|
|
44
|
+
- Keep the type hierarchy: heading levels in order, heading styles only on headings.
|
|
45
|
+
- Use realistic content when building, not placeholder text — real lengths reveal wrapping and overflow.
|
|
46
|
+
- Avoid the generic generated look: a default accent palette on everything, decorative gradients,
|
|
47
|
+
maximal rounding, uniform oversized padding, stock card grids, stacked shadows. Each one ignores the
|
|
48
|
+
product's real hierarchy; the project's system already decided these.
|
|
49
|
+
|
|
50
|
+
## Handle every state
|
|
51
|
+
|
|
52
|
+
Each view that loads or changes data needs, where it applies:
|
|
53
|
+
|
|
54
|
+
- **Loading** — a placeholder that keeps the layout stable.
|
|
55
|
+
- **Empty** — what this is and the next action, never a blank area.
|
|
56
|
+
- **Error** — what went wrong in plain words and a way to retry.
|
|
57
|
+
- **Partial or not permitted** — what the user can still do.
|
|
58
|
+
- **Success** — feedback that the action happened.
|
|
59
|
+
|
|
60
|
+
Check long and short content, and the narrowest and widest layouts the product supports.
|
|
61
|
+
|
|
62
|
+
## Accessibility basics
|
|
63
|
+
|
|
64
|
+
- Use native interactive elements (buttons, links, inputs) over clickable generic containers. A custom
|
|
65
|
+
control needs a role, keyboard focus, and the expected key handling.
|
|
66
|
+
- Every control is reachable and operable from the keyboard, in a sensible order.
|
|
67
|
+
- Every input has a label; an icon-only control has an accessible name.
|
|
68
|
+
- Move focus deliberately when content changes — into a dialog when it opens, back when it closes.
|
|
69
|
+
- Text meets WCAG AA contrast (4.5:1 for body text, 3:1 for large text).
|
|
70
|
+
- Never convey state by colour alone; pair it with text or an icon.
|
|
71
|
+
|
|
72
|
+
## Verification
|
|
73
|
+
|
|
74
|
+
Extend the project's existing UI tests for the new states and controls. When the project has no way to
|
|
75
|
+
check something in this session (a visual check, a screen-reader pass), say what was not verified in a
|
|
76
|
+
`note` signal when the prompt's output-contract section lists it; otherwise fold it into the required
|
|
77
|
+
signal's own fields.
|
|
78
|
+
|
|
79
|
+
## Red flags
|
|
80
|
+
|
|
81
|
+
- Raw colour or spacing values instead of tokens.
|
|
82
|
+
- A view with no loading, empty, or error state.
|
|
83
|
+
- A clickable element that the keyboard cannot reach.
|
|
84
|
+
- Colour as the only indicator of state.
|
|
85
|
+
- A new component that duplicates one the project already has.
|
|
86
|
+
|
|
87
|
+
## Self-check
|
|
88
|
+
|
|
89
|
+
- [ ] Uses the project's components and tokens.
|
|
90
|
+
- [ ] Loading, empty, error, permission, and success states are handled where they apply.
|
|
91
|
+
- [ ] Every interactive element works from the keyboard and has an accessible name.
|
|
92
|
+
- [ ] Focus moves correctly when content changes.
|
|
93
|
+
- [ ] Contrast meets AA; no state is conveyed by colour alone.
|
|
94
|
+
- [ ] Works at the narrowest and widest supported layouts.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ralphctl-humanizer
|
|
3
|
+
description: Edit prose so it reads like a specific person wrote it while keeping its meaning intact — remove staged contrasts, restating closers, run-up openers, reflexive lists of three, dash-chained clauses, inflated significance, promotional and stock model vocabulary, decorative bold and headings, and chat leftovers, while keeping every fact and the format the output contract requires. Use when writing or revising human-facing text such as a PR description, requirements prose, or a summary.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Humanizer
|
|
8
|
+
|
|
9
|
+
> Concept from [blader/humanizer](https://github.com/blader/humanizer) (MIT), which builds on Wikipedia's
|
|
10
|
+
> "Signs of AI writing" guide. The pattern catalogue below is written fresh for ralphctl, not copied.
|
|
11
|
+
> Adapted for ralphctl's harness contract.
|
|
12
|
+
|
|
13
|
+
Generated prose defaults to whatever suits the most readers, so the same safe moves recur in every text.
|
|
14
|
+
Someone writing for a particular reader makes particular choices. This skill strips the defaults and keeps
|
|
15
|
+
the content.
|
|
16
|
+
|
|
17
|
+
## How this runs here
|
|
18
|
+
|
|
19
|
+
- Apply it while writing the prose your output signal carries. The signal gets only the final text — no
|
|
20
|
+
draft, no list of patterns found, no commentary about the edit.
|
|
21
|
+
- The prompt's output contract wins: keep its required headings, sections, field formats, and literal
|
|
22
|
+
values. Leave code, commands, paths, identifiers, and link targets exactly as they are.
|
|
23
|
+
- Add nothing. No fact, name, number, date, or claim that is not in your source material. If a sentence
|
|
24
|
+
only works with a detail you don't have, simplify the sentence instead.
|
|
25
|
+
|
|
26
|
+
## When this applies
|
|
27
|
+
|
|
28
|
+
- **Create PR** — the title and the description body.
|
|
29
|
+
- **Refine** — the prose around the requirements. Plain wording never costs a criterion its precision; a
|
|
30
|
+
testable predicate stays testable.
|
|
31
|
+
|
|
32
|
+
## Method
|
|
33
|
+
|
|
34
|
+
1. **Spot the patterns.** Go through the full draft and mark each pattern listed below. They also show up
|
|
35
|
+
across sentences and paragraphs: a contrast spread over two sentences counts, and so does every section
|
|
36
|
+
ending on an identical wrap-up line.
|
|
37
|
+
2. **Rewrite each point plainly.** State it directly. When a paragraph is awkward, restructure it from its
|
|
38
|
+
central point instead of patching phrases. Let sentence length vary.
|
|
39
|
+
3. **Check the result.** Nothing added, nothing lost. Then look once more for the tells that survive a
|
|
40
|
+
rewrite most often: contrasts, closers, threes, dashes, and bold labels.
|
|
41
|
+
|
|
42
|
+
## Patterns, strongest first
|
|
43
|
+
|
|
44
|
+
### Staging instead of saying
|
|
45
|
+
|
|
46
|
+
1. **Contrast with a claim nobody made.** "This isn't just X — it's Y", "rather than X", a "No, it's
|
|
47
|
+
not…" sentence followed by the real point, a trailing "— no X needed". The negative half inflates the
|
|
48
|
+
positive one. A contrast earns its place if it fixes a misconception your reader really has, or if each
|
|
49
|
+
side tells them something.
|
|
50
|
+
2. **Closers that restate.** A last short line repeating the paragraph ("That's the whole point."), a
|
|
51
|
+
string of fragments for drama, emphasis by capitals or dotted words. Cut it unless it adds a fact.
|
|
52
|
+
3. **Borrowed depth.** "At its heart", "the real question is", "X is the currency of Y". Drop the
|
|
53
|
+
aphorism and state the concrete point.
|
|
54
|
+
4. **Run-ups.** Announcing what comes next ("Here's the thing", "Let's walk through it", "Quick note").
|
|
55
|
+
Start with the content.
|
|
56
|
+
5. **Answering no one.** "To be clear", "This doesn't mean", "You might think". Remove the defence unless
|
|
57
|
+
the objection is real in context.
|
|
58
|
+
|
|
59
|
+
### Rhythm by habit
|
|
60
|
+
|
|
61
|
+
6. **Reflexive threes.** Three items because three sounds complete. Keep three only when there are three
|
|
62
|
+
distinct things.
|
|
63
|
+
7. **Repeated openings.** Consecutive sentences that open with the same word or phrase. Merge them or
|
|
64
|
+
vary the subject.
|
|
65
|
+
8. **Dashes as default glue.** Reach for ordinary punctuation first (full stop, comma, colon, brackets) and
|
|
66
|
+
use a dash only when none of those works. Never touch a dash that belongs to code, a command, a path, or
|
|
67
|
+
a URL.
|
|
68
|
+
9. **Piled hedges.** "Could potentially perhaps". Keep one qualifier where the doubt is real.
|
|
69
|
+
|
|
70
|
+
### Inflation
|
|
71
|
+
|
|
72
|
+
10. **Stock model vocabulary.** Words that turn up far more in generated text than in people's: delve,
|
|
73
|
+
seamless, leverage and harness (as figurative verbs), robust (when not technical), crucial, pivotal,
|
|
74
|
+
myriad, realm, tapestry, landscape (abstract), foster, elevate, empower, unlock, streamline,
|
|
75
|
+
showcase, underscore, testament, meticulous, game-changing, cutting-edge. Use the plain word. One on
|
|
76
|
+
its own is weak evidence; a cluster is strong.
|
|
77
|
+
11. **Inflated significance.** "Marks a turning point", "paves the way", "raises the bar", a closing
|
|
78
|
+
paragraph about what the future holds. Stop once the concrete facts run out.
|
|
79
|
+
12. **Editorialising -ing tails.** "…, highlighting its importance", "…, ensuring a smooth experience".
|
|
80
|
+
Keep the fact; drop the tail unless the source supports it.
|
|
81
|
+
13. **Promotional tone.** "Powerful", "effortless", "best-in-class", "beautifully". Say what the thing does.
|
|
82
|
+
14. **Vague authority.** "Experts agree", "widely regarded". Name the source or drop the claim.
|
|
83
|
+
15. **Dodging plain verbs.** "Serves as", "functions as", "boasts". Use is and has.
|
|
84
|
+
16. **Vague links.** "Associated with", "tied to". Name the actual relation, or keep the vague wording
|
|
85
|
+
when the source gives nothing more.
|
|
86
|
+
|
|
87
|
+
### Formatting by habit
|
|
88
|
+
|
|
89
|
+
17. **Bold everywhere.** Bold on ordinary words, or a bolded label plus colon at the start of every
|
|
90
|
+
bullet. Remove the bold, and when the labels say nothing, rewrite the list as sentences.
|
|
91
|
+
18. **Decorated headings.** Title Case, emoji, arrows, a rule between every section. Use sentence case and
|
|
92
|
+
plain headings, unless the contract prescribes the heading text.
|
|
93
|
+
|
|
94
|
+
### Leftovers
|
|
95
|
+
|
|
96
|
+
19. **Chat residue.** "I hope this helps", "Great question", "Happy to adjust this", offers to do
|
|
97
|
+
more. Remove the wrapper, keep the content.
|
|
98
|
+
20. **Writing about the text.** "Below is a summary of", "this description was generated from",
|
|
99
|
+
narrating how the text was assembled. Describing what a change replaces is fine in a PR description —
|
|
100
|
+
that is its subject.
|
|
101
|
+
21. **Knowledge-limit filler.** Conceding that information is missing, then papering over the hole with
|
|
102
|
+
something that merely sounds right. Say plainly what is unknown, or delete the sentence.
|
|
103
|
+
|
|
104
|
+
### Wrong reader
|
|
105
|
+
|
|
106
|
+
22. **Telling the reader what they already know.** A reviewer already has the ticket and the diff. Open with
|
|
107
|
+
the decision and include only the argument that could change their mind about it.
|
|
108
|
+
|
|
109
|
+
## Before and after
|
|
110
|
+
|
|
111
|
+
Before:
|
|
112
|
+
|
|
113
|
+
> This PR doesn't just fix the retry loop — it fundamentally transforms how we handle 503 responses,
|
|
114
|
+
> ensuring a robust, seamless experience. Retries now stop at the configured limit.
|
|
115
|
+
|
|
116
|
+
After:
|
|
117
|
+
|
|
118
|
+
> Retries on a 503 response now stop at the configured limit instead of looping.
|
|
119
|
+
|
|
120
|
+
Before:
|
|
121
|
+
|
|
122
|
+
> **Performance:** Performance has been improved. **Reliability:** Reliability has been enhanced.
|
|
123
|
+
|
|
124
|
+
After: cut both lines. Neither says what changed; name the concrete changes from the diff instead.
|
|
125
|
+
|
|
126
|
+
## When not to act
|
|
127
|
+
|
|
128
|
+
Don't rewrite a flagged phrase when it sits in a quotation, a name or title, or a passage about the phrase
|
|
129
|
+
itself. A single tell is weak evidence; act on clusters. Keep what carries a writer's voice — an unusual
|
|
130
|
+
specific detail, mixed feelings, a genuine aside.
|
|
131
|
+
|
|
132
|
+
## Self-check
|
|
133
|
+
|
|
134
|
+
- [ ] Every fact, number, and name from the source survives; nothing new was added.
|
|
135
|
+
- [ ] The contract's required structure and literal values are untouched.
|
|
136
|
+
- [ ] No staged contrast, restating closer, or run-up remains.
|
|
137
|
+
- [ ] Code, commands, and paths are unchanged.
|
|
@@ -17,6 +17,8 @@ worth building — through structured divergent and convergent thinking, not a t
|
|
|
17
17
|
- **Ideate** — the primary home: turning a raw prompt or hunch into evaluated, distinct directions.
|
|
18
18
|
- **Refine** — when the input requirement is really an unshaped idea: run a compressed version of the phases below before writing acceptance criteria.
|
|
19
19
|
|
|
20
|
+
**Not for:** a direction that is already chosen and now needs sharp requirements — that is ralphctl-spec-driven-development when installed.
|
|
21
|
+
|
|
20
22
|
## Philosophy
|
|
21
23
|
|
|
22
24
|
- Simplicity is the ultimate sophistication. Push toward the simplest version that still solves the real problem.
|
|
@@ -8,7 +8,8 @@ description: Cross-phase skill — treat AI output as a controlled feedback loop
|
|
|
8
8
|
> Concept
|
|
9
9
|
>
|
|
10
10
|
> from [SPDD (Zhang & Xia, martinfowler.com) — "Iterative Review"](https://martinfowler.com/articles/structured-prompt-driven/iterative-review.html).
|
|
11
|
-
> Adapted for ralphctl's three phases.
|
|
11
|
+
> Adapted for ralphctl's three phases. Risk-first slicing draws on
|
|
12
|
+
> [addyosmani/agent-skills — "Incremental Implementation"](https://github.com/addyosmani/agent-skills) (MIT).
|
|
12
13
|
|
|
13
14
|
One-shot generation looks fast and is slow. The cheap review you skipped at iteration N becomes the expensive
|
|
14
15
|
unwind at iteration N+5, when a regression that lived undetected through five steps surfaces only at the
|
|
@@ -32,11 +33,16 @@ deployed form — but the same posture also belongs **inside** each phase's work
|
|
|
32
33
|
|
|
33
34
|
1. **Run the cheapest check first, often.** Lint, typecheck, narrow test runs — not the full suite — after
|
|
34
35
|
each meaningful change. The point is to catch the regression at the seam, not to certify completion.
|
|
35
|
-
2. **
|
|
36
|
+
2. **Slice risk-first, and stay buildable between slices.** When the work has several parts, take the
|
|
37
|
+
least certain one first — the unproven integration, the unfamiliar API — so a dead end surfaces before
|
|
38
|
+
anything is built on it; a plan orders its tasks the same way. When your session can run commands,
|
|
39
|
+
confirm after each slice that the project still builds and its existing checks still pass, so the next
|
|
40
|
+
slice never starts on a broken tree.
|
|
41
|
+
3. **Re-read your own output once before submitting.** Whether it is criteria, tasks, or a diff, the second
|
|
36
42
|
read catches what the first one missed. Cheap.
|
|
37
|
-
|
|
43
|
+
4. **Treat the check gate as a loop, not a finish line.** A failing gate is feedback, not a verdict. Apply
|
|
38
44
|
the fix and re-run; do not signal completion against a red gate.
|
|
39
|
-
|
|
45
|
+
5. **When a fix attempt repeats the same failure, escalate rather than retry.** Two iterations of the same
|
|
40
46
|
error is a plateau — the next fix is a guess. Surface the blocker rather than burning the budget on a
|
|
41
47
|
third attempt: write a `note` signal in `signals.json` when the prompt's output-contract section lists
|
|
42
48
|
it as an accepted kind; when it does not, use whichever blocked or narrative signal the contract does
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ralphctl-observability-and-instrumentation
|
|
3
|
+
description: Instrument code so its production behaviour can be diagnosed from the outside — start from the questions an operator will ask, then emit structured events with stable names, a correlation id, and an entry-point field, bounded-cardinality metrics with latency percentiles, traces across async boundaries, and symptom-based alerts, never secrets or personal data. Use when adding I/O, retries, queues, background jobs, external integrations, or endpoints, or when a reported problem could not be diagnosed from existing telemetry.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Observability and Instrumentation
|
|
8
|
+
|
|
9
|
+
> Adapted from [addyosmani/agent-skills — "Observability and Instrumentation"](https://github.com/addyosmani/agent-skills)
|
|
10
|
+
> (MIT). Adapted for ralphctl's harness contract.
|
|
11
|
+
|
|
12
|
+
Code you cannot observe is code you cannot operate. Instrumentation is written with the feature, the way
|
|
13
|
+
tests are — when it ships without telemetry, the first reported bug becomes archaeology instead of a
|
|
14
|
+
query.
|
|
15
|
+
|
|
16
|
+
**Not for:** diagnosing a failure happening now (ralphctl-debugging-and-error-recovery when installed),
|
|
17
|
+
or optimising measured slowness (ralphctl-performance-optimization when installed).
|
|
18
|
+
|
|
19
|
+
## When this applies
|
|
20
|
+
|
|
21
|
+
- **Plan** — for tasks that add I/O, retries, queues, jobs, or integrations, put the telemetry in the
|
|
22
|
+
task's steps and add a verification criterion that the failure path is observable. Name the operator
|
|
23
|
+
questions it must answer.
|
|
24
|
+
- **Execute** — instrument as you build, with the logging, metrics, and tracing libraries the project
|
|
25
|
+
already uses. Adding a new telemetry stack is a decision for the task to make, not a side effect.
|
|
26
|
+
|
|
27
|
+
## 1. Define "working" first
|
|
28
|
+
|
|
29
|
+
Telemetry without a question is noise. Before instrumenting, write down two to four questions an operator
|
|
30
|
+
will ask about this feature — what fraction succeeds first time, why permanent failures fail, whether a
|
|
31
|
+
dependency is slower than usual. Every signal you add must help answer one of them.
|
|
32
|
+
|
|
33
|
+
## 2. Pick the signal per question
|
|
34
|
+
|
|
35
|
+
| Signal | Answers | Cost |
|
|
36
|
+
| -------------- | ---------------------------------------- | ----------------------------- |
|
|
37
|
+
| Structured log | What happened in this specific case? | Per event; grows with traffic |
|
|
38
|
+
| Metric | How often, how fast, in aggregate? | Fixed per series; cheap |
|
|
39
|
+
| Trace | Where did the time go across components? | Per request; usually sampled |
|
|
40
|
+
|
|
41
|
+
Metrics tell you _that_ something is wrong, traces tell you _where_, logs tell you _why_.
|
|
42
|
+
|
|
43
|
+
## 3. Structured logging
|
|
44
|
+
|
|
45
|
+
- **Events, not prose.** A stable event name plus machine-readable fields — never a sentence built by
|
|
46
|
+
string interpolation that nobody can query.
|
|
47
|
+
- **Levels used consistently** — error: an invariant broke and someone may need to act; warn: degraded
|
|
48
|
+
but handled (a retry succeeded, a fallback ran); info: a significant business event; debug: diagnostic
|
|
49
|
+
detail, off in production by default.
|
|
50
|
+
- **A correlation id on everything.** Accept or create one at the system boundary and attach it to every
|
|
51
|
+
log line, span, and outbound call, so one request can be reconstructed from interleaved output.
|
|
52
|
+
- **Name the entry point** when several entry points (a scheduler, a replay endpoint, a manual run) feed
|
|
53
|
+
one log. Set it where the run starts and propagate it with the correlation id across the same
|
|
54
|
+
boundaries — queue metadata, headers — rather than re-deriving it downstream.
|
|
55
|
+
- **Never log secrets, tokens, passwords, or full personal data.** Log an allowlist of fields, never a
|
|
56
|
+
whole request body.
|
|
57
|
+
|
|
58
|
+
## 4. Metrics
|
|
59
|
+
|
|
60
|
+
Instrument rate, errors, and duration for every request-driven endpoint and every external dependency;
|
|
61
|
+
utilisation, saturation, and errors for resources such as pools and queues. Labels come from small fixed
|
|
62
|
+
sets (route template, status class, dependency name) — never user ids, raw URLs, or message text, which
|
|
63
|
+
explode the number of series and belong in logs and traces. Record latency as a histogram and read
|
|
64
|
+
percentiles; an average hides the slowest users.
|
|
65
|
+
|
|
66
|
+
## 5. Tracing
|
|
67
|
+
|
|
68
|
+
Prefer a vendor-neutral standard such as OpenTelemetry when choosing, and the project's existing setup
|
|
69
|
+
when there is one. Use auto-instrumentation where the stack offers it; add manual spans only around
|
|
70
|
+
meaningful units of work, with the attributes an operator will filter by. Propagate context across every
|
|
71
|
+
async boundary or the trace dies at the gap.
|
|
72
|
+
|
|
73
|
+
## 6. Alerting
|
|
74
|
+
|
|
75
|
+
Alert on symptoms users feel (error rate, latency, queue age), not causes (CPU, one restart). Every alert
|
|
76
|
+
is actionable, has a threshold and duration justified by an objective or by history, and uses one of two
|
|
77
|
+
severities: act now, or act this week. When the project keeps runbooks, link each new alert to one; do
|
|
78
|
+
not create a runbook location the task did not ask for.
|
|
79
|
+
|
|
80
|
+
## 7. Verify the telemetry itself
|
|
81
|
+
|
|
82
|
+
Instrumentation is code and can be wrong. Exercise the failure path in a test and assert the emitted
|
|
83
|
+
event and its fields — the project's logger or metrics library usually offers a capture or in-memory
|
|
84
|
+
sink. Checks that need a live environment (a dashboard, a tracing UI, firing an alert) cannot happen in
|
|
85
|
+
this session: list them as unverified in a `note` signal when the prompt's output-contract section lists
|
|
86
|
+
it; otherwise fold them into the required signal's own fields.
|
|
87
|
+
|
|
88
|
+
## Red flags
|
|
89
|
+
|
|
90
|
+
- A change adding retries, queues, or external calls with no new telemetry.
|
|
91
|
+
- Log lines built by interpolation instead of structured fields.
|
|
92
|
+
- No correlation id, or one shared log fed by several entry points with nothing naming which.
|
|
93
|
+
- Metric labels carrying user ids, raw URLs, or error text.
|
|
94
|
+
- Latency tracked only as an average.
|
|
95
|
+
- Secrets, tokens, or whole request bodies in log output.
|
|
96
|
+
|
|
97
|
+
## Self-check
|
|
98
|
+
|
|
99
|
+
- [ ] The operator questions are named, and each signal maps to one.
|
|
100
|
+
- [ ] Log output is structured, with stable event names and a correlation id.
|
|
101
|
+
- [ ] No secret or unredacted personal data reaches any log line.
|
|
102
|
+
- [ ] New endpoints and dependencies have rate, error, and duration metrics with bounded labels.
|
|
103
|
+
- [ ] Latency is a histogram with queryable percentiles.
|
|
104
|
+
- [ ] The failure path's telemetry is asserted in a test, or listed as unverified.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ralphctl-performance-optimization
|
|
3
|
+
description: Measure-first performance discipline — take a baseline with the project's own tooling, find the actual bottleneck, change one thing, re-measure the same way, and keep the change only when it beats run-to-run noise with the tests still green. Use when a task states a performance target, reports slowness or a regression, or touches a hot path, query, cache, or connection pool; not for speculative optimisation without evidence of a problem.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Performance Optimization
|
|
8
|
+
|
|
9
|
+
> Adapted from [addyosmani/agent-skills — "Performance Optimization"](https://github.com/addyosmani/agent-skills)
|
|
10
|
+
> (MIT). Adapted for ralphctl's harness contract.
|
|
11
|
+
|
|
12
|
+
Performance work without measurement is guessing, and guessing adds complexity that costs more than the
|
|
13
|
+
speed it buys. Measure, find the real bottleneck, fix that one thing, measure again — and keep only what
|
|
14
|
+
the numbers justify.
|
|
15
|
+
|
|
16
|
+
**When not to use:** there is no evidence of a problem. Optimising on a hunch is how neutral complexity
|
|
17
|
+
lands.
|
|
18
|
+
|
|
19
|
+
## When this applies
|
|
20
|
+
|
|
21
|
+
- **Execute** — when the task carries a performance target or a slowness report, or the change touches a
|
|
22
|
+
hot path. The generator measures with the project's tooling; when reviewing, a performance claim with no
|
|
23
|
+
before-and-after numbers behind it is a finding, and so is an "optimisation" that changed behaviour.
|
|
24
|
+
|
|
25
|
+
## The workflow
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
MEASURE → IDENTIFY → FIX ONE THING → RE-MEASURE (keep or undo) → GUARD
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 1. Measure
|
|
32
|
+
|
|
33
|
+
Use what the repository already has — a benchmark target, a profiler, a timing harness, a query-plan
|
|
34
|
+
command, a load script — found in its manifest, scripts, or CI configuration. Fix the budget before you
|
|
35
|
+
start: the same command, the same input, the same conditions (warm or cold cache, sample count). Record
|
|
36
|
+
the baseline numbers.
|
|
37
|
+
|
|
38
|
+
### 2. Identify
|
|
39
|
+
|
|
40
|
+
Let the symptom pick what to measure first:
|
|
41
|
+
|
|
42
|
+
- **Startup or first load is slow** — payload or bundle size, blocking work at start, slow first
|
|
43
|
+
response.
|
|
44
|
+
- **Interaction feels sluggish** — long synchronous work on the main thread or event loop, redundant
|
|
45
|
+
re-rendering or recomputation.
|
|
46
|
+
- **One operation is slow** — profile it; read the query plan of each query it runs.
|
|
47
|
+
- **Everything slows at once** — connection or thread pool exhaustion, memory pressure, CPU saturation.
|
|
48
|
+
- **Slowness is intermittent** — lock contention, garbage-collection pauses, a slow external dependency.
|
|
49
|
+
- **Memory keeps growing** — leaked references, unbounded caches or lists, retained payloads.
|
|
50
|
+
|
|
51
|
+
### 3. Fix one thing
|
|
52
|
+
|
|
53
|
+
Fix only the bottleneck step 2 identified. The usual suspects:
|
|
54
|
+
|
|
55
|
+
- **Query per row (N+1).** Fetch the relation in the same query or one batched query, not in the loop.
|
|
56
|
+
- **Unbounded fetching.** Every list read has a limit and a stable order.
|
|
57
|
+
- **A query that ignores its index.** "Add an index" is the guess; the query plan before and after is the
|
|
58
|
+
measurement. A stale row estimate wants refreshed statistics, not a new index. Index for the query's
|
|
59
|
+
shape — equality columns first, then the range or sort column. An index that did not change the plan
|
|
60
|
+
is an undo, and every index taxes every write.
|
|
61
|
+
- **Pool exhaustion.** Every operation slows together and time goes to waiting for a connection. A bigger
|
|
62
|
+
pool only moves the queue somewhere harder to see — find what holds connections, and size pools so the
|
|
63
|
+
total across all processes stays under the server's limit.
|
|
64
|
+
- **Missing or wrong caching.** Cache only what is expensive to produce and read far more often than it
|
|
65
|
+
changes. Every input that changes the result belongs in the key (tenant, locale, permissions, flags) —
|
|
66
|
+
a key that omits the viewer serves one user's data to another. Pick one invalidation strategy and state
|
|
67
|
+
the acceptable staleness. Protect hot keys against a stampede (serve stale while one request
|
|
68
|
+
recomputes, or coalesce concurrent misses). Never cache what must be fresh.
|
|
69
|
+
- **Repeated work in a hot loop.** Hoist the invariant; memoise only what the profile shows is costly.
|
|
70
|
+
|
|
71
|
+
### 4. Re-measure: keep or undo
|
|
72
|
+
|
|
73
|
+
A fix is a hypothesis until re-measured — the same way as the baseline. Change one thing at a time so the
|
|
74
|
+
number is attributable, and repeat the measurement to compare the delta against run-to-run variance.
|
|
75
|
+
|
|
76
|
+
| Result against the baseline | Action |
|
|
77
|
+
| ----------------------------- | ---------------------------------------- |
|
|
78
|
+
| Beyond the noise, tests green | Keep it. |
|
|
79
|
+
| Within the noise | Undo it. Neutral is not a keep. |
|
|
80
|
+
| Worse | Undo it. |
|
|
81
|
+
| Faster, but a test went red | Undo it — a regression dressed as a win. |
|
|
82
|
+
|
|
83
|
+
Correctness gates the metric: an "optimisation" that wins by skipping work the product needed (a
|
|
84
|
+
validation, a fresh read, an awaited step) is a regression.
|
|
85
|
+
|
|
86
|
+
**Record every attempt, kept and undone alike.** An undone attempt leaves no trace in the diff, which is
|
|
87
|
+
how the same dead idea gets tried again. Record idea, baseline and result, verdict, and why in a `note`
|
|
88
|
+
signal when the prompt's output-contract section lists it; otherwise fold it into the required signal's
|
|
89
|
+
own fields.
|
|
90
|
+
|
|
91
|
+
### 5. Guard
|
|
92
|
+
|
|
93
|
+
Protect the metric that justified the work. When the project already has a benchmark, performance test,
|
|
94
|
+
or budget, extend it to cover this path. Do not invent a new gate or pipeline step the task did not ask
|
|
95
|
+
for — name the missing guard in the same signal guidance as above instead.
|
|
96
|
+
|
|
97
|
+
## Common rationalisations
|
|
98
|
+
|
|
99
|
+
| Rationalisation | Reality |
|
|
100
|
+
| ------------------------------------------ | ----------------------------------------------------------------------------------- |
|
|
101
|
+
| "This optimisation is obvious" | If you did not measure, you do not know. Re-measuring an obvious win is cheap. |
|
|
102
|
+
| "The query is slow, add an index" | Read the plan first. The index may exist and be unusable; every index taxes writes. |
|
|
103
|
+
| "Just cache it" | Caching a cheap call buys a staleness bug and nothing else. |
|
|
104
|
+
| "Raise the pool size" | It relocates the queue. Find what holds the connections. |
|
|
105
|
+
| "It didn't help much, but it doesn't hurt" | Neutral changes are maintained forever and bought nothing. Undo them. |
|
|
106
|
+
| "We already wrote it, may as well keep it" | Sunk cost. The measurement does not care how long the change took. |
|
|
107
|
+
|
|
108
|
+
## Red flags
|
|
109
|
+
|
|
110
|
+
- An optimisation with no profiling data or baseline behind it.
|
|
111
|
+
- Several optimisations measured as one number.
|
|
112
|
+
- An index added without a query plan before and after.
|
|
113
|
+
- A cache key that omits an input the result depends on, or a cache with no stated staleness.
|
|
114
|
+
- A pool size raised in response to exhaustion without finding the holder.
|
|
115
|
+
- A "win" that needed a test changed, skipped, or deleted.
|
|
116
|
+
|
|
117
|
+
## Self-check
|
|
118
|
+
|
|
119
|
+
- [ ] Before-and-after numbers exist, taken the same way.
|
|
120
|
+
- [ ] The improvement exceeds run-to-run variance.
|
|
121
|
+
- [ ] Changes that did not beat the baseline were undone.
|
|
122
|
+
- [ ] Every attempt is recorded, including the undone ones.
|
|
123
|
+
- [ ] The existing tests still pass — behaviour did not change.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ralphctl-ponytail
|
|
3
|
-
description: Anti-over-engineering ladder for choosing HOW to implement something —
|
|
3
|
+
description: Anti-over-engineering ladder for choosing HOW to implement something — the smallest change that fully solves the task. Before writing custom code, climb the rungs in order and stop at the first that holds. Does this need to exist at all (YAGNI) → already in the codebase → standard library or platform feature → already-installed dependency → one line → minimum code that works. Use when picking an implementation approach or evaluating a new dependency; for keeping the footprint of an already-chosen approach small, defer to the ralphctl-surgical-simplicity skill when installed.
|
|
4
4
|
license: MIT
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ license: MIT
|
|
|
11
11
|
|
|
12
12
|
Be a lazy senior developer. Lazy means efficient, not careless — the posture of someone who has
|
|
13
13
|
seen every over-engineered codebase and been paged at 3am for one. The best code is the code
|
|
14
|
-
never written.
|
|
14
|
+
never written: solve the whole problem with the least new code.
|
|
15
15
|
|
|
16
16
|
## When this applies
|
|
17
17
|
|
|
@@ -22,22 +22,27 @@ never written.
|
|
|
22
22
|
- **Create PR** — when summarising the change, name what was deliberately skipped and when it
|
|
23
23
|
would be worth adding.
|
|
24
24
|
|
|
25
|
+
## Before you write
|
|
26
|
+
|
|
27
|
+
Read the task and the code it touches. List every place your change must reach: callers, tests,
|
|
28
|
+
fixtures, config, exports. Check what your change could break for users: data it would destroy or
|
|
29
|
+
expose, callers that stop working. That is scope. Extra features are not.
|
|
30
|
+
|
|
25
31
|
## The ladder
|
|
26
32
|
|
|
27
|
-
Stop at the first rung that
|
|
33
|
+
Stop at the first rung that fully works:
|
|
28
34
|
|
|
29
|
-
1. **Does this need to exist at all?**
|
|
30
|
-
2. **Already in this codebase?** A helper, util, type, or pattern that already lives here → reuse it. Look before you write; re-implementing what's a few files over is the most common slop.
|
|
31
|
-
3. **Standard library
|
|
32
|
-
4. **
|
|
33
|
-
5. **
|
|
34
|
-
6. **
|
|
35
|
-
7. **Only then:** the minimum code that works.
|
|
35
|
+
1. **Does this need to exist at all?** Skip features, options, and flexibility nobody asked for, and say so in one line. (YAGNI) A vague request gets the smallest version that does the core job.
|
|
36
|
+
2. **Already in this codebase?** A helper, util, type, component, or pattern that already lives here → reuse it, the way the surrounding code does. Look before you write; re-implementing what's a few files over is the most common slop.
|
|
37
|
+
3. **Standard library or a native platform feature covers it?** Use it — a built-in form control over a widget library, a stylesheet rule over scripted behaviour, a database constraint over application code — unless the project has its own: a house component beats a native widget.
|
|
38
|
+
4. **Already-installed dependency solves it?** Use it. Never add a new one for what a few lines can do.
|
|
39
|
+
5. **Can it be one line a reader gets at a glance?** One line.
|
|
40
|
+
6. **Only then:** the minimum code that works.
|
|
36
41
|
|
|
37
42
|
The ladder is a reflex, not a research project — but it runs _after_ you understand the problem,
|
|
38
|
-
not instead of it.
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
not instead of it. Trace the real flow end to end, then climb. Two rungs work → take the higher
|
|
44
|
+
one and move on. The first lazy solution that works is the right one — once you actually know
|
|
45
|
+
what the change has to touch.
|
|
41
46
|
|
|
42
47
|
**Bug fix = root cause, not symptom.** A report names a symptom. Before you edit, find every
|
|
43
48
|
caller of the function you're about to touch. The lazy fix IS the root-cause fix: one guard in
|
|
@@ -47,26 +52,30 @@ through.
|
|
|
47
52
|
|
|
48
53
|
## Rules
|
|
49
54
|
|
|
50
|
-
-
|
|
55
|
+
- Be lazy about the solution, never about the change itself: finish every part the task needs, including the callers, tests, and fixtures your change breaks.
|
|
56
|
+
- No unrequested abstractions: no interface with one implementation, no factory for one product, no wrapper or type conversion nobody asked for, no config for a value that never changes. Keep values in the form the platform already gives you.
|
|
51
57
|
- No boilerplate, no scaffolding "for later" — later can scaffold for itself.
|
|
58
|
+
- Keep the structure the codebase already has: its layers, interfaces, and conventions.
|
|
52
59
|
- Deletion over addition. Boring over clever — clever is what someone decodes at 3am.
|
|
53
|
-
- Fewest files possible. Shortest working diff wins — but only once you
|
|
60
|
+
- Fewest files possible. Shortest working diff wins — but only once you know everything it must touch. The smallest change in the wrong place isn't lazy, it's a second bug. A one-liner that needs decoding is not short.
|
|
61
|
+
- Code you move or merge keeps its error handling and validation.
|
|
62
|
+
- Comment only the why the code cannot show, in one line.
|
|
54
63
|
- Complex request? Ship the lazy version and question the rest: "Did X; Y covers it. Need full X? Say
|
|
55
64
|
so." Write it as a `note` signal in `signals.json` when the prompt's output-contract section lists it,
|
|
56
65
|
otherwise fold the question into the required signal's own fields. Never stall on an answer you can
|
|
57
66
|
default.
|
|
58
|
-
- Two
|
|
59
|
-
-
|
|
67
|
+
- Two options of the same size? Take the one that's correct on edge cases. Lazy means writing less code, not picking the flimsier algorithm.
|
|
68
|
+
- A shortcut with a known limit (global lock, O(n²) scan, naive heuristic) gets a code comment naming the limit and the upgrade path, in this form: `// shortcut: global lock, per-account locks if throughput matters`.
|
|
60
69
|
|
|
61
70
|
## Output
|
|
62
71
|
|
|
63
|
-
Code first. Keep any accompanying explanation to
|
|
64
|
-
|
|
65
|
-
defending a simplification is complexity smuggled back in as
|
|
66
|
-
explicitly asked for (a report, a walkthrough, per-step notes) is not
|
|
67
|
-
the rule is only against unrequested prose. Deliberate skips
|
|
68
|
-
when Y — as a `note` signal in `signals.json` when the
|
|
69
|
-
it, otherwise inside the required signal's own fields.
|
|
72
|
+
Code first. Keep any accompanying explanation to one or two short lines: what you skipped or did
|
|
73
|
+
not check, and any risk a reviewer must know. If the explanation is longer than the code, delete
|
|
74
|
+
the explanation — every paragraph defending a simplification is complexity smuggled back in as
|
|
75
|
+
prose. Explanation the task explicitly asked for (a report, a walkthrough, per-step notes) is not
|
|
76
|
+
debt — give it in full; the rule is only against unrequested prose. Deliberate skips and unchecked
|
|
77
|
+
risks worth remembering: skipped X, add when Y — as a `note` signal in `signals.json` when the
|
|
78
|
+
prompt's output-contract section lists it, otherwise inside the required signal's own fields.
|
|
70
79
|
|
|
71
80
|
## When NOT to be lazy
|
|
72
81
|
|
|
@@ -82,9 +91,10 @@ up as efficiency and ships a confident wrong fix. Read fully, then be lazy.
|
|
|
82
91
|
Hardware is never the ideal on paper: a real clock drifts, a real sensor reads off. Leave the
|
|
83
92
|
calibration knob, not just less code — the physical world needs tuning a minimal model can't see.
|
|
84
93
|
|
|
85
|
-
Lazy code without its check is unfinished.
|
|
86
|
-
money/security path) leaves ONE runnable check behind —
|
|
87
|
-
|
|
88
|
-
one-liners need no test —
|
|
94
|
+
Lazy code without its check is unfinished. New non-trivial logic (a branch, a loop, a parser, a
|
|
95
|
+
money/security path, or a whole new script or app) leaves ONE runnable check behind — one small
|
|
96
|
+
test or an assert-based self-check, the smallest thing that fails if the logic breaks. No
|
|
97
|
+
frameworks, no fixtures, no per-function suites unless asked. Trivial one-liners need no test —
|
|
98
|
+
YAGNI applies to tests too.
|
|
89
99
|
|
|
90
100
|
The shortest path to done is the right path.
|