@kl-c/matrixos 0.3.40 → 0.3.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/cli/index.js +167 -1
  2. package/dist/cli/skills/api-and-interface-design/SKILL.md +298 -0
  3. package/dist/cli/skills/browser-testing-with-devtools/SKILL.md +321 -0
  4. package/dist/cli/skills/ci-cd-and-automation/SKILL.md +394 -0
  5. package/dist/cli/skills/context-engineering/SKILL.md +293 -0
  6. package/dist/cli/skills/deprecation-and-migration/SKILL.md +251 -0
  7. package/dist/cli/skills/documentation-and-adrs/SKILL.md +292 -0
  8. package/dist/cli/skills/doubt-driven-development/SKILL.md +247 -0
  9. package/dist/cli/skills/incremental-implementation/SKILL.md +253 -0
  10. package/dist/cli/skills/interview-me/SKILL.md +229 -0
  11. package/dist/cli/skills/observability-and-instrumentation/SKILL.md +207 -0
  12. package/dist/cli/skills/performance-optimization/SKILL.md +354 -0
  13. package/dist/cli/skills/security-and-hardening/SKILL.md +471 -0
  14. package/dist/cli/skills/shipping-and-launch/SKILL.md +314 -0
  15. package/dist/cli/skills/source-driven-development/SKILL.md +198 -0
  16. package/dist/cli/skills/test-driven-development/SKILL.md +402 -0
  17. package/dist/cli-node/index.js +167 -1
  18. package/dist/features/dashboard/data-provider.d.ts +21 -1
  19. package/dist/features/dashboard/frontend/css/style.css +148 -1
  20. package/dist/features/dashboard/frontend/index.html +22 -0
  21. package/dist/features/dashboard/frontend/js/api.js +4 -0
  22. package/dist/features/dashboard/frontend/js/app.js +77 -2
  23. package/dist/features/dashboard/types.d.ts +9 -0
  24. package/dist/index.js +1 -1
  25. package/dist/skills/api-and-interface-design/SKILL.md +298 -0
  26. package/dist/skills/browser-testing-with-devtools/SKILL.md +321 -0
  27. package/dist/skills/ci-cd-and-automation/SKILL.md +394 -0
  28. package/dist/skills/context-engineering/SKILL.md +293 -0
  29. package/dist/skills/deprecation-and-migration/SKILL.md +251 -0
  30. package/dist/skills/documentation-and-adrs/SKILL.md +292 -0
  31. package/dist/skills/doubt-driven-development/SKILL.md +247 -0
  32. package/dist/skills/incremental-implementation/SKILL.md +253 -0
  33. package/dist/skills/interview-me/SKILL.md +229 -0
  34. package/dist/skills/observability-and-instrumentation/SKILL.md +207 -0
  35. package/dist/skills/performance-optimization/SKILL.md +354 -0
  36. package/dist/skills/security-and-hardening/SKILL.md +471 -0
  37. package/dist/skills/shipping-and-launch/SKILL.md +314 -0
  38. package/dist/skills/source-driven-development/SKILL.md +198 -0
  39. package/dist/skills/test-driven-development/SKILL.md +402 -0
  40. package/package.json +1 -1
  41. package/packages/shared-skills/skills/api-and-interface-design/SKILL.md +298 -0
  42. package/packages/shared-skills/skills/browser-testing-with-devtools/SKILL.md +321 -0
  43. package/packages/shared-skills/skills/ci-cd-and-automation/SKILL.md +394 -0
  44. package/packages/shared-skills/skills/context-engineering/SKILL.md +293 -0
  45. package/packages/shared-skills/skills/deprecation-and-migration/SKILL.md +251 -0
  46. package/packages/shared-skills/skills/documentation-and-adrs/SKILL.md +292 -0
  47. package/packages/shared-skills/skills/doubt-driven-development/SKILL.md +247 -0
  48. package/packages/shared-skills/skills/incremental-implementation/SKILL.md +253 -0
  49. package/packages/shared-skills/skills/interview-me/SKILL.md +229 -0
  50. package/packages/shared-skills/skills/observability-and-instrumentation/SKILL.md +207 -0
  51. package/packages/shared-skills/skills/performance-optimization/SKILL.md +354 -0
  52. package/packages/shared-skills/skills/security-and-hardening/SKILL.md +471 -0
  53. package/packages/shared-skills/skills/shipping-and-launch/SKILL.md +314 -0
  54. package/packages/shared-skills/skills/source-driven-development/SKILL.md +198 -0
  55. package/packages/shared-skills/skills/test-driven-development/SKILL.md +402 -0
@@ -0,0 +1,229 @@
1
+ ---
2
+ name: interview-me
3
+ description: Extracts what the user actually wants instead of what they think they should want. Achieves this through one-question-at-a-time interview until ~95% confidence about the underlying intent. Use when an ask is underspecified ("build me X" without "for whom" or "why now"), when the user explicitly invokes ("interview me", "grill me", "are we sure?", "stress-test my thinking"), or when you catch yourself silently filling in ambiguous requirements before any plan, spec, or code exists.
4
+ source: addyosmani/agent-skills (MIT)
5
+ ---
6
+
7
+ # Interview Me
8
+
9
+ ## Overview
10
+
11
+ What people ask for and what they actually want are different things. They ask for "a dashboard" because that's what one asks for, not because a dashboard solves their problem. They say "make it faster" without a number to hit.
12
+
13
+ The cheapest moment to find this gap is before any plan, spec, or code exists. Once you've started building, switching costs are real, and the user will rationalize the wrong thing into a "good enough" thing. The misfit gets locked in.
14
+
15
+ This skill closes the gap before it costs anything. The other Define-phase skills assume you already know roughly what you want: `idea-refine` generates variations from an idea, `spec-driven-development` writes the requirements down, `doubt-driven-development` stress-tests a plan after you've drafted one. Interview-me is the part before all of those, where you ask one question at a time, with your best guess attached, until you can predict what the user is going to say before they say it.
16
+
17
+ ## When to Use
18
+
19
+ Apply this skill when:
20
+
21
+ - The ask is missing at least one of: **who** the user is, **why** they want it, what **success** looks like, what the binding **constraint** is
22
+ - The request is conventional rather than specific ("build me X", "make it faster") and you can't unpack the convention without guessing
23
+ - You're tempted to start with assumptions you haven't surfaced
24
+ - The user hasn't said which value they're optimizing for when two reasonable ones are in tension (simplicity vs. flexibility, cost vs. speed)
25
+ - The user explicitly invokes: "interview me", "grill me", "before we start, are we sure?", "stress-test my thinking"
26
+
27
+ **When NOT to use:**
28
+
29
+ - The ask is unambiguous and self-contained ("rename this variable", "fix this typo")
30
+ - The user has explicitly asked for speed over verification
31
+ - Pure information requests ("how does X work?", "what does this code do?")
32
+ - Mechanical operations (renames, formats, file moves)
33
+ - You already have ≥95% confidence; re-read the stop condition below before assuming you don't
34
+
35
+ ## Loading Constraints
36
+
37
+ This skill needs a live, responsive user. **Do not invoke in non-interactive contexts** like CI pipelines, scheduled runs, `/loop`, or autonomous-loop. If you're in one of those and the ask is underspecified, flag that as a blocker for the user instead of guessing.
38
+
39
+ ## The Process
40
+
41
+ ### Step 1: Hypothesize, with a confidence number
42
+
43
+ Before asking anything, write down your current best read of what the user wants in **one sentence**, plus an honest confidence number (0–100%):
44
+
45
+ ```
46
+ HYPOTHESIS: You want a way to answer "how are we doing?" in standup, and "dashboard" was the convention that came to mind.
47
+ CONFIDENCE: ~30% — missing: who it's for, what "metrics" means in context, and what success looks like
48
+ ```
49
+
50
+ The number forces honesty. If you wrote down a high number but can't actually predict the user's reactions to the next three questions you'd ask, the number is wrong. Start at the confidence level you can defend.
51
+
52
+ When confidence is below ~70%, append a brief reason on the same line — what's still unresolved or missing. This tells the user exactly what the interview needs to surface, and prevents the number from being a vague signal.
53
+
54
+ ### Step 2: Ask one question at a time, each with a guess attached
55
+
56
+ Format:
57
+
58
+ ```
59
+ Q: <one focused question>
60
+ GUESS: <your hypothesis for the answer, with the reasoning that produced it>
61
+ ```
62
+
63
+ Wait for the user to react before asking the next question.
64
+
65
+ **Why one at a time, not a batch:**
66
+
67
+ - The user can't react to your hypotheses if you bury them in a list
68
+ - Batches encourage skim-reading and surface answers
69
+ - The third question often depends on the answer to the first; asking them all at once locks in the wrong framing
70
+ - The user's energy for thinking carefully is finite; spend it one question at a time
71
+
72
+ **Why attach a guess:**
73
+
74
+ - The user reacts faster to a wrong guess than they generate an answer from scratch
75
+ - It commits you to a hypothesis you can be visibly wrong about, which keeps you honest
76
+ - It surfaces *your* assumptions, which is what the interview is meant to expose
77
+
78
+ The risk here is a polite user agreeing with your guess to be agreeable. Mitigate by being visibly willing to be wrong, and occasionally guess in a direction you expect the user to push back on.
79
+
80
+ ### Step 3: Listen for "want vs. should want"
81
+
82
+ The most dangerous answers are the ones where the user says what a thoughtful answer *sounds like* rather than what they actually want. Watch for:
83
+
84
+ - Answers that pattern-match best-practice talk ("I want it to be scalable", "clean architecture") without specifics
85
+ - Answers that defer to convention ("the way most apps do it", "the standard approach")
86
+ - Phrases like "I should probably…", "I think I'm supposed to…", "good engineering practice says…"
87
+ - Buzzwords as goals — when "modern", "scalable", "robust" are the answer instead of a specific outcome
88
+
89
+ When you hear these, the question to ask is:
90
+
91
+ > *"If you didn't have to justify this to anyone, what would you actually want?"*
92
+
93
+ That single question often does more work than the previous five.
94
+
95
+ ### Step 4: Restate intent in the user's own words
96
+
97
+ When your confidence is high, write back what you now think the user wants. Keep it tight (5–8 lines), use their language where possible, and structure it so the user can confirm or correct line by line:
98
+
99
+ ```
100
+ Here's what I now think you want:
101
+
102
+ - Outcome: <one line>
103
+ - User: <one line — who benefits>
104
+ - Why now: <one line — what changed>
105
+ - Success: <one line — how we know it worked>
106
+ - Constraint: <one line — the binding limit>
107
+ - Out of scope: <one line — what we're explicitly not doing>
108
+
109
+ Yes / no / refine?
110
+ ```
111
+
112
+ Including "Out of scope" is non-negotiable. Half of misalignment is silent disagreement about what is *not* being built.
113
+
114
+ ### Step 5: Confirm — explicit yes, not "whatever you think"
115
+
116
+ The gate is an explicit "yes." The following are **not** yes:
117
+
118
+ - "Whatever you think is best." → The user is delegating, which means they don't have 95% confidence either. Re-ask with two concrete options framed as a choice.
119
+ - "Sounds good." → Ambiguous. Ask: "Anything you'd refine?" Silence isn't confirmation.
120
+ - "Sure, let's go." → Often a polite exit, not an endorsement. Same follow-up.
121
+ - Silence followed by "okay let's start." → The user has given up on the interview, not converged. Stop and ask whether you've missed something.
122
+
123
+ If they correct you, fold the correction in and restate. Loop until you get an explicit yes.
124
+
125
+ ### The 95% Confidence Stop
126
+
127
+ You're done when you can answer yes to this:
128
+
129
+ > *Can I predict the user's reaction to the next three questions I would ask?*
130
+
131
+ If yes, you have shared understanding. Stop interviewing and produce the restate. If no, you're not done; ask the next question.
132
+
133
+ This is a checkable test, not a vibe. It also has a floor: if you've gone several rounds and still can't predict, that's information about the ask, not a reason to keep grinding. Stop and tell the user: "I've asked X questions and I still can't predict your reactions. Something foundational is missing. Want to step back?"
134
+
135
+ ## Output
136
+
137
+ The output of this skill is a **confirmed statement of intent**: the restate from Step 4, with an explicit yes from Step 5. That's the deliverable. Specs, plans, and task lists are downstream; they consume the intent this skill produces.
138
+
139
+ If the user wants the intent to persist (a multi-session project, a handoff to another collaborator), offer to save it to `docs/intent/[topic].md`. Only save if they confirm.
140
+
141
+ ## Example
142
+
143
+ A short before-and-after.
144
+
145
+ **Without `interview-me`:**
146
+
147
+ ```
148
+ User: build me a dashboard for our metrics
149
+ Agent: <starts proposing chart libraries and layouts>
150
+ ```
151
+
152
+ The agent has assumed: who it's for, what metrics, what "for our team" means, what success looks like. None of these are stated. Every assumption is a place the user can later say "that's not what I meant."
153
+
154
+ **With `interview-me`:**
155
+
156
+ ```
157
+ User: build me a dashboard for our metrics
158
+
159
+ Agent:
160
+ HYPOTHESIS: You want a way to answer "how are we doing?" in standup, and "dashboard" came to mind because that's the conventional answer.
161
+ CONFIDENCE: ~30% — missing: who it's for, what "metrics" are, and what success looks like
162
+
163
+ Q: When you say "how are we doing?", who's asking — you alone, the engineering team in standup, or up the chain (e.g., your manager, an exec, a board)?
164
+ GUESS: engineering team in standup, because "we" usually scopes that way and standups are where this question gets asked. If it's for execs the metrics and the framing change a lot.
165
+
166
+ User: It's actually for me. I keep losing track of which experiments are running and what their early signal looks like.
167
+
168
+ Agent:
169
+ Updated read: not a team dashboard at all. It's a personal experiment tracker. Confidence: ~60% — still missing: what "early signal" means and what done looks like.
170
+
171
+ Q: Is the gap that you don't know which experiments exist, or that you can't see their results in one place?
172
+ GUESS: the second one. You have a list of experiments somewhere, but their results live in five different tools, and reconciling them by hand is what you're tired of.
173
+
174
+ User: First one actually. I literally don't have a list. They're spread across different docs.
175
+
176
+ Agent: <continues>
177
+ ```
178
+
179
+ Two questions in, the agent has discovered the actual ask isn't "a dashboard." It's "a list." Different artifact, different scope, different work. The dashboard would have been wrong.
180
+
181
+ ## Interaction with Other Skills
182
+
183
+ - **`idea-refine`**: downstream. If the confirmed intent is "I want X but I don't know how to scope it," hand off to `idea-refine` to generate variations against the now-explicit intent.
184
+ - **`spec-driven-development`**: downstream. If the confirmed intent is concrete ("I want X for Y users with Z success criteria"), hand off to `spec-driven-development` to write it down.
185
+ - **`planning-and-task-breakdown`**: two hops downstream of this skill (after the spec).
186
+ - **`doubt-driven-development`**: opposite end of the timeline. Interview-me is pre-decision intent extraction; doubt-driven is post-decision artifact review. Both catch divergence, but at different moments.
187
+ - **`source-driven-development`**: orthogonal. Interview-me clarifies what the user wants; SDD verifies framework facts. They don't compete.
188
+
189
+ ## Common Rationalizations
190
+
191
+ | Rationalization | Reality |
192
+ |---|---|
193
+ | "The ask is clear enough" | If you can't write the user's desired outcome in one sentence right now, the ask isn't clear. Run Step 1 before deciding. |
194
+ | "Asking too many questions wastes their time" | Time wasted by 4–6 targeted questions is small. Time wasted by building the wrong thing is enormous, and the user is the one bearing that cost. |
195
+ | "I'll figure it out as I build" | Switching costs after code exists are 10x what they are now. Discovery during implementation is rework. |
196
+ | "They said 'whatever you think,' so I should just decide" | "Whatever you think" is delegation, not decision. Re-ask with two concrete options as a choice. |
197
+ | "I should give them several options to pick from" | Options work when the user knows what they want and is choosing between trade-offs. They don't know what they want yet. Listing options widens the search; asking narrows it. |
198
+ | "If I attach my guess, I'm leading them" | Leading is the point. Reacting is faster than generating from scratch. The risk is sycophancy, not leading; mitigate by being visibly willing to be wrong. |
199
+ | "We've talked enough, I get it" | Test it: can you predict their reaction to the next three questions? If not, you don't get it yet. |
200
+ | "The user said yes, we're done" | If the yes followed a vague restate or an open-ended "sounds good," the yes is hollow. Restate concretely and re-confirm. |
201
+
202
+ ## Red Flags
203
+
204
+ - Three or more questions in a single message: that's batching, not interviewing
205
+ - A question without your hypothesis attached: that's surveying, not committing
206
+ - Accepting "whatever you think is best" as a terminal answer
207
+ - Producing a spec, plan, or task list before the user has explicitly confirmed your restate
208
+ - Questions framed as "what would be best practice?" instead of "what do you actually want?"
209
+ - The user gives a sophistication-signaling answer ("scalable", "clean", "modern") and you accept it without probing whether it's what they actually want
210
+ - Three or more rounds without your confidence visibly rising: you're asking the wrong questions, step back and reframe
211
+ - A confidence number below ~70% with no reason attached: the user can't help close the gap if they don't know what's missing
212
+ - Saving the intent doc before the user has confirmed (the doc itself implies a yes the user didn't give)
213
+ - Skipping the "Out of scope" line in the restate (silent disagreement about non-goals is half of misalignment)
214
+
215
+ ## Verification
216
+
217
+ After applying interview-me:
218
+
219
+ - [ ] An explicit hypothesis with a confidence number was stated in the first turn
220
+ - [ ] Every confidence number below ~70% was accompanied by a one-line reason (what's still unresolved or missing)
221
+ - [ ] Questions were asked one at a time, each with the agent's guess attached
222
+ - [ ] At least one "what would you actually want if you didn't have to justify it?" probe ran when the user gave a sophistication-signaling or convention-signaling answer
223
+ - [ ] A concrete restate (Outcome / User / Why now / Success / Constraint / Out of scope) was written back to the user
224
+ - [ ] The user confirmed the restate with an explicit yes (not "whatever you think," not "sounds good," not silence)
225
+ - [ ] At the stop point, the agent could predict reactions to the next three questions it would ask
226
+ - [ ] Any handoff to a downstream skill (`idea-refine`, `spec-driven-development`) was framed in terms of the confirmed intent, not the original underspecified ask
227
+
228
+ ---
229
+ *Source: addyosmani/agent-skills (MIT). Ported into MaTrixOS shared-skills bundle.*
@@ -0,0 +1,207 @@
1
+ ---
2
+ name: observability-and-instrumentation
3
+ description: Instruments code so production behavior is visible and diagnosable. Use when adding logging, metrics, tracing, or alerting. Use when shipping any feature that runs in production and you need evidence it works. Use when production issues are reported but you can't tell what happened from the available data.
4
+ source: addyosmani/agent-skills (MIT)
5
+ ---
6
+
7
+ # Observability and Instrumentation
8
+
9
+ ## Overview
10
+
11
+ Code you can't observe is code you can't operate. Observability is the ability to answer "what is the system doing and why?" from the outside, using the telemetry the code emits. Instrumentation is not a post-launch add-on — it's written alongside the feature, the same way tests are. If a feature ships without telemetry, the first user-reported bug becomes archaeology instead of a query.
12
+
13
+ ## When to Use
14
+
15
+ - Building any feature that will run in production
16
+ - Adding a new service, endpoint, background job, or external integration
17
+ - A production incident took too long to diagnose ("we couldn't tell what happened")
18
+ - Setting up or reviewing alerting rules
19
+ - Reviewing a PR that adds I/O, retries, queues, or cross-service calls
20
+
21
+ **NOT for:**
22
+ - Diagnosing a failure happening right now — use the `debugging-and-error-recovery` skill (observability is what makes that skill fast next time)
23
+ - Profiling and optimizing measured slowness — use the `performance-optimization` skill
24
+ - Launch-day monitoring checklists and rollback triggers — see the `shipping-and-launch` skill; this skill covers the instrumentation that feeds them
25
+
26
+ ## Process
27
+
28
+ ### 1. Define "working" before instrumenting
29
+
30
+ Telemetry without a question is noise. Before adding any instrumentation, write down 2–4 questions an on-call engineer will ask about this feature:
31
+
32
+ ```
33
+ FEATURE: checkout payment retry
34
+ QUESTIONS ON-CALL WILL ASK:
35
+ 1. What fraction of payments succeed on first attempt vs after retry?
36
+ 2. When a payment fails permanently, why? (provider error? timeout? validation?)
37
+ 3. Is the payment provider slower than usual?
38
+ → Every signal below must help answer one of these.
39
+ ```
40
+
41
+ If you can't name the questions, you're not ready to instrument — you'll log everything and learn nothing.
42
+
43
+ ### 2. Pick the right signal for each question
44
+
45
+ | Signal | Answers | Cost profile | Example |
46
+ |---|---|---|---|
47
+ | **Structured log** | "What happened in this specific case?" | Per-event; grows with traffic | `payment_failed` with provider error code |
48
+ | **Metric** | "How often / how fast, in aggregate?" | Fixed per series; cheap to query | p99 latency of provider calls |
49
+ | **Trace** | "Where did time go across services?" | Per-request; usually sampled | One slow checkout, broken down by hop |
50
+
51
+ Rule of thumb: metrics tell you **that** something is wrong, traces tell you **where**, logs tell you **why**.
52
+
53
+ ### 3. Structured logging
54
+
55
+ Log events, not prose. Every log line is a JSON object with a stable event name and machine-readable fields:
56
+
57
+ ```typescript
58
+ // BAD: string interpolation — unqueryable, inconsistent
59
+ logger.info(`Payment ${id} failed for user ${userId} after ${n} retries`);
60
+
61
+ // GOOD: stable event name + structured fields
62
+ logger.warn({
63
+ event: 'payment_failed',
64
+ paymentId: id,
65
+ provider: 'stripe',
66
+ errorCode: err.code,
67
+ attempt: n,
68
+ }, 'payment failed');
69
+ ```
70
+
71
+ **Log levels — use them consistently:**
72
+
73
+ | Level | Meaning | On-call action |
74
+ |---|---|---|
75
+ | `error` | Invariant broken; someone may need to act | Investigate |
76
+ | `warn` | Degraded but handled (retry succeeded, fallback used) | Watch for trends |
77
+ | `info` | Significant business event (order placed, job finished) | None |
78
+ | `debug` | Diagnostic detail | Off in production by default |
79
+
80
+ **Correlation IDs are mandatory.** Generate (or accept) a request ID at the system boundary and attach it to every log line, span, and outbound call. Without it, you cannot reconstruct a single request from interleaved logs:
81
+
82
+ ```typescript
83
+ // Express: child logger per request, ID propagated downstream
84
+ app.use((req, res, next) => {
85
+ req.id = req.headers['x-request-id'] ?? crypto.randomUUID();
86
+ req.log = logger.child({ requestId: req.id });
87
+ res.setHeader('x-request-id', req.id);
88
+ next();
89
+ });
90
+ ```
91
+
92
+ **Never log secrets, tokens, passwords, or full PII.** This is a hard rule from the `security-and-hardening` skill — telemetry pipelines are a classic data-leak path. Allowlist fields; don't log whole request bodies.
93
+
94
+ ### 4. Metrics
95
+
96
+ For request-driven services, instrument **RED** on every endpoint and every external dependency: **R**ate (requests/sec), **E**rrors (failure rate), **D**uration (latency histogram, not average). For resources (queues, pools, hosts), use **USE**: **U**tilization, **S**aturation, **E**rrors.
97
+
98
+ As with tracing, the vendor-neutral path is the OpenTelemetry metrics API (same SDK and context as step 5). The example below uses Prometheus' `prom-client` — one common backend choice, not the only one; the RED/USE and cardinality rules are identical either way.
99
+
100
+ ```typescript
101
+ import { Histogram } from 'prom-client';
102
+
103
+ const httpDuration = new Histogram({
104
+ name: 'http_request_duration_seconds',
105
+ help: 'HTTP request duration',
106
+ labelNames: ['method', 'route', 'status_class'], // '2xx', not '200'
107
+ buckets: [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
108
+ });
109
+ ```
110
+
111
+ **Cardinality is the failure mode.** Every unique label combination is a separate time series. Labels must come from small, fixed sets (route template, status class, provider name). Never use user IDs, raw URLs, error messages, or other unbounded values as labels — that belongs in logs and traces.
112
+
113
+ ```
114
+ OK as label: route="/api/tasks/:id" status_class="5xx" provider="stripe"
115
+ NEVER a label: user_id, email, request_id, full URL, error message text
116
+ ```
117
+
118
+ Track averages never, percentiles always: an average hides the 1% of users having a terrible time. Use histograms and read p50/p95/p99.
119
+
120
+ ### 5. Distributed tracing
121
+
122
+ Use OpenTelemetry — it's the vendor-neutral standard, and auto-instrumentation covers HTTP, gRPC, and common DB clients with near-zero code:
123
+
124
+ ```typescript
125
+ // tracing.ts — must be imported before anything else
126
+ import { NodeSDK } from '@opentelemetry/sdk-node';
127
+ import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
128
+
129
+ const sdk = new NodeSDK({
130
+ serviceName: 'checkout-service',
131
+ instrumentations: [getNodeAutoInstrumentations()],
132
+ });
133
+ sdk.start();
134
+ ```
135
+
136
+ Add manual spans only around meaningful internal units of work (e.g., `applyDiscounts`, `chargeProvider`) and attach the attributes on-call will filter by. Propagate context across every async boundary — HTTP headers, queue message metadata — or the trace dies at the gap. Sample head-based at a low rate by default; keep 100% of errors if your backend supports tail sampling.
137
+
138
+ ### 6. Alerting
139
+
140
+ Alert on **symptoms users feel**, not on causes:
141
+
142
+ ```
143
+ SYMPTOM (page-worthy): CAUSE (dashboard, not a page):
144
+ error rate > 1% for 5 min CPU at 85%
145
+ p99 latency > 2s one pod restarted
146
+ queue age > 10 min disk at 70%
147
+ ```
148
+
149
+ Cause-based alerts fire when nothing is wrong and miss failures you didn't predict. Symptom-based alerts fire exactly when users are hurt, regardless of the cause.
150
+
151
+ Rules for every alert you create:
152
+
153
+ 1. **It must be actionable.** If the response is "ignore it, it self-heals", delete the alert.
154
+ 2. **It links to a runbook** — even three lines: what it means, first query to run, escalation path.
155
+ 3. **It has a threshold and duration** justified by the SLO or by historical data, not by a guess.
156
+ 4. Use two severities only: **page** (user-facing, act now) and **ticket** (degradation, act this week). A third tier becomes noise that trains people to ignore everything.
157
+
158
+ ### 7. Verify the telemetry itself
159
+
160
+ Instrumentation is code; it can be wrong. Before calling the work done, trigger the paths and look at the actual output:
161
+
162
+ - Force an error in staging → find it in the logs by `requestId`, confirm fields are structured (not `[object Object]`)
163
+ - Send test traffic → confirm metric series appear with the expected labels and sane values
164
+ - Follow one request across services in the tracing UI → no broken spans
165
+ - Fire each new alert once (lower the threshold temporarily) → confirm it reaches the right channel and the runbook link works
166
+
167
+ ## Common Rationalizations
168
+
169
+ | Rationalization | Reality |
170
+ |---|---|
171
+ | "I'll add logging after it works" | "After" becomes "after the first incident", which is the most expensive moment to discover you're blind. Instrument as you build. |
172
+ | "More logs = more observability" | Unstructured noise makes incidents slower, not faster. Three queryable events beat three hundred prose lines. |
173
+ | "console.log is fine for now" | Unstructured output can't be filtered, correlated, or alerted on. The structured logger costs five extra minutes once. |
174
+ | "We can just look at the dashboards when something breaks" | Dashboards built without defined questions show you everything except the answer. Start from on-call questions. |
175
+ | "Alert on everything important, we'll tune later" | A noisy pager trains people to ignore it. The tuning never happens; the missed real page does. |
176
+ | "User ID as a metric label makes debugging easier" | It also makes your metrics backend fall over. High-cardinality lookups belong in logs and traces. |
177
+ | "Tracing is overkill for our two services" | Two services already means cross-service latency questions logs can't answer. Auto-instrumentation makes the cost trivial. |
178
+
179
+ ## Red Flags
180
+
181
+ - A feature PR with retries, queues, or external calls and zero new telemetry
182
+ - Log lines built by string interpolation instead of structured fields
183
+ - No correlation/request ID — each log line is an orphan
184
+ - Metrics labeled with user IDs, raw URLs, or error message text (cardinality bomb)
185
+ - Latency tracked as an average with no percentiles
186
+ - Alerts that fire daily and get acknowledged without action
187
+ - Alerts on causes (CPU, memory) paging humans while user-facing error rate is unmonitored
188
+ - Secrets, tokens, or full request bodies appearing in logs
189
+ - "It works on my machine" as the only evidence a production feature is healthy
190
+
191
+ ## Verification
192
+
193
+ After instrumenting a feature, confirm:
194
+
195
+ - [ ] The on-call questions for this feature are written down, and each signal maps to one
196
+ - [ ] All log output is structured (JSON), with stable event names and a correlation ID on every line
197
+ - [ ] No secrets, tokens, or unredacted PII in any log line (spot-check actual output)
198
+ - [ ] RED metrics exist for every new endpoint and every external dependency, with bounded label sets
199
+ - [ ] Latency is a histogram; p95/p99 are queryable
200
+ - [ ] A single request can be followed end-to-end in the tracing UI without broken spans
201
+ - [ ] Every new alert is symptom-based, has a runbook link, and was test-fired once
202
+ - [ ] An induced failure in staging was located via telemetry alone, without reading the source
203
+
204
+ For the at-a-glance version of this list, including the pre-launch instrumentation gate, see `references/observability-checklist.md`.
205
+
206
+ ---
207
+ *Source: addyosmani/agent-skills (MIT). Ported into MaTrixOS shared-skills bundle.*