{
  "jimothyPipeline": 1,
  "name": "Month-end variance commentary",
  "description": "Compares the two newest trial balance exports, explains material variances, and saves the report after you approve.",
  "icon": "workflow",
  "color": "#22c55e",
  "repo": {
    "mode": "inplace",
    "localPath": ""
  },
  "concurrency": 1,
  "variables": {
    "company": "Acme Inc.",
    "thresholdPercent": "10",
    "minAmount": "5000",
    "reportsFolder": "reports"
  },
  "steps": [
    {
      "id": "find",
      "name": "Find exports",
      "type": "shell",
      "description": "Lists the two newest CSV files in the folder: this period and the last one.",
      "timeoutMinutes": 2,
      "command": "files=$(ls -t -- *.csv 2>/dev/null | head -2); [ \"$(printf '%s\\n' \"$files\" | grep -c .)\" -eq 2 ] || { echo \"Put this month's and last month's trial balance exports (.csv) in $(pwd)\"; exit 1; }; printf '%s\\n' \"$files\""
    },
    {
      "id": "analyze",
      "name": "Analyze variances",
      "type": "agent",
      "description": "Joins the two periods with a script, flags material changes and explains them from the files in the folder.",
      "harnessId": "claude-code",
      "model": "sonnet",
      "dependsOn": [
        "find"
      ],
      "timeoutMinutes": 30,
      "prompt": "You are preparing month-end variance commentary for {{vars.company}}.\n\nThe two newest trial balance exports in the current folder are, newest first:\n{{steps.find.output}}\nThe first is the current period and the second is the prior period.\n\n1. Inspect both files to learn their columns. Write and run a small script (Python or awk) that joins the accounts by account number and computes, for each account: prior balance, current balance, change and % change. Never do arithmetic in your head; every number you report must come from the script's output.\n2. Check that debits equal credits in each file and report the totals.\n3. Flag accounts where the absolute change is at least {{vars.minAmount}} AND the absolute % change is at least {{vars.thresholdPercent}}%.\n4. For each flagged account, explain the change in one to three sentences. Use the other files in this folder (GL detail, accrual schedules, invoices, notes) as evidence and name the file you used. If nothing in the folder explains it, write \"Unexplained: ask the account owner\" instead of guessing.\n\nDo not modify or delete any existing file. Your final answer is a Markdown report with these sections and nothing else:\n# Variance commentary: <current period>\n## Summary (three bullets)\n## Flagged accounts (table: Account, Name, Prior, Current, Change, %)\n## Commentary (one sub-heading per flagged account)\n## Checks (debit and credit totals for each file)\n{{#if steps.review.output}}\n\nA reviewer checked your previous report. Fix every problem it lists:\n{{steps.review.output}}{{/if}}{{#if steps.approve.output}}\n\nYour previous draft was rejected with this feedback. Rewrite it:\n{{steps.approve.output}}{{/if}}"
    },
    {
      "id": "review",
      "name": "Check the numbers",
      "type": "agent",
      "description": "A second model checks the arithmetic and that every claim is backed by the data.",
      "harnessId": "anthropic-api",
      "model": "claude-opus-5",
      "dependsOn": [
        "analyze"
      ],
      "timeoutMinutes": 10,
      "passPattern": "VERDICT:\\s*APPROVE",
      "loopBackTo": "analyze",
      "maxLoops": 2,
      "prompt": "Review this variance report before it goes to the controller.\n\n{{steps.analyze.output}}\n\nCheck that:\n- every Change equals Current minus Prior, and every % equals Change divided by the absolute Prior, to one decimal place;\n- every account in the table has commentary, and every account in the commentary is in the table;\n- the commentary only states causes it attributes to a named file, or says \"Unexplained\";\n- the debit and credit totals in Checks balance.\n\nList each problem you find with the account it affects. End with exactly one line: VERDICT: APPROVE if there are no problems, otherwise VERDICT: CHANGES_REQUESTED."
    },
    {
      "id": "approve",
      "name": "Controller sign-off",
      "type": "approval",
      "description": "Shows you the report. Reject with a comment and it is rewritten with your notes.",
      "dependsOn": [
        "review"
      ],
      "loopBackTo": "analyze",
      "maxLoops": 3,
      "approvalMessage": "Save this variance report? Reject with a comment to have it rewritten.\n\n---\n\n{{steps.analyze.output}}"
    },
    {
      "id": "save",
      "name": "Save report",
      "type": "shell",
      "description": "Writes the approved report to the reports folder, named after the month.",
      "dependsOn": [
        "approve"
      ],
      "timeoutMinutes": 2,
      "command": "mkdir -p {{vars.reportsFolder}} && f={{vars.reportsFolder}}/variance-$(date +%Y-%m).md && printf '%s\\n' {{steps.analyze.output}} > \"$f\" && echo \"Saved $(pwd)/$f\""
    }
  ]
}