Shikanime Org Investigation
One discipline, stated plainly: never propose a change you cannot explain.
Research the defect's origin, prove it with a command, form a hypothesis, and
propose the solution — then hand the actual change to the fix skills. This
skill consolidates the org's debugging practice — the four-phase root-cause
cycle, isolated repro, and component-attribution fan-out — into a single
critical method, and flags where each step is commonly misapplied.
When to Use
- A test fails, build breaks, prod misbehaves, or behavior is unexpected.
- "Why does X fail" / "trace this error" / "something regressed".
- Especially under time pressure — guessing then is the most expensive path.
Iron Law
THIS SKILL RESEARCHES AND PROPOSES. IT NEVER APPLIES A FIX.
The deliverable is a root-cause finding plus a proposed solution, recorded in
the linked issue's comments (issue-first). Containment that stops active damage
is a separate, explicitly-labeled act owned by the fix skills — never folded
silently into an investigation. Hand off the change to sks-issue /
sks-dev-workflow / sks-pr once the proposal is approved.
The cycle is a fiction you keep anyway
The four phases — understand, isolate, hypothesize, propose — are taught in
order but never run in order. You oscillate: a hypothesis reveals you
misunderstood, so you re-understand; isolation surfaces a new theory. Hold the
phases as a checklist, not a pipeline. The only non-negotiable ordering: you
cannot declare a root cause before you have reproduced the failure on demand.
1. Understand — observed vs expected, then reproduce
- State the contract: what should happen, what does, and the smallest delta
between them.
- Reproduce consistently with the exact command (
pytest -q tests/test_x.py::t,
the precise build invocation). A bug you cannot reproduce on demand cannot be
explained, only guessed at — and a guess is not a finding.
- Read the whole error: stack trace, line, exit status, the frames in order.
Skimming the first line and guessing is the primary cause of wrong
conclusions.
2. Isolate — the smallest unit that still fails
Two distinct moves; pick by what you suspect:
- History bisection when a previously-working thing broke:
jj bisect /
git bisect to pin the introducing change; jj log -p -S <symbol> to watch a
symbol evolve. Most "regressions" are dependency or config, not code — bisect
the lockfile and the flag, not just the source.
- Boundary logging in multi-component systems (API → service → DB): add one
log line per boundary to learn where it breaks, then investigate only that
component. Do not debug all components at once.
Critique: isolation is where people rush. "I'll just read the code" skips the
step that would have shown the failure is in the network layer, not the handler.
3. Hypothesize — one theory, tested minimally
- One theory at a time: "X because Y." Test it by changing exactly one variable
in an isolated repro or spike — never in the production change. Confirmed →
you have the root cause. Not → new theory; never stack fixes.
- Rule of three: three failed theories → STOP. The architecture, not the code,
is the suspect. Talk to the user.
- Do not fan out parallel hypotheses. The defect is singular; dispatching
agents to test competing theories of the same component wastes cycles and
produces contradictory evidence. Fan-out is only correct for attribution —
when you know it fails somewhere across independent components and must learn
which one (see Multi-component).
4. Propose — root cause plus a concrete solution
- Write the finding: the root cause, the hypothesis that explains it, and the
evidence (the repro that proves it).
- Propose the solution as a concrete plan: the single change at the source where
all callers route through (not a guard in every caller), sketched as a diff or
PR description. Note the regression test that would lock it shut.
- Pass the proposal through the
ponytail ladder (laziest fix that works). When
the root cause traces to over-engineering — speculative abstraction, dead
flexibility, reinvented stdlib — run ponytail-review (diff) or
ponytail-audit (whole repo) on the failing component; its ranked
delete/simplify list doubles as the fix plan.
- Record it in the linked issue. The proposal is verified when the repro
confirms the theory and the proposed change addresses the source — not when
code is merged. Hand off the application.
Per-language minimal repro
Strip the surrounding app; keep only what manifests the failure. A small repro
beats a long stack trace.
- TypeScript: reproduce in the playground with only the types + the failing
expression. Surface the type with
satisfies / as const; let strict tell
you where narrowing breaks. Assert the expected inference with // ^? or
expectTypeOf from the test runner — the check fails loudly when the type
drifts. Bisect config/version, not code: toggle strict flags one at a time;
the failing flag is the clue.
- Python: reduce to a standalone module importing only the failing path;
assert the observed vs expected at the boundary.
- Build/CI: reproduce with the exact failing command locally (same
node/python version); most "CI-only" failures are version or cache drift, not
logic.
Critique: a unit repro cannot surface concurrency, load, or integration-only
defects. If the failure only appears under real traffic, a minimal repro is the
wrong tool — capture the live trace and isolate from there.
Multi-component attribution
For a system with several moving parts, dispatch one delegate_task per
component boundary (carrying the Phase-1 contract: observed vs expected, the
exact failure) and converge on the failing component. Same isolation discipline
as the parallel-implementation skills, applied to a trace instead of parallel
work. Stop fanning out the moment one component is implicated — then switch to
single-threaded hypothesis testing inside it.
Known cycles (reuse before re-deriving)
Recurring patterns from past investigations — recognize the signature, then
propose the known resolution; do not re-debug from zero:
- Verify-after-write. Any file edit can report success without landing on
disk (large file, many prior edits, fuzzy match). Read back and assert the new
string is present; if absent, rewrite via an explicit replace with a verify
read-back.
- Split layers first. When a multi-component system fails, separate host
reachability from pod/workload reachability; read the earliest fatal log —
later failures are downstream symptoms of the first. Don't reset a system
because an add-on retried on a separate fault.
- Eager-import resolution. A module-load resolve failure means runtime
depends on package resolution too early. Fix with explicit workspace deps +
lazy dynamic import from a fixed allowlist, not install flags or concurrency
tweaks.
- E2E race selectors. A row click before data arrives hits a placeholder,
then "element not found" on the detail heading. Wait for a stable data row and
visibility before clicking; keep the fix scoped to the shared root cause.
Pitfalls
- Exit code 137 (OOM) looks like a build error but is a resource ceiling — raise
NODE_OPTIONS=--max-old-space-size=4096, not a code change.
- "Simple" bugs have root causes too; the process is fast for them, so skipping
it buys nothing.
- Trusting a doc's claim about the code without verifying it is how drift ships.
- A symptom patch worn as a root-cause finding is the most expensive mistake: it
hides the real defect and makes the next failure harder.
- Parallel hypothesis testing of one component is not diligence — it is thrash.
- Applying the fix inside an investigation breaks the issue-first handoff and
leaves no reviewable proposal.
Verification
echo "investigation complete: root cause + hypothesis + proposed fix" \
"recorded in the linked issue"
# proof = the exact repro command that demonstrates the failure on demand
See also
sks-pr-review — the review gate enforces the same root-cause discipline on
incoming PRs.
sks-async — the isolation pattern, for parallel implementation rather than
parallel debugging.
sks-stack — canonical single-workspace isolation recipe before a fix.
ponytail-audit — when the defect's root cause is accidental complexity, its
ranked simplification list seeds the proposal.
sks-issue / sks-dev-workflow / sks-pr — receive the proposed solution
and apply it as a reviewed change.
1---2name: sks-investigate3description: Use when investigating a bug, test failure, build break, or unexpected behavior in a shikanime repo — find root cause, form a hypothesis, and propose a solution, never apply the fix itself.4license: Apache-2.05---67# Shikanime Org Investigation89One discipline, stated plainly: never propose a change you cannot explain.10Research the defect's origin, prove it with a command, form a hypothesis, and11_propose_ the solution — then hand the actual change to the fix skills. This12skill consolidates the org's debugging practice — the four-phase root-cause13cycle, isolated repro, and component-attribution fan-out — into a single14critical method, and flags where each step is commonly misapplied.1516## When to Use1718- A test fails, build breaks, prod misbehaves, or behavior is unexpected.19- "Why does X fail" / "trace this error" / "something regressed".20- Especially under time pressure — guessing then is the most expensive path.2122## Iron Law2324```text25THIS SKILL RESEARCHES AND PROPOSES. IT NEVER APPLIES A FIX.26```2728The deliverable is a root-cause finding plus a proposed solution, recorded in29the linked issue's comments (issue-first). Containment that stops active damage30is a separate, explicitly-labeled act owned by the fix skills — never folded31silently into an investigation. Hand off the change to `sks-issue` /32`sks-dev-workflow` / `sks-pr` once the proposal is approved.3334## The cycle is a fiction you keep anyway3536The four phases — understand, isolate, hypothesize, propose — are taught in37order but never run in order. You oscillate: a hypothesis reveals you38misunderstood, so you re-understand; isolation surfaces a new theory. Hold the39phases as a checklist, not a pipeline. The only non-negotiable ordering: you40cannot declare a root cause before you have reproduced the failure on demand.4142### 1. Understand — observed vs expected, then reproduce4344- State the contract: what should happen, what does, and the smallest delta45 between them.46- Reproduce consistently with the exact command (`pytest -q tests/test_x.py::t`,47 the precise build invocation). A bug you cannot reproduce on demand cannot be48 explained, only guessed at — and a guess is not a finding.49- Read the whole error: stack trace, line, exit status, the frames in order.50 Skimming the first line and guessing is the primary cause of wrong51 conclusions.5253### 2. Isolate — the smallest unit that still fails5455Two distinct moves; pick by what you suspect:5657- **History bisection** when a previously-working thing broke: `jj bisect` /58 `git bisect` to pin the introducing change; `jj log -p -S <symbol>` to watch a59 symbol evolve. Most "regressions" are dependency or config, not code — bisect60 the lockfile and the flag, not just the source.61- **Boundary logging** in multi-component systems (API → service → DB): add one62 log line per boundary to learn _where_ it breaks, then investigate only that63 component. Do not debug all components at once.6465Critique: isolation is where people rush. "I'll just read the code" skips the66step that would have shown the failure is in the network layer, not the handler.6768### 3. Hypothesize — one theory, tested minimally6970- One theory at a time: "X because Y." Test it by changing exactly one variable71 in an isolated repro or spike — never in the production change. Confirmed →72 you have the root cause. Not → new theory; never stack fixes.73- Rule of three: three failed theories → STOP. The architecture, not the code,74 is the suspect. Talk to the user.75- **Do not fan out parallel hypotheses.** The defect is singular; dispatching76 agents to test competing theories of the same component wastes cycles and77 produces contradictory evidence. Fan-out is only correct for _attribution_ —78 when you know it fails somewhere across independent components and must learn79 which one (see Multi-component).8081### 4. Propose — root cause plus a concrete solution8283- Write the finding: the root cause, the hypothesis that explains it, and the84 evidence (the repro that proves it).85- Propose the solution as a concrete plan: the single change at the source where86 all callers route through (not a guard in every caller), sketched as a diff or87 PR description. Note the regression test that would lock it shut.88- Pass the proposal through the `ponytail` ladder (laziest fix that works). When89 the root cause traces to over-engineering — speculative abstraction, dead90 flexibility, reinvented stdlib — run `ponytail-review` (diff) or91 `ponytail-audit` (whole repo) on the failing component; its ranked92 delete/simplify list doubles as the fix plan.93- Record it in the linked issue. The proposal is verified when the repro94 confirms the theory and the proposed change addresses the source — not when95 code is merged. Hand off the application.9697## Per-language minimal repro9899Strip the surrounding app; keep only what manifests the failure. A small repro100beats a long stack trace.101102- **TypeScript:** reproduce in the playground with only the types + the failing103 expression. Surface the type with `satisfies` / `as const`; let `strict` tell104 you where narrowing breaks. Assert the expected inference with `// ^?` or105 `expectTypeOf` from the test runner — the check fails loudly when the type106 drifts. Bisect config/version, not code: toggle `strict` flags one at a time;107 the failing flag is the clue.108- **Python:** reduce to a standalone module importing only the failing path;109 `assert` the observed vs expected at the boundary.110- **Build/CI:** reproduce with the exact failing command locally (same111 node/python version); most "CI-only" failures are version or cache drift, not112 logic.113114Critique: a unit repro cannot surface concurrency, load, or integration-only115defects. If the failure only appears under real traffic, a minimal repro is the116wrong tool — capture the live trace and isolate from there.117118## Multi-component attribution119120For a system with several moving parts, dispatch one `delegate_task` per121_component boundary_ (carrying the Phase-1 contract: observed vs expected, the122exact failure) and converge on the failing component. Same isolation discipline123as the parallel-implementation skills, applied to a trace instead of parallel124work. Stop fanning out the moment one component is implicated — then switch to125single-threaded hypothesis testing inside it.126127## Known cycles (reuse before re-deriving)128129Recurring patterns from past investigations — recognize the signature, then130propose the known resolution; do not re-debug from zero:131132- **Verify-after-write.** Any file edit can report success without landing on133 disk (large file, many prior edits, fuzzy match). Read back and assert the new134 string is present; if absent, rewrite via an explicit replace with a verify135 read-back.136- **Split layers first.** When a multi-component system fails, separate host137 reachability from pod/workload reachability; read the earliest fatal log —138 later failures are downstream symptoms of the first. Don't reset a system139 because an add-on retried on a separate fault.140- **Eager-import resolution.** A module-load resolve failure means runtime141 depends on package resolution too early. Fix with explicit workspace deps +142 lazy dynamic import from a fixed allowlist, not install flags or concurrency143 tweaks.144- **E2E race selectors.** A row click before data arrives hits a placeholder,145 then "element not found" on the detail heading. Wait for a stable data row and146 visibility before clicking; keep the fix scoped to the shared root cause.147148## Pitfalls149150- Exit code 137 (OOM) looks like a build error but is a resource ceiling — raise151 `NODE_OPTIONS=--max-old-space-size=4096`, not a code change.152- "Simple" bugs have root causes too; the process is fast for them, so skipping153 it buys nothing.154- Trusting a doc's claim about the code without verifying it is how drift ships.155- A symptom patch worn as a root-cause finding is the most expensive mistake: it156 hides the real defect and makes the next failure harder.157- Parallel hypothesis testing of one component is not diligence — it is thrash.158- Applying the fix inside an investigation breaks the issue-first handoff and159 leaves no reviewable proposal.160161## Verification162163```bash164echo "investigation complete: root cause + hypothesis + proposed fix" \165 "recorded in the linked issue"166# proof = the exact repro command that demonstrates the failure on demand167```168169## See also170171- `sks-pr-review` — the review gate enforces the same root-cause discipline on172 incoming PRs.173- `sks-async` — the isolation pattern, for parallel implementation rather than174 parallel debugging.175- `sks-stack` — canonical single-workspace isolation recipe before a fix.176- `ponytail-audit` — when the defect's root cause is accidental complexity, its177 ranked simplification list seeds the proposal.178- `sks-issue` / `sks-dev-workflow` / `sks-pr` — receive the proposed solution179 and apply it as a reviewed change.