test/mix/tasks/openagents_promises_backfill_test.exs

58e6347eeb72 · 3 KB

defmodule Mix.Tasks.Openagents.Promises.BackfillTest do
  use OpenAgents.DataCase

  alias OpenAgents.Issues
  alias OpenAgents.Projects

  import ExUnit.CaptureIO

  test "backfills the curated registry idempotently" do
    repository =
      repository_fixture(%{
        owner: "BackfillOrg",
        name: "backfill-promises",
        visibility: "public"
      })

    {:ok, project} =
      Projects.create_project(repository, %{
        title: "Promises",
        owner: "OpenAgents",
        state: "open"
      })

    args = [
      "--owner",
      repository.owner,
      "--repo",
      repository.name,
      "--project-number",
      to_string(project.number)
    ]

    first_output = capture_io(fn -> Mix.Tasks.Openagents.Promises.Backfill.run(args) end)
    assert first_output =~ "Backfilled 6 promise(s); skipped 0."
    assert length(Projects.list_project_fields(project)) == 1
    assert length(Projects.list_project_items(project)) == 6
    assert length(Issues.list_issues(repository, state: "all")) == 6
    assert Enum.all?(Issues.list_issues(repository, state: "all"), &(&1.state == "open"))

    Mix.Task.reenable("openagents.promises.backfill")

    second_output = capture_io(fn -> Mix.Tasks.Openagents.Promises.Backfill.run(args) end)
    assert second_output =~ "Backfilled 0 promise(s); skipped 6."
    assert length(Projects.list_project_fields(project)) == 1
    assert length(Projects.list_project_items(project)) == 6
    assert length(Issues.list_issues(repository, state: "all")) == 6
  end

  test "skips an unresolved LIVE promise and continues with later promises" do
    repository =
      repository_fixture(%{
        owner: "BackfillSkipOrg",
        name: "backfill-skip",
        visibility: "public"
      })

    {:ok, project} =
      Projects.create_project(repository, %{
        title: "Promises",
        owner: "OpenAgents",
        state: "open"
      })

    path =
      Path.join(
        System.tmp_dir!(),
        "promises-curated-#{System.unique_integer([:positive, :monotonic])}.json"
      )

    File.write!(
      path,
      Jason.encode!([
        %{
          "id" => "unresolved_live",
          "state" => "LIVE",
          "problem" => "A problem",
          "claim" => "A claim",
          "scope" => "A scope",
          "acceptance_criteria" => ["A criterion"],
          "success_metrics" => ["A metric"],
          "owner" => "OpenAgents",
          "target" => "2026-12-31",
          "evidence" => [
            %{
              "kind" => "accepted_outcome",
              "decision_receipt_ref" => "missing-decision"
            }
          ]
        },
        %{
          "id" => "later_gated",
          "state" => "GATED",
          "problem" => "A problem",
          "claim" => "A claim",
          "scope" => "A scope",
          "acceptance_criteria" => ["A criterion"],
          "success_metrics" => ["A metric"],
          "owner" => "OpenAgents",
          "target" => "2026-12-31",
          "gate" => %{
            "missing" => "A receipt",
            "owner" => "OpenAgents",
            "next_review" => "2026-09-01"
          },
          "evidence" => []
        }
      ])
    )

    previous = Application.get_env(:openagents, :promises_curated_path)
    Application.put_env(:openagents, :promises_curated_path, path)

    on_exit(fn ->
      if previous do
        Application.put_env(:openagents, :promises_curated_path, previous)
      else
        Application.delete_env(:openagents, :promises_curated_path)
      end

      File.rm(path)
    end)

    args = [
      "--owner",
      repository.owner,
      "--repo",
      repository.name,
      "--project-number",
      to_string(project.number)
    ]

    output = capture_io(fn -> Mix.Tasks.Openagents.Promises.Backfill.run(args) end)

    assert output =~ "Skipped unresolved_live: LIVE gate failed:"
    assert output =~ "Backfilled 1 promise(s); skipped 1."
    assert length(Projects.list_project_items(project)) == 1
    assert length(Issues.list_issues(repository, state: "all")) == 2
  end
end