Skip to content

Bug: find_active_run treats validation-report.json as a second live loop run #36

Description

@hpieris-dm

Problem

find_active_run (src/dmx/loop_state.py) decides which loop is active by globbing every *.json file under .dmx/jobs/{job_id}/ and keeping any file whose status is not complete or failed:

for path in sorted(job_dir.glob("*.json")):
    data = json.loads(path.read_text(encoding="utf-8"))
    if data.get("status") in _TERMINAL_STATUSES:
        continue
    candidates.append((data.get("loop_name", ""), data.get("task_id", "")))

Missing status is treated as non-terminal.

The bundled validate skill is required to write a sidecar artifact at exactly that path: .dmx/jobs/{job_id}/validation-report.json. spec_adherence (src/dmx/validators/spec_adherence.py) reads that file. The expected shape is commit SHA, scope items, regressions, and edge cases — not loop runtime state. There is no status, loop_name, or task_id.

So a correct validate run leaves two JSON files in the job directory:

  • validate-{task_id}.json — the real run (running / paused)
  • validation-report.json — an artifact with no status

loop_advance / loop_continue then see two non-terminal runs and raise AmbiguousActiveRun (or stall until a human edits the artifact). The workaround in this trial was to stamp "status": "complete" onto validation-report.json, which is a lie: that file is not a loop.

This showed up on the bundled spec → plan → dev → validate → release path with no custom loops or extra files. Job gh-1 in tasks-api-scrap.

Related: the GH-9 change that removed .dmx/loop-state.json and made the job directory the source of truth. That scan never excluded skill artifacts that the runtime itself tells the agent to write there (loop_tools._skill_instruction even names validation-report.json as the example).

Proposal

Not mutually exclusive:

  1. Only treat files that look like loop state as runs. Require loop_name, task_id, and status before a JSON file is a candidate. Anything else is ignored. Cheap, matches the {loop_name}-{task_id}.json naming already used by write_state.
  2. Do not write artifacts into the run directory. Put validation-report.json under .dmx/jobs/{job_id}/artifacts/ (or beside .dmx/ outside jobs/). Update spec_adherence and dmx-validate.md Step 9.
  3. If the glob stays, exclude known artifact names (validation-report.json). Weaker than (1); the next sidecar will hit the same bug.

(1) is the real fix. (2) is the cleaner layout. Tests should start a validate loop, write a report without status, and assert find_active_run still returns the validate run — not AmbiguousActiveRun.

Out of scope

  • Changing the report's scope/edge-case schema
  • Warning-vs-success chaining on dev / coverage_threshold

Acceptance criteria

  • find_active_run ignores .dmx/jobs/{job_id}/validation-report.json even when that file has no status
  • A validate loop can loop_advance after the skill writes the report, without editing the report
  • Two real loop state files that are both non-terminal still raise AmbiguousActiveRun
  • spec_adherence still finds the report

Context

  • src/dmx/loop_state.pyfind_active_run
  • src/dmx/loop_tools.py_skill_instruction (artifact path)
  • src/dmx/validators/spec_adherence.py
  • src/dmx/skills/workflow/4-validate/dmx-validate.md Step 9

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions