Lifestyle

A complete debugging workflow

Debugging starts with a reproducible symptom, narrows causes with evidence and verifies the fix. Give the input, exact step, expected behavior and observed failure instead of only saying the site is broken.

About 14 min read · Practice 25 min

Workflow illustration, not a product screenshot.
Image: Mokaair (© Mokaair)
Back to directory:Codex learning hub: tutorial directory

Practical · Desktop / CLI / VS Code / JetBrains / cloud

On this page
  1. Goal and preparation
  2. Step 1: Fix the faulty version and reproduction steps
  3. Step 2: Isolate a reproduction without the UI
  4. Step 3: Request a minimal repair and explanation
  5. Step 4: Regress using the same evidence
  6. Debugging habits, restoration and delivery

Goal and preparation

Lessons and resources mentioned here:

Step 1: Fix the faulty version and reproduction steps

Copy the five broken files from the ZIP into new codex-bug-lab and preserve the original. Completed has a reversed condition, unlike start's missing implementation. Verify the directory in your editor terminal with Get-Location or pwd and run existing tests, expecting two passes and one failure.

Terminal: baseline tests · sh
node --test core.test.mjs

For the UI, start preview from this folder: on Windows run py -m http.server 4173 --bind 127.0.0.1; on macOS/Linux run python3 -m http.server 4173 --bind 127.0.0.1. Open http://127.0.0.1:4173. Record any fictional data you want to keep, use Reset practice data, select All tasks, and confirm an empty list. Then add Read followed by Build, complete only Read and select Completed. Expected Read, actual Build. Record this exact sequence. Resetting practice data does not restore source files.

Include environment, starting state, steps, expected, actual and evidence without prematurely blaming cache. Fill the template from observations with your date and test result. If your UI differs, verify preview location and fixture before treating the article's expectation as your own measurement.

Document template: bug report · markdown
# Bug: Completed shows unfinished tasks
Environment/date: fill from this run
Fixture: broken copied to codex-bug-lab
Steps: reset practice data; add Read and Build; complete Read; select Completed.
Expected: Read only.
Observed: Build only, if reproduced.
Baseline: node --test core.test.mjs; fill actual result.
Scope: keep UI, storage format, ordering and tests unchanged.
Root cause: not confirmed yet.
Unperformed checks: list explicitly.

Step 2: Isolate a reproduction without the UI

Add root repro.mjs below. It directly passes one finished and one unfinished task to visibleTasks, bypassing storage, DOM, browser cache and networking. Run node repro.mjs in another terminal. The faulty version prints actual b then exits nonzero because a was expected. This assertion failure is evidence to retain.

New file: repro.mjs · javascript
import assert from "node:assert/strict";
import { visibleTasks } from "./core.mjs";

const tasks = [
  { id: "a", title: "Read", completed: true },
  { id: "b", title: "Build", completed: false },
];
const actual = visibleTasks(tasks, "completed").map((task) => task.id);
console.log("Completed IDs:", JSON.stringify(actual));
assert.deepEqual(actual, ["a"]);
console.log("Reproduction passed.");
Terminal: minimal reproduction · sh
node repro.mjs

The core returns the wrong result without a browser, so cache and button events are unnecessary to reproduce this defect. That does not prove all UI is correct, but directs investigation to Completed. Ask Codex to explain why the predicate selects unfinished tasks before fixing it; a lucky reload is not a root-cause finding.

Separate a behavior failure from an environment failure

If node repro.mjs reports ERR_MODULE_NOT_FOUND, it never reached the Completed assertion: check the current folder and core.mjs filename. For SyntaxError, check that you pasted the complete program. This bug is reproduced only when the program loads, prints b and fails because it expected a. A first-run pass does not mean you repaired it; you may have copied expected. Record the command, exit code, actual output and copy location instead of merely “red” or “failed”.

Step 3: Request a minimal repair and explanation

On desktop, create a Codex task for codex-bug-lab. With CLI, verify that folder and run codex there. Then send the scoped request below. Preserve existing tests and repro.mjs for before/after comparison. Remove the now-stale deliberate-bug comment when fixing the condition, but do not refactor unrelated functions, edit UI or switch frameworks. Require the baseline failure if the agent has not inspected it.

Codex prompt: scoped repair · text
Fix the reproduced Completed-filter bug in this codex-bug-lab.
First read core.mjs, core.test.mjs and repro.mjs. Run node repro.mjs and node --test core.test.mjs to confirm the current failure.
Explain the predicate error using the actual a/b IDs. Modify only the completed predicate in core.mjs and remove its obsolete deliberate-bug comment. Do not change tests, repro.mjs, active behavior, storage or UI.
Rerun both commands, inspect the final diff and report actual results. Browser checks must be marked NOT RUN unless actually performed. Do not publish or deploy.

Completed incorrectly uses !task.completed, selecting unfinished items like Active. Change only its line below to task.completed; keep Active's negation. Swapping dropdown labels may look plausible but leaves repro failing, distinguishing a cosmetic workaround from the behavioral repair.

Reference repair: Completed branch · javascript
if (filter === "completed") return tasks.filter((task) => task.completed);

Step 4: Regress using the same evidence

After repair, repro should print ["a"] and Reproduction passed with exit 0, and all three existing tests should pass. Repeat the original UI steps: Completed Read, Active Build, All both. Prove the original failure is gone with identical input before adding empty-list or uncompletion cases.

EvidenceBeforeAfter
Minimal reprob, failed assertiona, exit 0
Existing core tests2 pass, 1 fail3 pass, 0 fail
Completed UIBuildRead
Active/AllRecord actual resultBuild/both retained
Unperformed checksExplicitly NOT RUNDo not automatically mark passed

Inspect core.mjs diff for unchanged addTask, decodeTasks and test expectations. Request commands, exit status and failure summaries if a “fixed” claim lacks evidence; record blockers when execution is unavailable. Passing commands do not replace UI checks by you or a browser-capable agent, with platform and preview URL recorded.

Check uncompleting a task and empty lists

After the original reproduction passes, create regression.mjs with the program below and run node regression.mjs. It checks Completed ID a, uncompletes a, then expects empty Completed and Active IDs a/b. It also checks unchanged input and all three empty-list filters. Expect Regression passed and exit code 0. This is a standalone assertion program; it does not automatically increase the test count of node --test core.test.mjs.

File: regression.mjs · javascript
import assert from "node:assert/strict";
import { toggleTask, visibleTasks } from "./core.mjs";

const tasks = Object.freeze([
  Object.freeze({ id: "a", title: "Read", completed: true }),
  Object.freeze({ id: "b", title: "Build", completed: false }),
]);
const ids = (items, filter) => visibleTasks(items, filter).map((task) => task.id);
assert.deepEqual(ids(tasks, "completed"), ["a"]);
const changed = toggleTask(tasks, "a");
assert.deepEqual(ids(changed, "completed"), []);
assert.deepEqual(ids(changed, "active"), ["a", "b"]);
assert.deepEqual(ids(changed, "all"), ["a", "b"]);
assert.deepEqual(tasks.map((task) => task.completed), [true, false]);
for (const filter of ["all", "active", "completed"]) {
  assert.deepEqual(ids(Object.freeze([]), filter), []);
}
console.log("Regression passed.");
Terminal: run boundary regression · sh
node regression.mjs

Keep regression.mjs when restoring the original broken/core.mjs for the reset exercise. It should fail again with a nonzero exit, consistent with repro.mjs returning b. If you changed tests, labels or storage to get a green result, return to the saved originals and repeat the single repair; record the discarded hypothesis in the . Full regression still requires actual UI and reload checks; leave them unperformed until run.

Debugging habits, restoration and delivery

Change one testable hypothesis at a time and record attempts/results so the next task does not repeat failed fixes. If evidence points elsewhere, narrow scope again instead of forcing this one-line answer. Timing, accounts and networks can produce different real defects; remove private data from reproductions before sharing with Codex.

Deliver the report, minimal repro, cause, scoped diff and regression table. To repeat, stop your preview and restore only broken/core.mjs, keeping repro.mjs; it should fail again and original tests return to two passes/one failure. For fuller cases see . Diagram 1 reproduces, 2 diagnoses/repairs, 3 regresses. Local reference validation is distinct from your Codex conversation and platform execution.

20. A complete debugging workflow — Workflow illustration, not a product screenshot. Reproduce → Fix → Regression
20. A complete debugging workflow — Workflow illustration, not a product screenshot. Reproduce → Fix → Regression · Image: Mokaair (© Mokaair)
Read the full description

Reproduce to Fix to Regression

Back to directory

  • Lifestyle

    Codex learning hub: tutorial directory

    A planned 60-lesson, ten-unit Codex curriculum, from setup and your first task to MD instructions and advanced integrations. Find your next lesson by experience, platform, goal or command; unpublished entries show their status.

  • Lifestyle

    Worktrees and isolated tasks

    A Git worktree gives one repository multiple working directories on different branches. It isolates file edits, but databases, ports and external services may still be shared. File isolation is not full resource isolation.

  • Lifestyle

    Workshop: build a small website

    Plan and build the Small Steps task website from brief.md, with adding, completing, deleting, filtering and local persistence. Separate HTML, CSS, data functions, UI events and tests, verify with Node and browser checks, and document restart and recovery steps.

  • Lifestyle

    Usage and efficiency: reducing rework

    Record task conditions, model options, time and outcomes to reduce unnecessary retries and excess context.

Latest travel guides

Sources

Lifestyle