| name | lopi-learn |
| description | Capture lessons from an incident or debugging session as a structured intel YAML under tools/lopi/intel/. Operator-triggered after a problem that was harder to resolve than it should have been. |
/lopi-learn
After resolving a problem, capture a durable lesson so the next agent (or human) hitting the same symptoms finds the answer in one search. Intel is consumed at recall time on a search hit, so every byte costs context — keep entries lean and recall-focused.
Step 0 — Scan the session
Before classifying anything, extract from the conversation:
- Symptoms — what the operator observed, what errors appeared, what commands returned
- Diagnostic path — what was tried, what didn't work, what lopi reported vs. reality
- Resolution — the command, config change, or action that fixed it
Everything below is anchored in that scan. Don't ask the operator to re-explain — they triggered /lopi-learn because the session already has the signal.
Pre-flight
1. Classify
Pick a type using the conversation signal column:
| Type | Description | Signal in the session |
|---|
missing-check | lopi should have surfaced this automatically | lopi troubleshoot returned all-clear but the problem existed |
blind-spot | lopi had no visibility into the component | Needed raw docker logs / journalctl / SSH to find the issue |
missing-command | Diagnosis required a sequence lopi doesn't wrap | Raw shell commands lopi doesn't expose were used to diagnose or fix |
wrong-diagnosis | lopi pointed at the wrong thing | Operator corrected lopi's output mid-session |
insufficient-context | lopi couldn't correlate clues across sources | Multiple back-and-forth attempts before the pattern was visible |
missing-env-knowledge | Host/runtime config was the issue | .env or host config was inspected manually after lopi env |
2. Severity
critical — data loss, safety risk, or complete system failure
high — service down, mission-blocking, requires immediate manual intervention
medium — degraded functionality, workaround exists but wastes time
low — minor inconvenience, cosmetic, or rare edge case
3. Deduplicate
lopi intel search <keywords> --json --include-fixed. If a match exists, don't create a new file — append a sighting with lopi intel encounter <slug> --context "...". Stop here.
The retrospective (5 questions)
Answer from the session you just lived through — don't ask the operator. The operator's input comes at the review step below.
-
Could a check have caught this automatically? (lead with this — the win is making the gotcha auto-detectable, not just documented)
→ fills gap (prose, what was missing) and suggested_improvements (concrete proposals). Consider, in order of cheapness:
- Log line — would a single new log line have surfaced the cause? (cheapest, broadest)
- Healthcheck / liveness probe — would a probe have flipped a service to unhealthy?
- Metric — would a counter/gauge + threshold have alerted before the operator noticed?
lopi troubleshoot check — should the tool catch this on its next run?
- Test — would a unit/integration test have prevented the regression?
- Dashboard / alert — only if the others don't fit and visibility is the gap
Skip any axis that doesn't apply. Don't write filler. Name files/paths where the change should land when you can.
-
How would the agent recognize this next time?
→ fills symptoms (3–5 short bullet strings, the things you'd grep logs for) and trigger (one line: when does it occur).
-
What single check confirms it?
→ fills confirming_check (one command or short pipeline; the smoking gun).
-
What's the fix?
→ fills fix (prose, 1–3 sentences) and resolution_commands (the commands to run).
-
Is there a fix commit?
→ fills fix_commit (optional). Presence of a non-empty fix_commit is what marks intel as fixed — there is no separate status field. If a fix lands later, use lopi intel resolve <slug> --commit <sha>.
Draft
Target path: tools/lopi/intel/<slug>.yaml. Slug is lowercase-hyphenated and must match the filename.
slug: my-issue-slug
title: One-line summary
type: missing-check
severity: high
hit_count: 1
symptoms:
- "Service A logs 'connection refused' on startup"
- "docker compose ps shows B is restarting"
trigger: "Cold start when B not yet ready"
confirming_check: |
docker compose ps | grep service-b | grep -i restarting
fix: |
Restart with healthcheck dependency, or wait for B before A starts.
resolution_commands:
- "docker compose up -d --wait"
gap: |
No log identifies which dependency failed. Adding the target endpoint
to the connect-retry log would make this 30s to diagnose.
suggested_improvements:
- "Log retry target URL in connect-retry loop (src/client.rs)"
- "Add lopi troubleshoot dependencies check"
encounters:
- date: "YYYY-MM-DD"
context: "What was specific about this hit (env, version, host)."
Confirm → Sanitize → Write → Validate
-
Show the draft to the user.
-
Sanitize. Strip and replace:
- IP addresses →
<ip>
- Passwords, tokens, API keys →
<redacted>
- Internal hostnames or FQDNs →
<hostname>
- Internal URLs and ports tied to a single deployment →
<url>
- Personal names → role names (e.g.
the operator)
Intel must be generic enough for anyone on the team.
-
Write the file.
-
Run lopi intel validate tools/lopi/intel/<slug>.yaml. Fix any reported errors and re-validate.
-
Tell the user to review the diff and commit. Never git commit yourself.
Follow-up
If the suggested_improvements point at concrete code changes (un-stubbing a module, adding a check, adding a log), surface them to the user as a separate suggestion — but don't implement in the same turn.