Important
This repository has moved to fission-systems/Fission. All development, releases, and issues are tracked there. This repository is archived.
Fission is a Rust-native reverse-engineering and binary decompilation workspace. It is built around a Fission-owned intermediate-representation pipeline, with Ghidra-style Sleigh semantics feeding Rust-owned NIR, HIR, structuring, rendering, automation, and quality gates.
The project goal is not only to decode instructions. The goal is to produce decompiler output that is mechanically traceable, semantically defensible, and eventually readable enough to be useful in day-to-day reverse engineering.
This README is intentionally long. It is a practical orientation document for contributors, operators, and future agents working in the repository. The shorter source-of-truth references remain in docs/, AGENTS.md, and the crate-local AGENTS.md files.
- Project Status
- Quick Start
- Repository Tour
- Architecture in One Page
- Core Pipeline
- Crate Guide
- CLI Guide
- Resource Bundle
- Decompiler Quality Loop
- NIR and HIR Policy
- Sleigh Runtime
- Loader Policy
- Static Facts
- Dynamic Analysis and Emulator
- Time-Travel Debugging (TTD)
- Symbolic Execution and Taint Engine
- Concolic Path Exploration
- Structuring Model
- Telemetry and Reports
- Testing Matrix
- CI and Release
- Development Workflow
- Security and Malware Sample Policy
- Contributor Notes
- Troubleshooting
- Glossary
- Roadmap
- Appendix A: Commands
- Appendix B: Review Checklists
- Appendix C: File Ownership Index
- Appendix D: Quality Investigation Playbook
- Appendix E: Documentation Index
- Fission is a research-heavy Rust workspace for binary loading, instruction lifting, decompiler IR, structuring, automation, and product surfaces.
- The canonical semantic layer is
fission-pcode, especially the NIR/HIR and structuring modules. - Application orchestration belongs in
fission-decompilerand user-facing command routing belongs infission-cli. - Binary parsing and provenance belong in
fission-loader. - Static facts and native preparation services belong in
fission-static. - Sleigh decode and raw p-code lift behavior belong in
fission-sleigh. - Quality reports and automation lanes belong in
fission-automation. - Vendor trees are references only. Production paths must not depend on them at runtime or build time.
- Checked-in utility resources under
utils/must be accessed through the existing resource-root mechanisms, not hardcoded absolute paths. - Current day-to-day quality work prioritizes x86 and x86-64 decompilation correctness and readable pseudocode.
Fission should be treated as a system with strict ownership boundaries. If a semantic issue is discovered in the final pseudocode, the fix should land where the behavior is owned, not in the renderer or README-level presentation.
git clone https://github.com/sjkim1127/Fission.git
cd Fission- Rust 1.85 or newer.
cargo-nextestfor the preferred local test runner.- A modern C toolchain if local fixtures or corpus binaries need to be rebuilt.
rustup update
cargo install cargo-nextest --lockedThe Rust workspace can build without every large resource, but real decompilation needs Sleigh specifications and some quality lanes need signature or support data. utils/ is not checked into git; pull the bundled release asset instead:
mkdir -p utils
curl -L --fail --show-error \
"https://github.com/sjkim1127/Fission/releases/download/assets-v1/fission-utils.tar.gz" \
-o /tmp/fission-utils.tar.gz
tar -xzf /tmp/fission-utils.tar.gz -C utils --strip-components=1cargo build -p fission-cli --release
./target/release/fission_cli --helpFor local iteration, prefer --profile quick-release over --release:
[profile.release] uses fat LTO + codegen-units = 1 for shipping-quality
runtime perf, which serializes codegen/linking and dominates rebuild time.
[profile.quick-release] (workspace Cargo.toml) drops those two knobs but
keeps opt-level = 3, so decomp-speed/output checks stay representative —
measured ~2.9x faster on a touch-one-core-crate rebuild (44s → 15s), with
byte-identical output on the real-binary regression set and ~9% slower
runtime on the heaviest measured function. Binaries land in
target/quick-release/. Use plain --release for anything going into a
benchmark run, a release build, or a perf measurement that needs to match
production codegen.
cargo build -p fission-cli --profile quick-release
./target/quick-release/fission_cli --helpcargo nextest run -p fission-pcode
cargo check -p fission-pcode
cargo check -p fission-decompiler
cargo check -p fission-automationThe repository is organized as a Cargo workspace plus documentation, resource bundles, scripts, CI workflows, and reference-only vendor trees.
| Path | Purpose |
|---|---|
crates/ |
Rust workspace crates. |
docs/ |
Architecture, CLI, evaluation, release, versioning, onboarding, roadmap, and ADR documents. |
utils/ |
Checked-in resource bundle material such as Sleigh specs and Ghidra data manifests. |
vendor/ |
Reference-only third-party source trees and datasets. |
scripts/ |
Local helper scripts for testing, corpus work, and maintenance. |
.github/workflows/ |
CI, reusable workflow jobs, release tag workflow, fuzzing, and heavy gates. |
image/ |
Project logo and icon assets. |
target/ |
Local Cargo build output; not source. |
AGENTS.mddefines repository-level engineering rules and ownership boundaries.PROJECT.mdtracks the active normalize pass-pipeline migration: current per-stage status, the two pass-framework tracks, and recurring pitfalls found while migrating.docs/PROJECT_MAP.mdis the quick navigation map.docs/architecture/ARCHITECTURE.mdis the architecture source of truth.docs/CLI.mddocuments command-line behavior.docs/EVALUATION.mddescribes evaluation posture.docs/QUALITY_METRICS.mddocuments metric contracts.docs/RELEASE.mdanddocs/VERSIONING.mddescribe release discipline.docs/adr/records architectural decisions.docs/onboarding/contains practical first-task guides.docs/roadmap/RUST_DECOMPILER_ROADMAP.mdtracks long-term direction.
The shortest useful architecture summary is: binary bytes are loaded by fission-loader, instruction semantics are lifted through fission-sleigh, canonical IR and decompiler semantics are owned by fission-pcode, orchestration is performed by fission-decompiler, and user or automation surfaces consume those results without inventing new semantic policy.
Binary bytes
-> fission-loader
-> fission-static facts and provenance
-> fission-sleigh decode and p-code lift
-> fission-pcode NIR
-> fission-pcode HIR
-> structuring, cleanup, rendering
-> fission-decompiler result contracts
-> CLI, TUI, GUI, automation, reports
fission-pcodeis the semantic owner.fission-pcode::nir::structuringis the structuring owner.fission-decompileris the orchestration owner.fission-staticis the facts and preparation owner.fission-loaderis the binary-format owner.- Printer surfaces are consume-only.
- Benchmark and report code must project canonical telemetry instead of inventing parallel counters.
- Load bytes from a supported binary format.
- Classify format, architecture, sections, symbols, imports, exports, and executable regions.
- Attach provenance and identity hints without changing IR semantics.
- Prepare static facts needed by the decompiler.
- Decode instructions through Sleigh language definitions.
- Emit raw p-code in a form that can be compared against parity expectations.
- Lower p-code into Fission NIR.
- Normalize NIR while preserving semantics.
- Recover type, calling convention, stack, pointer, and data-flow hints when evidence supports them.
- Build HIR as a human-readable representation.
- Apply structuring passes using CFG, dominance, post-dominance, SCC, and proof evidence.
- Render pseudocode without inventing missing semantics.
- Report telemetry through canonical counters.
- Use automation lanes to compare quality over time.
| Crate | Role | Editing rule |
|---|---|---|
fission-script |
Script-facing helpers and experiments for automation or user scripting. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-automation |
Quality lanes, reports, summaries, and go/stop automation signals. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-core |
Shared core types, path configuration, resource roots, and utilities. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-loader |
Binary loading, sections, symbols, relocations, virtual types, and identity reports. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-pcode |
Canonical IR, NIR, HIR, structuring, CFG analysis, type hints, and printer. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-decompiler |
Decompilation orchestration, request/result contracts, Rust-Sleigh bridge, and render routing. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-signatures |
Signature datasets and lookup logic. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-static |
Static analysis facts, native preparation, discovery, xrefs, patches, and strings. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-dynamic |
Dynamic-analysis support surfaces. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-ttd |
Time-travel and trace-adjacent support. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-emulator |
Pure-Rust P-Code execution engine, OS HLE, TTD recording, and taint-aware concolic execution. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-solver |
Pure-Rust SMT/constraint engine: SymExpr AST, Solver node registry, path condition management. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-plugin |
Plugin contracts, manager, loader, and runtime hooks. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-cli |
Command-line product surface. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-sleigh |
Sleigh decode and p-code lift runtime. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-ai |
AI-facing assistance surfaces and integration points. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-tui |
Terminal UI with ratatui-based interaction. | Keep behavior inside its owner; do not leak semantic policy to callers. |
fission-dioxus |
Pure Rust desktop GUI surface. | Keep behavior inside its owner; do not leak semantic policy to callers. |
Script-facing helpers and experiments for automation or user scripting.
- Read
crates/fission-script/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-script. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Quality lanes, reports, summaries, and go/stop automation signals.
- Read
crates/fission-automation/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-automation. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Shared core types, path configuration, resource roots, and utilities.
- Read
crates/fission-core/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-core. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Binary loading, sections, symbols, relocations, virtual types, and identity reports.
- Read
crates/fission-loader/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-loader. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Canonical IR, NIR, HIR, structuring, CFG analysis, type hints, and printer.
- Read
crates/fission-pcode/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-pcode. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Decompilation orchestration, request/result contracts, Rust-Sleigh bridge, and render routing.
- Read
crates/fission-decompiler/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-decompiler. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Signature datasets and lookup logic.
- Read
crates/fission-signatures/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-signatures. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Static analysis facts, native preparation, discovery, xrefs, patches, and strings.
- Read
crates/fission-static/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-static. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Dynamic-analysis support surfaces.
- Read
crates/fission-dynamic/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-dynamic. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Time-travel and trace-adjacent support.
- Read
crates/fission-ttd/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-ttd. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Plugin contracts, manager, loader, and runtime hooks.
- Read
crates/fission-plugin/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-plugin. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Command-line product surface.
- Read
crates/fission-cli/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-cli. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Sleigh decode and p-code lift runtime.
- Read
crates/fission-sleigh/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-sleigh. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
AI-facing assistance surfaces and integration points.
- Read
crates/fission-ai/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-ai. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Terminal UI with ratatui-based interaction.
- Read
crates/fission-tui/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-tui. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
Pure Rust desktop GUI surface.
- Read
crates/fission-dioxus/Cargo.tomlbefore changing dependencies. - Prefer local patterns already used inside
crates/fission-dioxus. - Do not create a parallel metric, loader rule, or semantic policy if another crate already owns it.
- Run the narrowest relevant test first, then broaden to crate checks.
The CLI is the fastest product surface for validating loader and decompiler behavior locally. It should expose capabilities, not own semantic fixes.
fission_cli --help
fission_cli info <binary>
fission_cli list <binary>
fission_cli decomp <binary> --addr 0x1400010a0
fission_cli decomp <binary> --all --json- Use
infofor loader-level identity and provenance questions. - Use
listfor function discovery questions. - Use
decompfor function-level pseudocode output. - Use JSON output when comparing rows, caches, or automation artifacts.
- Keep command-line compatibility shims separate from semantic behavior.
Fission keeps large or operationally specific data out of git and ships it as a standalone utils/ resource bundle (fission-utils.tar.gz) attached to the assets-v1 GitHub Release.
utils/sleigh-specs/contains Sleigh language resources and manifests.utils/ghidra-data/contains reference data and provenance notes.utils/MANIFEST.mddocuments utility resources.- Runtime code should use
PathConfig,PATHS,resource_roots, or existing loaders. - Production code must not hardcode
/Users/sjkim1127/Fission/utils. - CI fetches the bundle via
.github/actions/setup-utils(cached byassets_tag);.github/workflows/publish-utils-assets.ymlregenerates it from a given ref.
mkdir -p utils
curl -L --fail --show-error \
"https://github.com/sjkim1127/Fission/releases/download/assets-v1/fission-utils.tar.gz" \
-o /tmp/fission-utils.tar.gz
tar -xzf /tmp/fission-utils.tar.gz -C utils --strip-components=1
fission_cli resources statusQuality work starts from a concrete function or row, not a vague aggregate. The loop below is the standard operating model for decompiler-quality changes.
- Anchor the exact row, binary, address, function name, behavior status, and quality scores.
- Record stdout, stderr, line count, byte count, and static feature gaps.
- Find the canonical owner: Sleigh, NIR, type recovery, structuring, cleanup, printer, benchmark, or automation.
- Add focused coverage for the invariant.
- Make the smallest invariant-based production change.
- Run the targeted test first.
- Run relevant crate-level tests and checks.
- Run the focused source-semantic row with stale caches disabled when available.
- Inspect artifacts, not only aggregate numbers.
- Run broader smoke or automation checks after a focused improvement.
- Report whether behavior mechanically changed and whether quality improved.
- A passing synthetic test is necessary but not sufficient for a decompiler-quality claim.
- A changed pseudocode file is not automatically a quality improvement.
- Aggregate metrics must not hide row-level regressions.
- Raw p-code parity must be checked before NIR or HIR interpretation when the lift is suspect.
- Ghidra may be used as a cleanroom reference for behavior, not as a copied implementation source.
NIR and HIR have different contracts.
| Layer | Contract | Consequence |
|---|---|---|
| NIR | Semantically identical to the source behavior. | Correctness and parity are the highest priorities. |
| HIR | Human-readable pseudocode derived from correct semantics. | Readability can be prioritized when the underlying semantics remain traceable. |
- NIR must not be prettified by losing behavior.
- HIR may remove unnecessary temporaries when that improves readability without hiding semantics.
- Printer code must not fake structure that the structuring owner did not prove.
- Type and data abstraction should be recovered at semantic layers, not by output-only substitution.
The Sleigh runtime is the decode and raw p-code lift path. It should execute .sla ConstructTpl semantics rather than accumulating manual opcode mappings.
- Keep
.slaexecution as the success source. - Raw p-code canaries are admission gates for lift changes.
- Validate x86 and x86-64 shared-token cases carefully.
- Preserve Ghidra-style materialization behavior where downstream parity depends on it.
- Do not grow legacy token cursor or compatibility-classifier debt without a clear retirement path.
The loader owns binary format parsing and metadata provenance. It does not own decompiler repair.
detectstage in the loader pipeline.probe/load-specstage in the loader pipeline.mapstage in the loader pipeline.symbolsstage in the loader pipeline.finalizestage in the loader pipeline.
- Known unsupported formats should fail closed with typed messages.
- Raw binary loading must not silently become a fallback for unknown bytes.
- Container formats must be classified before executable loading.
- Loader provenance is a public contract consumed by CLI and GUI surfaces.
- Function lists must use loader-owned views rather than surface-specific filtering rules.
Static facts help the decompiler, but they are not the final semantic owner. The fact layer should provide evidence, provenance, and analysis services.
- Xrefs and discovery facts.
- Patch and string facts.
- Native decompiler preparation.
- FactStore-style aggregation for decompilation contexts.
- Binary-derived helper services.
Fission includes a pure-Rust dynamic analysis engine (fission-emulator) capable of executing arbitrary x86/x86-64 P-Code sequences produced by Sleigh, without requiring any external runtime like QEMU or Unicorn.
The emulator is a core pillar for future dynamic reasoning capabilities:
- Tracing and Differential Analysis — Execute binaries with a full instruction trace and diff the output against expected behavior.
- Time-Travel Debugging (TTD) — Record/replay execution with memory and register delta snapshots.
- Concolic Execution — Use TTD snapshots to fork execution at unexplored conditional branches.
- Symbolic Taint Tracking — Propagate symbolic expressions through P-Code operations and track tainted data flows from inputs (e.g.
stdin) through memory and registers.
fission-emulator
├── core.rs — Emulator state, main run loop, register I/O, TTD hooks
├── pcode/
│ ├── eval.rs — P-Code opcode evaluator (taint-aware)
│ └── state.rs — MachineState: address spaces + shadow memory
├── arch/ — Architecture descriptors, calling conventions
├── os/
│ ├── linux/ — Linux syscall HLE (read, write, mmap, brk, exit, ...)
│ ├── windows/ — Windows HLE stubs
│ └── bare_metal/ — No-OS / embedded HLE
├── sym/
│ └── mod.rs — SymbolicExecutor: TTD-backed concolic path exploration
├── trace.rs — TraceLog: per-instruction audit trail
├── snapshot.rs — Lightweight snapshot helpers
└── loader.rs — Binary loading bridge for the emulator
# Emulate a binary (default: auto-detect OS, no limits)
fission_cli run <binary>
# Limit to N instructions
fission_cli run <binary> --max-inst 10000
# Provide stdin mock data
fission_cli run <binary> --stdin "hello
"
# Emit full instruction trace (JSON)
fission_cli run <binary> --trace --json
# Enable TTD recording (snapshot every 1000 instructions)
fission_cli run <binary> --ttd-record 1000
# Seek TTD to step N (rewind and replay from that point)
fission_cli run <binary> --ttd-record 1000 --ttd-seek 5000
# Enable concolic path exploration
fission_cli run <binary> --ttd-record 500 --sym-exploreThe emulator uses High-Level Emulation (HLE) rather than emulating an actual OS kernel. Each architecture+OS pair has its own HLE handler:
| OS | HLE Handler | Key syscalls |
|---|---|---|
| Linux x86-64 | os/linux/mod.rs |
read, write, mmap, brk, exit_group, open, close, fstat, stat |
| Windows x86-64 | os/windows/hle.rs |
VirtualAlloc, HeapAlloc, WriteFile, ExitProcess, and common NT stubs |
| Bare Metal | os/bare_metal/mod.rs |
Minimal: semihosting stubs only |
HLE handlers can intercept function calls by name (via PLT/IAT hooks) or by recognized calling patterns.
The arch/ subsystem provides architecture-agnostic calling convention helpers:
Emulator::read_arg(n)— read the nth integer argument per the current ABIEmulator::write_return_val(v)— write to the return registerEmulator::simulate_return()— pop the stack or read the link register and set PC
Currently supported: System V AMD64 ABI (Linux x86-64), Microsoft x64 (Windows), and a stub for ARM AArch64.
The fission-ttd crate provides a deterministic execution recorder and replayer. It is the backbone for all forms of non-linear execution analysis.
-
Recording Phase — As the
Emulatorexecutes, every N instructions (configurable via--ttd-record <N>) it captures:- Complete CPU register state (
RegisterState) - Memory write deltas:
(address, old_bytes, new_bytes) - Shadow state (taint) deltas:
(space_id, address, old_node_id, new_node_id)
- Complete CPU register state (
-
Snapshot Storage — Snapshots are stored in a bounded ring buffer (
TTDRecorder) with configurable capacity. Older snapshots are evicted when capacity is reached. -
Seeking / Rewinding —
Emulator::ttd_seek(step)locates the most recent snapshot at or beforestep, then restores:- All GP registers from
RegisterState - All memory bytes from
MemoryDeltarecords - All symbolic taint mappings from
ShadowDeltarecords
- All GP registers from
-
Replay — After rewinding,
emulator.run()continues forward from the restored state.
| Type | Crate | Purpose |
|---|---|---|
TTDRecorder |
fission-ttd |
Manages the ring buffer of ExecutionSnapshots |
ExecutionSnapshot |
fission-ttd |
Single-point snapshot: registers + memory + shadow deltas |
MemoryDelta |
fission-ttd |
Before/after memory diff for one address range |
ShadowDelta |
fission-ttd |
Before/after taint AST node diff for one byte position |
RegisterState |
fission-ttd |
Full x86-64 GP register snapshot |
Fission's taint and symbolic engine is a pure-Rust implementation — no Z3 bindings, no C++ FFI, no external SMT dependencies. It is designed for long-term maintainability and architecture-agnostic reasoning.
fission-solver — Pure-Rust SMT/Constraint engine
├── ast.rs — SymExpr: the symbolic expression AST
└── solver.rs — Solver: node registry, path conditions, SAT stub
fission-emulator — Concrete + Symbolic execution
└── pcode/
├── state.rs — MachineState: shadow_memory (taint map)
└── eval.rs — Evaluator: taint propagation per P-Code opcode
Every symbolic value is represented as a node in the SymExpr tree:
| Variant | Description |
|---|---|
Const { val, size } |
Concrete bitvector constant |
Var { id, name, size } |
Named symbolic variable (e.g. stdin_0x4000) |
Add(a, b) / Sub(a, b) / Mul(a, b) |
Integer arithmetic |
And(a, b) / Or(a, b) / Xor(a, b) |
Bitwise operations |
Shl(a, b) / Lshr(a, b) |
Shift operations |
Eq(a, b) / Neq(a, b) / Ult(a, b) / Ule(a, b) |
Comparisons (return 1-bit) |
Ite { cond, t, f } |
If-then-else |
Extract { expr, lsb, size } |
Bit extraction |
Concat(a, b) |
Bitvector concatenation |
The MachineState holds a parallel "shadow" layer alongside the concrete memory:
// shadow_memory: (space_id, byte_address) -> SymNodeId
pub shadow_memory: HashMap<(u64, u64), u32>space_id = 2→ CPU registers (Sleigh register address space)space_id = 3→ RAM (Sleigh ram address space)
When a concrete byte is written, its shadow entry is cleared. When a symbolic value is written, its shadow entry is updated with the corresponding AST node ID.
| P-Code Op | Taint Behavior |
|---|---|
COPY |
Propagate source shadow to destination |
LOAD |
Propagate shadow from RAM byte to output varnode |
STORE |
Propagate shadow from source varnode to RAM byte |
INT_ADD |
If either input is tainted, build SymExpr::Add(a, b) and store new node |
INT_SUB |
Similar: build SymExpr::Sub |
| Other ops | Currently concrete-only (no taint propagation yet) |
The primary taint source is stdin. In os/linux/mod.rs, the sys_read(fd=0, ...) handler:
- Reads bytes from
stdin_buffer(the--stdinmock). - Writes them into RAM as concrete bytes.
- For each byte, calls
solver.register_var("stdin_<addr>", 1)to create aSymExpr::Var. - Tags the corresponding
shadow_memoryentries with the new node ID.
From that point forward, any P-Code operation that reads those bytes will propagate the taint forward into new SymExpr constraint trees.
Concolic (concrete + symbolic) execution combines real execution with symbolic state to explore multiple code paths automatically.
- The emulator runs normally in concrete mode, recording TTD snapshots along the way.
- Every
CBranch(conditional branch) P-Code instruction emits aSymBranchevent containing:- The TTD step index at the branch point
- The current PC value
- Whether the branch was taken or not
- The alternate target (address or relative P-Code index)
- After the current path terminates, the
SymbolicExecutorpops unexplored branches from a queue. - It rewinds the emulator to the snapshot closest to the branch step via
ttd_seek(). - It forces the PC (or P-Code index) to the alternate target and resumes execution.
- This continues until the exploration queue is empty.
Path 1: [A] → [B] → [D] → halt (branch at B taken = true)
Rewind to B
Path 2: [A] → [B] → [C] → [E] → halt (branch at B taken = false)
The SymbolicExecutor (sym/mod.rs) is the exploration driver:
pub struct SymbolicExecutor {
pub emu: Emulator,
pub queue: Vec<SymBranch>, // unexplored branch events
}It calls emu.run() in a loop, drains emu.sym_events into the queue, and rewinds to the next unexplored branch. Each new execution path may reveal additional branches, which are added to the queue.
The current implementation is concolic scaffolding: it explores paths by forcing PC values, but does not yet invert branch conditions symbolically via the Solver. The planned evolution:
- When a
CBranchis encountered and a taint variable is used in the branch condition, add the negated constraint!conditiontosolver.assertions. - Call
solver.check_sat()to verify the alternate path is feasible. - Use
solver.get_value(var_id)to obtain a concrete input that triggers the alternate path. - Replay with that concrete input instead of forcing PC.
This requires implementing the DPLL/CDCL bit-blasting core inside fission-solver, which is the next development milestone.
The active structuring path is graph-oriented and proof-driven. It should use deterministic collapse rules and explicit fallback when legality is incomplete.
StructureGraphowns the collapsed overlay.CollapseDriverapplies deterministic collapse rules.RegionProofrecords replacement and readiness evidence.- Collapse only proof-complete and emit-ready regions.
- Fallback output should be explicit rather than disguised as clean structure.
- Printer and postprocess code must not reconstruct structure after the fact.
There are two independent pass-orchestration tracks; neither subsumes the
other, because they operate on different IR shapes. Current migration
status and the full per-stage backlog live in PROJECT.md.
- Structuring (pre-structuring, block-CFG level): new transformations
should be expressed as
NirPassimplementations (crates/fission-pcode/src/midend/pass/), operating onNirFunc(wrapsPreviewBuilder's block/CFG state) throughPassCtxinstead of capturing builder internals. Every pass declares anInvariantBasis(dominator tree, postdominator tree, SCC, loop body, edge classification) so review can reject address/function-specific overfitting.PassOutcome::changedmust be accurate. Binary-specific and address-specific guards are forbidden in pass bodies. - Normalize (post-structuring,
HirFunction/Vec<HirStmt>level): new transformations should be expressed asaction_pipeline::Passimplementations (fission-midend-core::action_pipeline), registered asActionGroupentries infission-midend-normalize/src/pipeline/groups.rs. Prefer the existing composable primitives (fn_pass,cleanup_pass,gated_followup,admission_gated) over new free-function control flow inpipeline/stages.rs; this migration is in progress, is done stage-by-stage with a real-binary before/after parity check per slice, and is not something to attempt in one large change.cleanup_passis budget-gated (mirrors the legacyrun_cleanup_blockadmission check onEARLY_CLEANUP_BLOCK_STMT_LIMIT/BLOCK_LIMIT);fn_passis not — using the wrong one silently changes admission behavior on large functions without failing any test on small ones, so always check which one the original call site used before registering. - A chain whose body calls something that itself needs
diag/perf(apply_type_signature_fixed_point,run_cleanup_family_passes) cannot go throughfn_pass/GatedFollowupPass— neither primitive carriesdiag/perfthrough to a callee. Keep those as a namedstage_passstep instead of dropping the forwarding silently.
Decompiler output must be identical across separate process runs of the
same binary (AGENTS.md Core Rule 4). std::collections::HashMap/HashSet
use a per-process-random RandomState by default; any unsorted iteration
over one that feeds a .first()/.find_map()-style pick (not just a
.contains()/.get() membership check) is a real nondeterminism bug, not
a style nit — two were found and fixed this way in
fission-pcode::midend::structuring. When adding a new HashMap/HashSet
in fission-pcode::midend or fission-midend-structuring, prefer the
crate-local fixed-seed alias (rustc_hash::FxBuildHasher, already the
default there) over std::collections::HashMap directly, and never iterate
either collection to pick a specific value without sorting first.
Telemetry is useful only if the same counter means the same thing everywhere. Fission keeps canonical decompiler counters in NirBuildStats and projects them outward.
NirBuildStatsis the canonical telemetry owner.- Automation reports should consume canonical counters.
- Benchmark layers should not define parallel meanings for the same behavior.
- Regression reasons should map to structuring, materialization, type, or lift families.
- Reporting changes are not semantic fixes unless the row-level oracle moves.
| Scope | Default command | Use when |
|---|---|---|
| pcode tests | cargo nextest run -p fission-pcode |
NIR, HIR, structuring, printer, and type-hint work. |
| pcode check | cargo check -p fission-pcode |
Compile validation after semantic changes. |
| decompiler check | cargo check -p fission-decompiler |
Orchestration or Rust-Sleigh glue changes. |
| automation check | cargo check -p fission-automation |
Telemetry or reporting changes. |
| core tests | cargo nextest run -p fission-core |
Resource path and shared core changes. |
| CLI build | cargo build -p fission-cli --release |
Product and benchmark validation requiring the release CLI. |
| workspace check | cargo check --workspace |
Broad compile confidence before larger handoff. |
- Use
cargo nextest runby default for Rust tests. - Use
cargo testfor doctests or harness-specific behavior. - Run targeted tests before crate-wide tests.
- Do not claim success from a targeted test if crate-level regression remains.
- Call out known unrelated failures explicitly.
CI source of truth lives in .github/workflows/. Reusable workflows keep the main pipelines smaller and make heavy checks explicit.
.github/workflows/ci.yml.github/workflows/ci-heavy.yml.github/workflows/cd.yml.github/workflows/release-tag.yml.github/workflows/fuzz.yml.github/workflows/ci-cd-monitor.yml.github/workflows/reusable-build-cli.yml.github/workflows/reusable-cli-smoke.yml.github/workflows/reusable-corpus-validation.yml.github/workflows/reusable-coverage.yml.github/workflows/reusable-lint-format.yml.github/workflows/reusable-miri.yml.github/workflows/reusable-msrv.yml.github/workflows/reusable-nir-check.yml.github/workflows/reusable-nir-regression-gate.yml.github/workflows/reusable-run-tests.yml.github/workflows/reusable-security-check.yml.github/workflows/reusable-setup-rust.yml.github/workflows/reusable-upload-artifacts.yml.github/workflows/reusable-benchmark.yml
Release tags should be shipped through Release Tag (CI green), which tags only a commit whose push run has already passed the required CI path.
- Read the nearest
AGENTS.mdbefore editing a scoped area. - Confirm the owner layer before changing behavior.
- Inspect existing tests and local patterns.
- Add focused coverage for new invariants.
- Make scoped production changes.
- Run targeted validation.
- Run crate-level validation.
- Inspect Git status and stage only intended hunks.
- Report both mechanical change and quality impact.
- Assume unrelated changes belong to the user.
- Do not revert changes you did not make.
- Ignore unrelated dirty files unless they block the task.
- If a touched file has user changes, read carefully and work with them.
- Use non-interactive Git commands when possible.
Reverse-engineering repositories often touch untrusted binaries. Treat samples and externally sourced executables as hostile inputs.
- Do not execute unknown samples as part of normal decompiler validation.
- Prefer parsing and static analysis paths.
- Keep malware sample handling aligned with
docs/MALWARE_SAMPLE_POLICY.mdandSECURITY.md. - Do not upload private or suspicious binaries to third-party services without explicit approval.
- Keep sample provenance visible in reports.
- Prefer small invariant-based fixes over address-specific special cases.
- Use CFG, dominance, post-dominance, SCC, dataflow, and fixed-point reasoning where appropriate.
- Do not add runtime dependencies on
vendor/. - Do not add C++ bindings to shortcut reference behavior.
- Do not bypass existing resource configuration helpers.
- Document new public contracts near the code and in
docs/when they affect users.
| Symptom | First check |
|---|---|
| Missing Sleigh specs | Pull fission-utils.tar.gz from the assets-v1 release (see Resource Bundle) and check resource status. |
| CLI cannot find resources | Check FISSION_RESOURCE_ROOT, --resource-root, and PathConfig::detect behavior. |
| Raw p-code mismatch | Start in fission-sleigh before interpreting NIR output. |
| NIR is wrong but p-code is right | Investigate NIR materialization, normalization, or type hint application. |
| HIR is unreadable but NIR is right | Investigate structuring, cleanup, or printer consume behavior. |
| Report counters disagree | Trace the counter back to NirBuildStats. |
| Loader identifies unsupported container | Extract an executable child explicitly instead of raw-loading the container. |
| A test passes locally but CI fails | Check LFS pulls, OS-specific paths, feature flags, and reusable workflow inputs. |
| Term | Meaning |
|---|---|
| CFG | Control-flow graph. |
| HIR | High-level intermediate representation for readable pseudocode. |
| NIR | Normalized intermediate representation with strict semantic requirements. |
| P-code | Ghidra-style low-level instruction semantics representation. |
| Sleigh | Language specification system used for instruction decode and semantics. |
| Dominance | Graph relation used to reason about control-flow ownership. |
| Post-dominance | Graph relation used to reason about exits and structured regions. |
| SCC | Strongly connected component, often used for loop analysis. |
| RegionProof | Evidence that a region can be safely promoted during structuring. |
| NirBuildStats | Canonical NIR telemetry contract. |
| FactStore | Aggregated facts and provenance consumed by decompilation contexts. |
| FID | Function identification through signatures. |
| LFS | Git Large File Storage. |
| Taint | A label on data indicating it originated from a symbolic (untrusted) source. |
| Shadow Memory | Parallel memory map tracking symbolic AST node IDs alongside concrete bytes. |
| Concolic | Execution that combines concrete runs with symbolic state to explore multiple paths. |
| HLE | High-Level Emulation: OS syscall interception without full kernel emulation. |
| TTD | Time-Travel Debugging: record/replay execution via memory and register snapshots. |
| SymExpr | Symbolic expression AST node in fission-solver. |
| SAT | Boolean satisfiability problem. Used to check if a path constraint can be fulfilled. |
- Improve x86 and x86-64 pseudocode quality on small sample binaries first.
- Continue strengthening control-flow recovery for if, else, switch, loop, break, and continue structures.
- Improve pointer, array, struct, and field-access expression recovery.
- Improve calling convention, parameter, local-variable, return-value, accumulator, and induction-variable cleanup.
- Maintain raw p-code parity gates for Sleigh changes.
- Improve FID and name recovery relative to signature ecosystems.
- Expand architecture and file-format breadth after x86/x86-64 quality is strong enough.
- Expand the pure-Rust symbolic execution engine: implement DPLL/CDCL bit-blasting in
fission-solver. - Add more P-Code taint propagation opcodes in
fission-emulator. - Connect taint-tracking results to decompiler type recovery.
- Continue the normalize
action_pipeline/ActionGroupmigration stage by stage (seePROJECT.mdfor current status and backlog); each stage's imperativerun_stage_*free function is replaced with declarative passes, validated with a real-binary before/after check.
cargo build -p fission-cli --release
cargo check --workspacecargo nextest run -p fission-pcode
cargo nextest run -p fission-corecargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings./target/release/fission_cli --help
./target/release/fission_cli info <binary>
./target/release/fission_cli list <binary>mkdir -p utils
curl -L --fail --show-error \
"https://github.com/sjkim1127/Fission/releases/download/assets-v1/fission-utils.tar.gz" \
-o /tmp/fission-utils.tar.gz
tar -xzf /tmp/fission-utils.tar.gz -C utils --strip-components=1
fission_cli resources status- Owner layer is correct.
- Targeted test captures the invariant.
- No address-specific shortcut.
- No printer-only semantic patch.
- NIR correctness is preserved.
- HIR readability impact is inspected.
- Telemetry still maps to canonical counters.
- Format detection fails closed.
- Bounds checks are explicit.
- Provenance is preserved.
- Function views use loader rules.
- No raw fallback for unknown bytes.
- Container inputs are handled as containers.
- Raw p-code parity is checked.
- ConstructTpl execution remains the success source.
- No manual opcode mapping was introduced.
- Shared-token cursor behavior is covered.
- Canonical gates are rerun.
- Counters come from canonical telemetry.
- Reports remain deterministic.
- JSON contracts are stable or versioned.
- Go/stop criteria are documented.
- Artifacts remain under expected output roots.
- Links resolve locally.
- Claims match current repo state.
- Commands are copy-pastable.
- Ownership boundaries are not blurred.
- Large assets are referenced through repo paths.
| Path | Owner meaning |
|---|---|
AGENTS.md |
Repository-level contributor instructions. |
Cargo.toml |
Workspace members and profile settings. |
crates/fission-pcode/src/nir/ |
Core NIR/HIR implementation. |
crates/fission-pcode/src/nir/structuring/ |
Structuring algorithms and region collapse. |
crates/fission-pcode/src/nir/types/ |
NIR/HIR type contracts and build stats. |
crates/fission-decompiler/ |
Decompiler orchestration and Rust-Sleigh bridge. |
crates/fission-sleigh/ |
Sleigh runtime. |
crates/fission-static/src/analysis/ |
Static facts and analysis services. |
crates/fission-loader/src/loader/ |
Binary loader implementations. |
crates/fission-automation/src/report/ |
Automation report implementation. |
crates/fission-cli/src/cli/ |
CLI command ownership. |
docs/architecture/ARCHITECTURE.md |
Architecture source of truth. |
docs/adr/ |
Architectural decision records. |
utils/ |
Checked-in resource bundle material. |
vendor/ |
Reference-only third-party material. |
- Compare raw p-code against a known-good reference.
- Check Sleigh token cursor placement.
- Check dynamic memory output materialization.
- Add a row-level canary before broad benchmark runs.
- Inspect p-code to NIR lowering.
- Check temporary, register, stack, and memory varnode handling.
- Inspect normalization rules and wave stats.
- Validate semantic preservation before HIR cleanup.
- Check calling convention source.
- Check stack slot and parameter hints.
- Check import and function hints.
- Avoid output-only substitution.
- Inspect CFG shape.
- Inspect dominance and post-dominance.
- Inspect SCC and loop facts.
- Check
RegionProofand collapse readiness. - Prefer explicit fallback over invalid structure.
- Confirm HIR is already correct.
- Keep printer consume-only.
- Avoid reconstructing missing control flow.
- Add snapshot coverage if formatting changes.
docs/CLI.mddocs/EVALUATION.mddocs/MALWARE_SAMPLE_POLICY.mddocs/PROJECT_MAP.mddocs/QUALITY_METRICS.mddocs/RELEASE.mddocs/VERSIONING.mddocs/adr/README.mddocs/architecture/ARCHITECTURE.mddocs/architecture/DECOMPILER_ACTIONS.mddocs/architecture/DIAGRAMS.mddocs/architecture/GHIDRA_PARITY_GAP_AUDIT.mddocs/architecture/XREF_INDEX.mddocs/contributing/LABELS.mddocs/onboarding/ADDING_A_LOADER_TEST.mddocs/onboarding/DEBUGGING_A_DECOMP_FAILURE.mddocs/onboarding/FIRST_30_MINUTES.mddocs/roadmap/RUST_DECOMPILER_ROADMAP.mdCONTRIBUTING.mdSECURITY.mdTHIRD_PARTY.mdLICENSE
Verify instruction semantics before diagnosing decompiler output.
- Owner check: identify the crate that owns p-code parity before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Preserve source behavior even when output is temporarily verbose.
- Owner check: identify the crate that owns nir materialization before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Improve readability only after the semantic basis is correct.
- Owner check: identify the crate that owns hir cleanup before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Promote evidence-backed types and keep provenance inspectable.
- Owner check: identify the crate that owns type hints before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Model stack slots consistently across calls, locals, and spills.
- Owner check: identify the crate that owns stack recovery before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Prefer data-flow-backed pointer reasoning over text substitution.
- Owner check: identify the crate that owns pointer recovery before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Recover indexed forms when stride and base evidence are present.
- Owner check: identify the crate that owns array recovery before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Recover field access only when layout evidence supports it.
- Owner check: identify the crate that owns struct recovery before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Derive parameters and returns from ABI facts and observed uses.
- Owner check: identify the crate that owns calling convention before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Use SCC and dominance facts before emitting structured loops.
- Owner check: identify the crate that owns loop structuring before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Use jump-table evidence and bounds before emitting switch syntax.
- Owner check: identify the crate that owns switch recovery before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Use explicit fallback when legal structure is not proven.
- Owner check: identify the crate that owns goto fallback before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Render the model; do not create semantic facts.
- Owner check: identify the crate that owns printer formatting before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Attach evidence without changing parse semantics.
- Owner check: identify the crate that owns loader identity before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Route through resource roots and path config.
- Owner check: identify the crate that owns resource lookup before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Project canonical metrics and keep outputs deterministic.
- Owner check: identify the crate that owns automation reports before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Prefer focused reusable jobs with explicit inputs.
- Owner check: identify the crate that owns ci gates before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Tag only after successful push CI for the exact commit.
- Owner check: identify the crate that owns release tags before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Consult for invariants without copying or depending on code.
- Owner check: identify the crate that owns vendor reference before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
Keep claims grounded in current source and docs.
- Owner check: identify the crate that owns documentation before editing.
- Evidence check: record the concrete function, row, sample, test, or artifact that motivated the change.
- Coverage check: add focused coverage for the invariant rather than only inspecting output manually.
- Regression check: run the smallest useful test first and then the relevant crate check.
- Reporting check: state whether the change is semantic, presentational, telemetry-only, or documentation-only.
This section expands the repository rules into concrete scenarios. It is intentionally operational: each playbook describes where to start, what to avoid, and what evidence should exist before claiming the work is done.
Start in fission-sleigh; compare emitted p-code before touching NIR or HIR.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Start in fission-pcode/src/nir; preserve exact source behavior before readability work.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Start from correct NIR; prefer cleanup passes over printer substitutions.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Start in fission-pcode/src/nir/structuring; require CFG evidence and proof completeness.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Implement a pass with declared analysis dependencies and accurate changed status.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Inspect dominance, post-dominance, and region exits before modifying emitted syntax.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Inspect SCCs, loop headers, latches, exits, and break or continue candidates.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Inspect jump table evidence, bounds, case targets, and default target handling.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Confirm the temporary has no semantic or ordering role before removing it.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Use ABI facts, call uses, stack/register evidence, and type context together.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Tie stack slots, stores, loads, and lifetimes to stable local names.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Check accumulator registers, call sites, and observed return uses.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Prefer base plus offset or indexed forms only when data-flow evidence supports them.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Require stable stride, base object, and index expression evidence.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Require layout evidence before rendering field access.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Fail closed for unknown or unsupported families; never hide uncertainty as raw bytes.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Attach evidence without changing parsing semantics or decompiler behavior.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep true imports, import thunks, undefined externals, and debug-only symbols distinct.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Preserve symbol provenance and loader-owned function views.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Route through path config and resource roots; do not embed local absolute paths.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep manifests deterministic and explain what data is required at runtime.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep signature hits evidence-backed and separate from semantic repair.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Project NirBuildStats and other canonical counters; do not redefine metrics.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Version or document the contract and keep output deterministic.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep CLI as a surface; do not fix semantics in formatting code.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Separate compatibility shims from command ownership and behavior.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Preserve backend contracts and avoid UI-specific semantic rules.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Consume shared contracts and avoid duplicate function filtering rules.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep AI assistance advisory and preserve deterministic core behavior.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep contracts explicit, stable, and separated from core crate internals.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep dynamic evidence labeled and do not blur it with static facts.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep trace-derived facts explicit and reproducible.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Document provenance, architecture, compiler, and why the fixture is useful.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Name the invariant, not just the failing sample.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Inspect semantic meaning before accepting changed text.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Compare exact rows, artifacts, scores, stdout, stderr, and feature gaps.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Trace whether the change is semantic, presentational, telemetry-only, or noise.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Inspect line count and byte count together with readability and semantics.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Check OS, LFS resources, workflow inputs, feature flags, and rust version.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Check LFS pull scope, resource roots, and CLI resource status.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Capture command, input, backtrace, crate owner, and minimal reproducer.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Check map iteration, filesystem order, random seeds, timestamps, and local paths.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Justify long-term maintenance value and avoid dependency shortcuts for core semantics.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Use it for invariants and expected behavior, not copied implementation.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Use it as reference material without creating runtime dependency.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Do not add production links, shell-outs, bindings, or copied shortcuts.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Use existing loaders and manifests instead of bypassing resource configuration.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
State owner boundaries and avoid implying surface layers own semantics.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Prefer commands and observed behavior over aspiration.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Map symptom to first owner and first command.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Separate features, fixes, quality movement, and known limitations.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Stage intended hunks only and keep unrelated dirty work untouched.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Lead with behavior change, validation, and residual risk.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Prioritize bugs, regressions, missing tests, and ownership drift.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep behavior stable unless the refactor explicitly includes a measured semantic change.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Add it only when it removes real duplication or encodes a real invariant.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Prove the active path no longer depends on it and keep compatibility expectations visible.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Check every consumer and avoid parallel meanings.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Consider CLI JSON, GUI, automation, and downstream compatibility.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep errors typed enough for users and automation to act on.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep logs useful for debugging without making tests flaky.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Measure before and after when the change affects common loops.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Check large binaries and avoid unbounded accumulation.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Use structured readers and bounds checks rather than ad hoc slicing.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Prefer explicit graph facts over lexical ordering or sample-specific assumptions.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Document convergence, lattice meaning, and budget behavior.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Make termination, changed status, and budget behavior inspectable.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep confidence and provenance visible; avoid overconfident names.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep architecture and calling convention boundaries explicit.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Validate exact sample first, then the broader x86/x86-64 family.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Do not regress x86/x86-64 priority while expanding breadth.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Do not claim semantic improvement from documentation changes.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Keep icon and README logo responsibilities separate.
- Owner: identify the crate and module that owns the behavior before editing.
- Evidence: preserve the command, binary, address, row, fixture, or artifact that motivated the change.
- Coverage: add or update the smallest test that captures the invariant.
- Validation: run the targeted check first, then the relevant crate-level check.
- Regression: compare existing passing rows or smoke lanes when behavior is user-visible.
- Report: separate mechanical change from quality improvement.
Use these questions during code review or before handing off a quality cycle.
- 01. Which layer owns this behavior?
- 02. Is the change semantic, presentational, telemetry-only, or documentation-only?
- 03. What exact row, address, sample, command, or artifact motivated the change?
- 04. What invariant does the new test encode?
- 05. Could this patch accidentally special-case one binary?
- 06. Could this have been fixed lower in the pipeline?
- 07. Does the printer now infer facts it does not own?
- 08. Does automation define a metric already owned by
NirBuildStats? - 09. Does the loader fail closed on unsupported input?
- 10. Does resource lookup go through path configuration?
- 11. Are vendor files used only as reference material?
- 12. Is any new dependency justified by a long-term bottleneck?
- 13. Is output deterministic across machines?
- 14. Are local absolute paths absent from production code?
- 15. Does the CLI remain a product surface rather than a semantic owner?
- 16. Does GUI code consume shared function views?
- 17. Are errors typed enough to debug?
- 18. Are logs useful without being test-sensitive?
- 19. Are large binaries handled without unbounded memory growth?
- 20. Does the pass pipeline converge with accurate changed flags?
- 21. Are analysis dependencies declared explicitly?
- 22. Is fallback output honest when structure is not proven?
- 23. Are type hints evidence-backed?
- 24. Are stack slots and registers handled consistently?
- 25. Is ABI behavior isolated by architecture?
- 26. Are sample fixtures documented?
- 27. Were snapshots inspected before acceptance?
- 28. Were stale caches disabled for semantic benchmark checks?
- 29. Were row-level artifacts inspected?
- 30. Did any existing pass row regress?
- 31. Was the release CLI rebuilt when benchmark validation needed it?
- 32. Does CI pull the right LFS resources?
- 33. Are docs updated when public behavior changes?
- 34. Are limitations stated plainly?
Use this template when handing off a substantial decompiler-quality change.
- Problem:
- Root cause:
- Owner layer:
- Implementation summary:
- Tests run:
- Benchmarks or row checks:
- Artifacts inspected:
- Quality result:
- Regressions checked:
- Known risks:
- Follow-up work:
