← Back to the catalog

Skill · Version 1.0.0

Legacy behavior discovery

Reconstructs existing behavior and hidden dependencies so a legacy change has an observable, controlled starting point.

legacy-code-discovery

See how it helps

When is it useful?

Use it when an old module lacks trustworthy documentation or tests and seemingly small edits have surprising effects.

What does it help you do?

  • Traces callers, outputs and hidden external side effects.
  • Finds global state, initialization order and dynamic references.
  • Identifies small seams for observing or replacing dependencies.

Try asking this

Map dependencies of this untested invoice class before refactoring it. Find every caller and observe a representative invoice without changing it. Record hidden time, database and notification dependencies before choosing the first extraction seam.

Detailed documentation

Read the skill’s original instructions, examples and checks in their authored language.

Details…Show less

Legacy Code & Dependency Discovery

Before changing hard-to-modify code, map what the system actually does today — not what comments, outdated docs or naming suggest. Legacy code often relies on implicit execution order, shared mutable state, dynamic dispatch or undocumented external contracts.

1. Behavior & Entry-Point Mapping

Trace the affected area from its real entry points to its observable outputs:

  • Entry surfaces: HTTP routes, RPC handlers, CLI commands, queue consumers, scheduled jobs, event listeners, lifecycle hooks, UI event handlers and public library exports.
  • Call graph: trace both incoming callers (who invokes this unit and with what shapes) and outgoing callees (what services, repositories, SDKs or globals this unit touches).
  • Observable outputs: return values, thrown exceptions or error codes, HTTP status and headers, database writes, emitted events, queued jobs, cache mutations, filesystem changes and telemetry.

2. Hidden Coupling & Implicit Dependencies

Look past explicit function arguments for hidden dependencies that break when code moves:

  • Shared mutable state: module-level singletons, static properties, request-context globals, in-memory caches and mutated input parameters.
  • Temporal coupling: initialization steps that must run before a method works, two-phase setup, reliance on transaction scope opened by a caller, or middleware ordering.
  • Dynamic and reflective access:
    • Dynamic property indexing (obj[key]), eval, string-based container resolution, dependency injection tokens or service locators.
    • Framework conventions: magic method names, decorators, annotations, auto-discovered directory paths, ORM relation names, serializer field reflection and job/event class names persisted in databases or queues.
  • Configuration & environment reads: direct process.env / getenv / config reads buried deep inside domain logic that behave differently across environments.

3. Identifying Seams

Follow Michael Feathers's seam model: a seam is a place where you can alter behavior or observe execution without editing the risky code in place, and every seam has an enabling point where you choose which behavior runs.

  • Object / interface seams: pass a collaborator, adapter or clock/ID generator through constructor or parameter injection instead of instantiating it inline.
  • Preprocessing / configuration seams: environment config, feature flags or router/container bindings that swap implementations at the boundary.
  • Link / module seams: module exports or wrapper functions that allow intercepting calls at a module boundary before decomposing internals.
  • ** Sprout & Wrap points**: when a function is too entangled to edit directly, identify where a new pure helper can be sprouted or the existing function can be wrapped to isolate new or extracted logic.

4. Risk & Test-Coverage Audit

Before proposing a refactoring plan, classify the safety net around the target code:

  1. Existing tests: run the current test suite around the target module. Check whether tests assert observable behavior or merely lock down private mocks.
  2. Uncovered branches: identify error paths, fallback branches, null/empty edge cases and boundary conditions with zero test coverage.
  3. External blast radius: note whether serialized payloads, database columns, public URLs, webhook formats or exported types cross process or version boundaries.
  4. Stop condition: if discovering dependencies reveals an undocumented architectural constraint or ambiguous business rule, record the concrete evidence and align with the architect or product analyst before restructuring.

Included files 1

  • SKILL.md

About this skill package

legacy-code-discovery

legacy-code-discovery: Improve legacy code in small, verifiable steps while preserving existing behavior and keeping complexity proportionate.

Details…Show less

legacy-code-discovery

legacy-code-discovery: Improve legacy code in small, verifiable steps while preserving existing behavior and keeping complexity proportionate.

Includes the complete skill and its supporting files (1 files). The exact authored scope is preserved below.

Original skill description (source language)

Use when mapping existing behavior, call graphs, hidden couplings, side effects, dynamic references and test seams before refactoring or modernizing legacy code.

Install the skill, review its source and trust settings, then enable it for the relevant project or agent.

Requirements

  • Orqestria installed on your computer.