@stacknext/cli 0.6.1 → 0.7.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/dist/collector/server.d.ts +3 -1
- package/dist/collector/server.d.ts.map +1 -1
- package/dist/collector/server.js +385 -15
- package/dist/collector/server.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +87 -19
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/diagnose.d.ts.map +1 -1
- package/dist/commands/diagnose.js +36 -3
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/skill.d.ts +34 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +121 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/commands/snapshot.d.ts +36 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +286 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +18 -5
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +4 -0
- package/dist/program.js.map +1 -1
- package/dist/runtime.d.ts +17 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +148 -4
- package/dist/runtime.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -7
- package/skills/stacknext-debugging/SKILL.md +306 -0
- package/skills/stacknext-debugging/references/setup.md +228 -0
- package/skills/stacknext-debugging/references/tools.md +369 -0
- package/skills/stacknext-debugging/references/workflows.md +332 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# Investigation workflows
|
|
2
|
+
|
|
3
|
+
These playbooks assume the StackNext MCP server is connected and the collector
|
|
4
|
+
has data. Always start with `get_project_summary` and stop when the evidence
|
|
5
|
+
answers the user's question. Prefer two or three targeted calls over browsing
|
|
6
|
+
every tool.
|
|
7
|
+
|
|
8
|
+
## Mandatory reasoning rules
|
|
9
|
+
|
|
10
|
+
- Cite a tool result for every runtime claim: route, trace/error/query/finding
|
|
11
|
+
id, span, duration, status or count.
|
|
12
|
+
- A diagnostic finding is a hypothesis. `possible` is not proof and `observed`
|
|
13
|
+
is not a root cause. Verify the referenced evidence before recommending work.
|
|
14
|
+
- Never sum parent and child spans; parent duration includes child work.
|
|
15
|
+
- `null` query duration is unmeasured, never zero.
|
|
16
|
+
- A regression sample is verified only by the injected trace plus a parented
|
|
17
|
+
server span. Never infer a missing sample from time or proximity. An
|
|
18
|
+
`inconclusive` comparison is not a pass, and a result is not statistically
|
|
19
|
+
significant.
|
|
20
|
+
- Do not invent source changes, index recommendations, EXPLAIN output or bind
|
|
21
|
+
parameters. StackNext cannot read source or execute SQL.
|
|
22
|
+
- Read `meta.completeness`, `meta.result`, coverage sample and finding
|
|
23
|
+
limitations. Absence of evidence is not evidence that a feature is broken.
|
|
24
|
+
|
|
25
|
+
## Workflow A: runtime error
|
|
26
|
+
|
|
27
|
+
**Question:** Why did this route fail, and where in the request did it happen?
|
|
28
|
+
|
|
29
|
+
1. `get_project_summary`
|
|
30
|
+
- Confirm `summary.errorCount > 0`.
|
|
31
|
+
- Note `firstEventTime`/`lastEventTime` so you do not search outside the
|
|
32
|
+
retention window.
|
|
33
|
+
2. `list_errors` with the narrowest filter you have:
|
|
34
|
+
- known route: `{ "route": "/api/error" }`
|
|
35
|
+
- known error name: `{ "name": "Error" }`
|
|
36
|
+
- free text: `{ "q": "database is locked" }`
|
|
37
|
+
3. Pick the most recent relevant error and call `get_error` with its `id`.
|
|
38
|
+
Read:
|
|
39
|
+
- `error.message` and `error.stack` (already redacted)
|
|
40
|
+
- `error.route`, `error.method`, `error.requestPath`
|
|
41
|
+
- `error.resolvedTraceId`
|
|
42
|
+
4. If `resolvedTraceId` exists, call `get_trace`:
|
|
43
|
+
- Find spans with `status: "error"` and read `statusMessage`.
|
|
44
|
+
- Check whether a database query in the same trace has `success: false`.
|
|
45
|
+
- Check `missingParentSpanIds` before claiming the timeline is complete.
|
|
46
|
+
5. If the error is uncorrelated, say so. Use the error timestamp and route to
|
|
47
|
+
find nearby requests with `list_requests`, but label that as a time-based
|
|
48
|
+
inference, not an exact correlation.
|
|
49
|
+
|
|
50
|
+
**Evidence to report:** error id, message, route, stack frame, failing span or
|
|
51
|
+
query, trace id, and whether the correlation was exact or fallback.
|
|
52
|
+
|
|
53
|
+
**Do not:** paste an entire stack when one frame explains the failure; call
|
|
54
|
+
`get_error` repeatedly for the same id; claim a root cause from a message alone.
|
|
55
|
+
|
|
56
|
+
## Workflow B: slow request
|
|
57
|
+
|
|
58
|
+
**Question:** Which request is slow, and what consumed the time?
|
|
59
|
+
|
|
60
|
+
1. `get_project_summary`
|
|
61
|
+
- Record `summary.p95DurationMs`, `summary.avgDurationMs`, and the slow
|
|
62
|
+
threshold configured for the project.
|
|
63
|
+
2. `find_slow_requests` with `{ "minDurationMs": 500, "limit": 10 }` (adjust the
|
|
64
|
+
threshold to the user's definition of slow).
|
|
65
|
+
3. Choose the request that matches the reported route or the worst duration and
|
|
66
|
+
call `get_request`.
|
|
67
|
+
4. Build a time budget from the trace:
|
|
68
|
+
- `durationMs` is the request total.
|
|
69
|
+
- Sort spans by `durationMs`; inspect the top three.
|
|
70
|
+
- Identify route/render spans, fetch spans and database queries.
|
|
71
|
+
- Check for gaps between parent and child spans. A gap can indicate work that
|
|
72
|
+
Next.js did not instrument; say that instead of inventing a cause.
|
|
73
|
+
5. Test whether the pattern repeats:
|
|
74
|
+
- `list_requests` with `{ "q": "/api/slow", "sort": "slowest" }`
|
|
75
|
+
- or `{ "method": "GET", "minDurationMs": 300 }`
|
|
76
|
+
6. If database queries are inside the trace, read their `durationMs`. If they
|
|
77
|
+
are `null` (Drizzle), report database time as unmeasured.
|
|
78
|
+
|
|
79
|
+
**Evidence to report:** trace id, total duration, longest span name and duration,
|
|
80
|
+
query count, whether the slowdown is isolated or repeated, and any unmeasured
|
|
81
|
+
regions.
|
|
82
|
+
|
|
83
|
+
**Do not:** add span durations together as if they were sequential; a parent span
|
|
84
|
+
already contains its children. Compare self time or use the waterfall order.
|
|
85
|
+
|
|
86
|
+
## Workflow C: database investigation
|
|
87
|
+
|
|
88
|
+
**Question:** What SQL ran, did it fail, and which request did it belong to?
|
|
89
|
+
|
|
90
|
+
1. `get_project_summary`
|
|
91
|
+
- Confirm `summary.databaseQueryCount > 0`. If zero, check that the adapter is
|
|
92
|
+
registered and that the app is connected.
|
|
93
|
+
2. `list_database_queries` with one of:
|
|
94
|
+
- `{ "traceId": "<32 hex>" }` for a known request
|
|
95
|
+
- `{ "q": "orders" }` for a table or SQL fragment
|
|
96
|
+
- `{ "databaseSystem": "sqlite" }` for one adapter
|
|
97
|
+
- `{ "minDurationMs": 100 }` when durations are measured
|
|
98
|
+
3. Inspect `success`, `errorMessage`, `source`, `operation` and
|
|
99
|
+
`resolvedTraceId`. Remember:
|
|
100
|
+
- Drizzle durations are always `null`.
|
|
101
|
+
- Prisma durations are reported by Prisma, not measured by StackNext.
|
|
102
|
+
- SQL bind parameters are never captured.
|
|
103
|
+
4. For a failed query, call `get_request` on `resolvedTraceId` and inspect the
|
|
104
|
+
surrounding spans.
|
|
105
|
+
5. For a suspected N+1 pattern, compare query counts across several similar
|
|
106
|
+
requests with `list_requests`, then open the worst trace.
|
|
107
|
+
|
|
108
|
+
**Evidence to report:** redacted SQL shape, source, success state, measured
|
|
109
|
+
duration or `null`, trace id, and the route.
|
|
110
|
+
|
|
111
|
+
**Do not:** compare Drizzle and Prisma durations; claim a query is slow when its
|
|
112
|
+
duration is `null`; attempt to reconstruct bind parameters.
|
|
113
|
+
|
|
114
|
+
## Workflow D: general runtime investigation
|
|
115
|
+
|
|
116
|
+
**Question:** What is happening in this app right now?
|
|
117
|
+
|
|
118
|
+
1. `get_project_summary`
|
|
119
|
+
- Read counts, failed/slow request counts, p95, recent errors and the event
|
|
120
|
+
time range.
|
|
121
|
+
- Read `coverage` and `meta.coverage`: note `not-observed`, `unknown` and
|
|
122
|
+
`unsupported` items before assuming a runtime problem.
|
|
123
|
+
2. `list_requests` with `{ "sort": "recent", "limit": 20 }`.
|
|
124
|
+
3. `list_requests` with `{ "sort": "slowest", "limit": 10 }`.
|
|
125
|
+
4. `list_errors` with `{ "limit": 10 }`.
|
|
126
|
+
5. `list_database_queries` with `{ "limit": 10 }`.
|
|
127
|
+
6. Pick one representative request or trace and call `get_request`/`get_trace`.
|
|
128
|
+
7. Summarize at most three findings, each with evidence. If everything is
|
|
129
|
+
healthy, say so and cite the counts and latency.
|
|
130
|
+
|
|
131
|
+
**Stop condition:** you can answer the user's question with named routes,
|
|
132
|
+
identifiers and measurements. Do not keep listing after that.
|
|
133
|
+
|
|
134
|
+
## Workflow E: diagnostic findings
|
|
135
|
+
|
|
136
|
+
**Question:** What deterministic problems does StackNext see in this sample, and
|
|
137
|
+
which one is supported by evidence?
|
|
138
|
+
|
|
139
|
+
1. `get_project_summary`
|
|
140
|
+
- Confirm the app is connected and note the retention window.
|
|
141
|
+
- Read `summary.errorCount`, `slowRequests` and `coverage`.
|
|
142
|
+
2. `stacknext_list_diagnostics`
|
|
143
|
+
- Start broad, then narrow with `category`, `severity`, `status`, `ruleId`,
|
|
144
|
+
`route`, `traceId`, `since`, `until` or `q`.
|
|
145
|
+
- Read `total`, `counts`, `sample`, `notes` and `limitations`.
|
|
146
|
+
3. Select one finding and call `stacknext_get_diagnostic` with its id.
|
|
147
|
+
- Read `finding.status`, `severity`, `affectedTraceCount`, `fingerprint`,
|
|
148
|
+
`evidence`, `verification` and `limitations`.
|
|
149
|
+
- Note the related `trace.traceId` and whether the trace is bounded.
|
|
150
|
+
4. Verify by rule:
|
|
151
|
+
- **n-plus-one-queries:** count matching queries per trace and inspect the
|
|
152
|
+
normalized SQL shape. Findings aggregate by canonical route; confirm whether
|
|
153
|
+
the count tracks a list size. StackNext cannot prove the calling code is a
|
|
154
|
+
loop.
|
|
155
|
+
- **slow-request:** inspect the request duration distribution and self-time
|
|
156
|
+
contributors. Self time attributes measured work; it is not proof of cause.
|
|
157
|
+
- **slow-span:** inspect the span self time, inclusive duration and Next.js
|
|
158
|
+
phase. Slow-span findings are suppressed when the request itself is slow.
|
|
159
|
+
Check children, queueing and cold starts; do not add overlapping spans.
|
|
160
|
+
- **repeated-external-http:** inspect the endpoint shape and per-trace
|
|
161
|
+
occurrence counts. Determine whether calls are independent, retries or a
|
|
162
|
+
missing cache; query values are absent.
|
|
163
|
+
- **error-fingerprint:** inspect the latest error, Next.js context and deepest
|
|
164
|
+
error span. Findings group by canonical route and can merge different
|
|
165
|
+
causes. Not-found and redirect control-flow errors are excluded.
|
|
166
|
+
- **server-error-response:** the request returned 5xx without a correlated
|
|
167
|
+
non-control-flow error record. The status is observed; the cause is unknown.
|
|
168
|
+
5. If the related trace is truncated, call `get_trace` for the full tree. If the
|
|
169
|
+
finding has no trace, say the evidence aged out or was never correlated.
|
|
170
|
+
6. Report the finding id/rule/status, the evidence checked, what remains
|
|
171
|
+
unproven and one concrete next step. Do not call the finding a root cause.
|
|
172
|
+
|
|
173
|
+
**Stop condition:** one verified finding, or an explicit statement that the
|
|
174
|
+
sample has no finding that explains the symptom.
|
|
175
|
+
|
|
176
|
+
## Workflow F: runtime regression evidence
|
|
177
|
+
|
|
178
|
+
**Question:** Did a Playwright-covered flow improve, regress, stay unchanged or
|
|
179
|
+
remain inconclusive compared with its baseline?
|
|
180
|
+
|
|
181
|
+
1. `get_project_summary`
|
|
182
|
+
- Confirm the collector state and project name.
|
|
183
|
+
- Remember that regression records are local files under `.stacknext`, not
|
|
184
|
+
retention-window telemetry. An empty telemetry store is not evidence that
|
|
185
|
+
they are missing.
|
|
186
|
+
2. `stacknext_list_test_runs` with `{ "limit": 10 }`
|
|
187
|
+
- Identify the candidate run by name, project, time and `status`.
|
|
188
|
+
- Use `stacknext_get_test_run` for the chosen `runId`.
|
|
189
|
+
3. Read the run evidence:
|
|
190
|
+
- `status` must be `completed` for a normal candidate; any other status makes
|
|
191
|
+
the comparison inconclusive.
|
|
192
|
+
- `stats.verifiedSamples` versus `stats.incompleteSamples`.
|
|
193
|
+
- Each sample's `correlation.status` and `reasons`. A sample is verified only
|
|
194
|
+
when the collector found the injected trace and a server span parented to
|
|
195
|
+
the injected span id.
|
|
196
|
+
- `warnings`, `notes` and `limitations`, especially collector disconnects,
|
|
197
|
+
capped evidence and cold route-module spans.
|
|
198
|
+
4. `stacknext_list_baselines` and `stacknext_get_baseline`
|
|
199
|
+
- Confirm `sourceRunId` and that the baseline contains the same
|
|
200
|
+
`scenarioId` values. An annotation change creates a new scenario with no
|
|
201
|
+
baseline.
|
|
202
|
+
5. `stacknext_list_comparisons` and `stacknext_get_comparison`
|
|
203
|
+
- Read `environment.compatible` and `environment.differences` first,
|
|
204
|
+
including `diagnostics.ruleSetVersion`. Different or unknown rule-set
|
|
205
|
+
versions make captured findings incomparable and the comparison
|
|
206
|
+
inconclusive.
|
|
207
|
+
- Read top-level `status` and `severity`, then `summary`, then each scenario's
|
|
208
|
+
`status`, `severity` and `reasons`.
|
|
209
|
+
- Inspect regressed or inconclusive metrics: `baselineValue`,
|
|
210
|
+
`candidateValue`, `delta`, `percent`, `sampleCount`, `note` and
|
|
211
|
+
`unmeasured`.
|
|
212
|
+
- Check both sides' sample counts. Fewer than `minSamples` verified samples
|
|
213
|
+
or any incomplete sample blocks a verdict.
|
|
214
|
+
6. Explain the result:
|
|
215
|
+
- `regressed` means the measured median crossed the configured threshold in
|
|
216
|
+
this sample. It does not identify the cause.
|
|
217
|
+
- `improved` is not automatically a success; confirm the behavior is still
|
|
218
|
+
present and instrumented.
|
|
219
|
+
- `unchanged` means no configured threshold was crossed in this sample, not
|
|
220
|
+
that nothing changed.
|
|
221
|
+
- `inconclusive` means fix the evidence (environment, samples, warm-up,
|
|
222
|
+
correlation), not the app.
|
|
223
|
+
- Never call a result statistically significant. Severity is separate from
|
|
224
|
+
status.
|
|
225
|
+
7. If no record exists, say so. The MCP tools cannot capture, save, compare,
|
|
226
|
+
delete or edit. Point the user to `stacknext capture`,
|
|
227
|
+
`stacknext baseline save` and `stacknext compare`; do not run those commands
|
|
228
|
+
without being asked and never synthesize a comparison.
|
|
229
|
+
|
|
230
|
+
**Evidence to report:** comparison id, baseline id, candidate run id,
|
|
231
|
+
top-level status/severity, environment compatibility, per-scenario verified
|
|
232
|
+
sample counts, the decisive reasons/metrics, and what remains unproven.
|
|
233
|
+
|
|
234
|
+
**Do not:** treat `inconclusive` as a pass; compare different environments as if
|
|
235
|
+
they were equivalent; use trace/span ids or timestamps as matching keys; call a
|
|
236
|
+
regressed metric a root cause.
|
|
237
|
+
|
|
238
|
+
## Workflow G: saved snapshot evidence
|
|
239
|
+
|
|
240
|
+
**Question:** What does a saved snapshot show, and is it still relevant to the
|
|
241
|
+
current app?
|
|
242
|
+
|
|
243
|
+
1. `stacknext_list_snapshots` with `{ "limit": 20 }`
|
|
244
|
+
- Identify the snapshot by `label`, `source`, `createdAt` and `sample`.
|
|
245
|
+
- `manual` and `import` snapshots never rotate; `exit` and `error` snapshots
|
|
246
|
+
keep the newest ten by default.
|
|
247
|
+
- `invalid > 0` means some summary files are unreadable and were left in
|
|
248
|
+
place. Do not repair or delete them.
|
|
249
|
+
2. `stacknext_get_snapshot` with the `snapshotId`
|
|
250
|
+
- Read `snapshot.sample`, `snapshot.stats`, captured `config`,
|
|
251
|
+
`limitations`, and the first traces/errors/queries.
|
|
252
|
+
- Confirm the snapshot contains the route or error the user asked about.
|
|
253
|
+
3. `stacknext_get_snapshot_trace` with `snapshotId` and `traceId`
|
|
254
|
+
- Inspect spans, errors and queries inside that frozen trace.
|
|
255
|
+
- The response has no `diagnostics`; do not invent finding references.
|
|
256
|
+
4. Decide whether the snapshot can answer the question:
|
|
257
|
+
- It can describe what happened at save time.
|
|
258
|
+
- It cannot describe current app behavior, current config or current
|
|
259
|
+
instrumentation coverage.
|
|
260
|
+
- If the user needs current behavior, inspect the live sample and say that
|
|
261
|
+
the snapshot was used only for historical comparison.
|
|
262
|
+
5. If no snapshot exists, say so. The MCP tools cannot save, import, rotate or
|
|
263
|
+
delete one. Point the user to `stacknext snapshot save` or the dashboard
|
|
264
|
+
`/snapshots` page and do not create a file yourself.
|
|
265
|
+
|
|
266
|
+
**Evidence to report:** snapshot id, source, save time, sample window, the
|
|
267
|
+
scoped trace/error/query ids inspected, and the explicit caveat that the data is
|
|
268
|
+
frozen rather than live.
|
|
269
|
+
|
|
270
|
+
**Do not:** replay a snapshot into the live store; treat snapshot diagnostics or
|
|
271
|
+
coverage as present; compare snapshot medians as if they were a regression
|
|
272
|
+
comparison; call a snapshot finding a current root cause.
|
|
273
|
+
|
|
274
|
+
| Observation | Likely meaning | Next action |
|
|
275
|
+
| --- | --- | --- |
|
|
276
|
+
| Collector unreachable | `stacknext dev` is stopped or the runtime file is stale | Ask the user to start it; do not guess |
|
|
277
|
+
| `connection.instrumentation: "waiting"` | Collector is up, app is not connected | Start the app through `stacknext dev`, make a request |
|
|
278
|
+
| `total: 0` for a filter | No match in the current retention window | Broaden the filter or check the time range |
|
|
279
|
+
| `meta.completeness.reasons` mentions drops | Capacity/retention dropped data | Report the gap; export or raise limits if needed |
|
|
280
|
+
| `missingParentSpanIds` is non-empty | Spans arrived late or were dropped | Report an incomplete timeline |
|
|
281
|
+
| Query `durationMs: null` | Adapter cannot measure duration | Report unmeasured, not zero |
|
|
282
|
+
| Error has no `resolvedTraceId` | No span context and fallback found no match | Use time/route inference and label it |
|
|
283
|
+
| Coverage item is `not-observed` | The sample did not exercise the feature, or it is disabled | Check limitations and sample window; ask for a request that uses it |
|
|
284
|
+
| Coverage item is `unknown` | Config/evidence cannot determine the state | Report the uncertainty; do not call it a failure |
|
|
285
|
+
| Coverage item is `unsupported` | Intentional StackNext boundary | Explain the boundary and the documented alternative, if any |
|
|
286
|
+
| Run `status` is `failed`, `interrupted` or `incomplete` | Candidate telemetry is incomplete | Report it; the comparison is inconclusive |
|
|
287
|
+
| Sample `correlation.status` is `incomplete` | Trace not found, injected parent missing or no request trace | Do not guess from time; re-capture the scenario |
|
|
288
|
+
| Comparison is `inconclusive` | Environment mismatch, missing/incomplete samples, structural change | Fix the evidence; it is not a pass |
|
|
289
|
+
| Scenario has no baseline | Annotation changed or scenario is new | Re-baseline the intended scenario |
|
|
290
|
+
| Query metric is `unmeasured` | Drizzle duration is null | Report unmeasured, never zero |
|
|
291
|
+
| No snapshots listed | No manual/exit/error snapshot has been saved for this project directory | Save one with `stacknext snapshot save` or the dashboard |
|
|
292
|
+
| Snapshot `invalid` is greater than 0 | Unreadable summary files were left on disk | Report them; do not repair or delete automatically |
|
|
293
|
+
| Snapshot has no diagnostics | Diagnostics are intentionally not stored | Inspect the live sample if a finding is needed |
|
|
294
|
+
| Snapshot trace is missing | The trace id is wrong or not in that snapshot | Use `stacknext_get_snapshot` to list its traces |
|
|
295
|
+
| Snapshot sample is old | It is frozen evidence from save time | State the save time; check the live sample for current behavior |
|
|
296
|
+
|
|
297
|
+
## Report template
|
|
298
|
+
|
|
299
|
+
```text
|
|
300
|
+
Finding
|
|
301
|
+
<one sentence answering the question>
|
|
302
|
+
|
|
303
|
+
Evidence
|
|
304
|
+
- tool: <tool name>
|
|
305
|
+
- route: <route or "unknown">
|
|
306
|
+
- trace/error id: <id or "none">
|
|
307
|
+
- measurement: <duration, status, count, or SQL shape>
|
|
308
|
+
|
|
309
|
+
Correlation
|
|
310
|
+
exact span context | route+time fallback | unknown
|
|
311
|
+
|
|
312
|
+
Completeness
|
|
313
|
+
<pagination, drops, missing parents, null durations, verified/incomplete
|
|
314
|
+
samples, or "complete">
|
|
315
|
+
|
|
316
|
+
Regression
|
|
317
|
+
<status/severity, environment compatibility and verified sample counts, or
|
|
318
|
+
"not relevant">
|
|
319
|
+
|
|
320
|
+
Snapshot
|
|
321
|
+
<snapshot id, source, save time and sample window, or "live sample">
|
|
322
|
+
|
|
323
|
+
Unproven
|
|
324
|
+
<what the evidence cannot establish>
|
|
325
|
+
|
|
326
|
+
Recommended next step
|
|
327
|
+
<one concrete action, or "none">
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Keep the report shorter than the evidence you inspected. If the user asks for a
|
|
331
|
+
fix, propose the smallest code change that addresses the proven failure, and say
|
|
332
|
+
which evidence supports it.
|