Skip to content

[FEATURE] Idempotence for labels/comments/generated outputs #113

Description

@koydas

🎯 Goal

Make all write-side operations idempotent so reruns with the same inputs do not create duplicates or inconsistent state.

📍 Context

  • Repo: autonomous-dev-loop
  • Domain: Re-runnability
  • Component: scripts/lib/output_writer.mjs, scripts/manage_labels.mjs

🚀 Description

Idempotence is already partially applied in this repo but inconsistently:

  • upsert_issue_validation_comment.mjs — upserts by bot-marker ✅
  • auto_fix_pr.mjs label creation — tolerates HTTP 422 (existing label) ✅
  • output_writer.mjs — overwrites files unconditionally without checking expected state ❌
  • manage_labels.mjs — label operations need idempotence verification ❌

A re-run caused by a transient failure or manual retry must produce the same final state as the first run.

🧩 Scope

In:

  • scripts/lib/output_writer.mjs: before writing a file, check if its content is already identical; skip the write if so (use fs.readFile + strict equality).
  • scripts/manage_labels.mjs: verify each label operation is upsert-safe — add only if not already present, remove only if present; no-op otherwise.
  • Define a run-context idempotency key composed of { issueNumber, commitSha, step } to scope write guards.
  • Document the idempotency contract for each write operation (inline, one line per function).

Out:

  • Workflow trigger strategy changes.
  • Changes to read-only operations.

🧪 Acceptance criteria

  • Functional

    • Running output_writer.mjs twice with identical inputs produces exactly one file write on disk (second call is a no-op).
    • Running manage_labels.mjs twice with the same label set leaves the PR/issue in the same label state (no duplicate add, no spurious remove).
  • Edge cases

    • If a file write is interrupted mid-run and the file is partially written, the next run overwrites it correctly (partial state is not treated as "already applied").
    • Removing a label that does not exist is a silent no-op, not an error.
    • Adding a label that already exists is a silent no-op, not an error (HTTP 422 already handled in auto_fix_pr.mjs — extend same pattern).
  • Tests

    • Unit: calling writeGeneratedFiles twice with the same changes array results in fs.writeFile being called only once per file (second call skipped).
    • Unit: manage_labels add operation with a label already present does not call the GitHub API a second time.
    • Smoke: re-running a full generation flow with the same issue does not create duplicate comments or labels.
    • Non-regression: no writes occur outside the allowed output scope after the change.

⚙️ Constraints

  • Preserve current business behavior — this is hardening only, no functional changes.
  • The skip-write check must use strict byte-level equality, not semantic comparison.
  • No new runtime dependencies.

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

    enhancementNew feature or requestready-for-devIssue validated and ready for automated implementation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions