Technical Research
Technical Research
Produce evidence-backed technical findings, not plausible-sounding guesses. Every non-trivial claim needs a source, a version/date context, and an honest confidence level.
Before researching anything, answer this triage question:
Can this be resolved by reading the project's own code, config, lockfile, or local docs — with high confidence and no material risk from being wrong?
- Yes → Don't research. Answer directly from project context.
- No → Proceed with the workflow below.
Example trigger vs. non-trigger:
| Situation | Research? |
|---|---|
"Does useEffect cleanup run on unmount?" (well-established, low-risk, you know it cold) | No |
"Does React 19's useEffect behave differently under Strict Mode than React 18's?" | Yes |
| "Which JSON parser should we add?" when one already works fine | No (reconsider: is there a real problem?) |
"Is node-fetch still needed given our Node version?" | Yes (version-dependent fact) |
| "Does Stripe's API support idempotency keys on refunds?" | Yes (external API contract) |
Progress:
- [ ] 1. Confirm research is warranted (triage above)
- [ ] 2. Pin down the exact question + decision it serves
- [ ] 3. Inspect project context (versions, manifests, lockfiles, code, config)
- [ ] 4. Identify constraints (platform, license, perf, deployment, compat)
- [ ] 5. Retrieve authoritative sources (official docs/specs first)
- [ ] 6. Cross-check consequential claims against a second source
- [ ] 7. Separate: confirmed fact / inference / conflicting info / unknown
- [ ] 8. Compare alternatives only if a real choice exists
- [ ] 9. Write proportional report with citations and handoff
Step 1–2: Scope the question
State explicitly:
- "The question is: ___"
- "This answer will be used to decide: ___" Do not widen scope unless evidence reveals a material new risk (note it, don't silently chase it).
Step 3: Inspect project context first
Check, as applicable: package.json/lockfile, requirements.txt/poetry.lock, go.mod, Cargo.toml, framework config, actual installed version (node_modules/x/package.json, pip show x), existing usage of the API/library in the codebase, CI config, .nvmrc/engines.
Record: installed version, target environment, and what's already verifiable without external lookup.
Step 4: Identify real constraints
Platform/OS, language version, license compatibility with the project, performance/budget requirements, deployment environment (serverless vs. long-running, edge vs. node, browser support matrix).
Step 5: Source priority (highest to lowest authority)
- Official docs, API reference, specification/standard (W3C, RFC, ECMA, etc.)
- Official release notes, changelogs, migration guides, security advisories
- Official source code, type definitions, tests, issue tracker (for undocumented behavior)
- Reputable secondary sources (maintainer blog posts, well-known technical writeups)
- Community discussion (Stack Overflow, forums) — leads only, never sole evidence for a "documented" claim
Always confirm the source matches: correct product, correct version, correct environment, and recency (check publish/update date — don't trust an undated tutorial for version-sensitive behavior).
Step 6: Cross-check consequential claims
If the finding materially affects an architecture, security, or migration decision, verify it against at least two independent authoritative sources (e.g., official docs + changelog, or docs + source code).
Step 7: Categorize everything
Explicitly label each finding as one of:
- Confirmed (stated in official docs/spec and matches the relevant version)
- Inferred (reasoned from adjacent documented facts, not stated outright)
- Conflicting (sources disagree — state both and which is more authoritative/current)
- Unknown (could not be verified — state what's missing and how to resolve it)
Step 8: Compare only if a real choice exists
Don't manufacture alternatives. If one option is clearly correct given constraints, say so and justify briefly. Use a comparison table only for genuine multi-option decisions (see template below).
Step 9: Report (see format below)
Example 1 — Version-specific API behavior
Input: "Does fetch's signal option work with AbortSignal.timeout() in the Node version we use?"
Output:
Question: Is AbortSignal.timeout() supported with fetch in our runtime (Node 18.17, per package.json engines)?
Finding: CONFIRMED. Node.js added AbortSignal.timeout() as stable in Node 17.3.0
(Node.js release notes, v17.3.0, 2021-12-17) and global fetch became stable in Node 18
(Node.js docs, "Fetch API", stable since v18.0.0). Node 18.17 satisfies both.
Source: nodejs.org/docs/latest-v18.x/api/globals.html#fetch;
nodejs.org/en/blog/release/v17.3.0
Caveat: Behavior inside fetch's internal undici implementation can differ slightly
from browser fetch for signal propagation on redirects — not verified against
project's actual retry logic. If retries-on-redirect matter, inspect
node_modules/undici source directly.
Handoff: Safe to use AbortSignal.timeout() directly; no polyfill needed for Node 18.17+.
Example 2 — Comparing libraries with a real decision
Input: "Should we use date-fns or luxon for new date handling? We currently use raw Date."
Output:
Question: Pick a date library for new timezone-aware scheduling feature.
Constraints: Bundle size matters (frontend, already size-conscious per webpack config budget
of 250kb); need IANA timezone support; current code uses zero date libs.
| Criterion | date-fns (v3) | luxon (v3) | Status quo (raw Date) |
|----------------------------|---------------------------|---------------------------|------------------------|
| IANA timezone support | Via date-fns-tz (separate pkg) | Built-in (Intl-based) | No |
| Bundle impact (tree-shaken)| ~2-5kb for used fns | ~23kb, not tree-shakeable | 0kb |
| Maintenance (per GitHub) | Active, v3 released 2023 | Active, v3 released 2023 | N/A |
| License | MIT | MIT | N/A |
Sources: date-fns.org/docs, moment.github.io/luxon (official docs),
npm registry metadata (checked 2024, package versions as published).
Recommendation: date-fns + date-fns-tz, given tree-shaking fits the bundle budget;
luxon's built-in TZ support doesn't outweigh its larger footprint here.
Unresolved: Did not benchmark actual tree-shaken size in this project's specific
webpack config — recommend confirming with a build size check before merging.
Example 3 — No research needed Input: "Why is this Express route returning 404?" Output: No external research warranted — this is answerable from the project's own route definitions and middleware order. Inspect the code directly.
- State the question and the decision it serves before searching anything.
- Always note the version/date context of every source you cite.
- Prefer inspecting actual installed versions over assuming "latest."
- Distinguish a documented guarantee from an observed behavior or a forum claim — say which one you have.
- Keep reports proportional: a one-line API check needs a one-line answer with a source, not a report template.
- When browsing/external access is unavailable, say so explicitly and work from local/project evidence only — never present unverified claims as confirmed.
- Treat semver as a signal, not proof — note when you haven't verified actual compatible behavior.
- Include "do nothing" / the current implementation as a baseline option in comparisons when relevant.
- If a dependency research task touches license, support status, and security, check each explicitly — don't infer security from absence of mentioned CVEs without saying that's what you're doing.
- Researching things already answerable from the codebase — wastes effort and signals poor judgment.
- Citing an old tutorial or blog post as if it reflects current API behavior without checking its date/version.
- Presenting a popularity ranking (stars, downloads) as a technical conclusion.
- Recommending an upgrade just because a newer version exists, with no stated benefit tied to a real requirement.
- Fabricating URLs, version numbers, benchmark numbers, or claiming to have "read the docs" or "run a test" when that didn't happen.
- Building a comparison table for a decision that doesn't actually have competing options.
- Treating "no known vulnerability found" as "proven secure."
- Expanding scope into full security audits, architecture redesign, or implementation — hand those off instead of absorbing them.
- Skipping the distinction between confirmed/inferred/conflicting/unknown and presenting everything with equal confidence.