Skip to content

PROJECT.md is never clean: render timestamp + duplicate detour-log rows create a commit loop #81

Description

@cfdude

Two defects that compound into an unbreakable loop

1. Last rendered: timestamp makes the generated file dirty on every render

-> Last rendered: 2026-08-10T23:53:14.916Z
+> Last rendered: 2026-08-11T00:09:25.444Z

PROJECT.md is generated and committed, so any render — including the one the post-commit hook triggers — rewrites this line and leaves the working tree dirty. There is no state in which git status is clean after a render.

2. The detour log accumulates duplicate rows for the same SHA

Measured in one repo right now — 8 rows, 4 distinct SHAs:

3 | `d249112` | DETOUR-COMMIT
2 | `ea50c52` | DETOUR-COMMIT
2 | `9883d39` | DETOUR-COMMIT
1 | `8e7a257` | DETOUR-COMMIT

ea50c52 is logged three times with different timestamps, twice with an empty note:

| 2026-08-10T16:29:04.686Z | `ea50c52` | DETOUR-COMMIT | ... | chore(pm): re-render PROJECT.md |
| 2026-08-10T22:15:34.211Z | `ea50c52` | DETOUR-COMMIT | ... |  |
| 2026-08-10T22:32:31.209Z | `ea50c52` | DETOUR-COMMIT | ... |  |

The log appears keyed on time rather than SHA, so running against an unchanged HEAD appends another row instead of being idempotent.

The loop

  1. Commit anything → the hook logs a DETOUR-COMMIT row and bumps the render timestamp
  2. PROJECT.md is now dirty
  3. Commit PROJECT.md → step 1 again, with a new row for the SHA of the render commit itself

Each iteration adds a row and a fresh timestamp. In one working session this produced 8 rows for 4 real commits, several describing commits whose only content was re-rendering the file the row lives in.

Practical effect: git status is never clean, so "commit everything, then verify clean" stops being a usable check — and the detour log, which exists to show what happened during a detour, fills with rows about its own regeneration.

Suggested fixes

  1. Drop the timestamp from the committed file, or move it to .conductor/render-stamp.json (which already exists and is the natural home). A generated artifact that changes on every generation cannot be version-controlled cleanly.
  2. Make detour logging idempotent on SHA — one row per SHA; an unchanged HEAD should be a no-op, not an append.
  3. Skip logging commits whose only change is PROJECT.md — they are the plugin's own bookkeeping, not detour work, and they are what closes the loop.

Either (1) or (3) alone breaks the loop; (2) fixes the log independently.

Engine 0.25.0. Related: #79 (add-epic --notes accepted and discarded) and #80 (gate-guard prints a refusal then applies the change) — same family: the plugin reporting one thing while doing another.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions