{
  "name": "Payday Outlook",
  "status": "Unpublished availability candidate",
  "price": "Free; no account or runtime API",
  "inputs": "One explicit two-decimal currency/account, supplied end-of-day balance/date, known dated income/outgoings and explicit occurrence/checkpoint decisions",
  "outputs": "Qualified daily projected closing balances, low point, retained history, editable JSON plan and browser print view",
  "limits": [
    "90 days",
    "60 rules",
    "400 overrides",
    "20 later checkpoints",
    "100 history records",
    "256 KiB UTF-8 JSON",
    "No bank validation, intraday guarantee, financial advice or safe-to-spend claim"
  ],
  "data": "Entries and opened plan contents remain in the page; Save downloads JSON. App has no analytics/cookies/background storage. On a Cloudflare-hosted version, Cloudflare receives normal page/asset request metadata/security handling and hosting may use security cookies. No plan values in URLs.",
  "callable": {
    "module": "./core.mjs",
    "pure_exports": [
      "create",
      "money",
      "date",
      "scheduled",
      "occurrences",
      "forecast",
      "addRule",
      "editRule",
      "removeRule",
      "override",
      "checkpoint",
      "parse",
      "serialize"
    ],
    "read_only_browser": "window.PaydayOutlook.inspect(), .forecast(), .status()",
    "mutations": "Labelled visible forms; pure module functions return a new master",
    "arguments": {
      "create": {
        "arguments": [
          {
            "title": "Synthetic plan",
            "currency": "AUD",
            "date": "2026-10-20",
            "balance": 75000,
            "horizon": 90
          }
        ],
        "returns": "A new schema1 master; date is supplied end-of-day checkpoint. Forecast starts next date."
      },
      "addRule": {
        "arguments": [
          "master",
          {
            "id": "pay",
            "label": "Pay",
            "direction": "in",
            "amount": 155000,
            "frequency": "fortnightly",
            "start": "2026-10-23",
            "end": null
          }
        ],
        "returns": "New master, original unchanged. Frequency is once/weekly/fortnightly/monthly/yearly; month-end/anniversary clamps retain anchor."
      },
      "override": {
        "arguments": [
          "master",
          {
            "ruleId": "pay",
            "scheduled": "2026-11-06",
            "date": "2026-11-10",
            "amount": 155000,
            "skipped": false,
            "reason": "Synthetic one-off delay"
          }
        ],
        "returns": "New master keyed by ruleId+original scheduled date; later repeats unchanged. Unpaid effective date must be after current checkpoint."
      },
      "checkpoint": {
        "arguments": [
          "master",
          "2026-11-08",
          40000,
          [
            {
              "key": "repair@2026-11-06",
              "decision": "deferred",
              "date": "2026-11-09"
            }
          ]
        ],
        "decision_shape": "Illustrative single decision, not a complete array. Supply exactly one decision for every item from occurrences(master,newDate): key=ruleId@scheduled; decision=included/skipped/deferred; date required for deferred and must be later than checkpoint within90days. Operator chooses; none is assumed included.",
        "returns": "New master with prior checkpoint/projection/difference/decisions/history retained. Deferred past-original items carry forward."
      },
      "forecast": {
        "arguments": [
          "master"
        ],
        "returns": "Derived days/low/closing/items; earliest tied low is projected end-of-day only."
      },
      "serialize_parse": {
        "serialize": "serialize(master) returns exact validated two-space JSON plus newline withinUTF8bytecap.",
        "parse": "parse(text) validates bytes/schema/full forecast before returning supplied saved records; never proves bank authenticity."
      }
    },
    "errors": "Invalid dates/money/identity/schema/limits/forecast or unresolved checkpoint throw Error. Mutators return new validated masters and preserve supplied input on refusal; caller must catch Error. No automatic file/network/storage action."
  },
  "compatibility": "Own local Firefox synthetic UI journey evidenced; no external MCP/protocol/client compatibility claim.",
  "provenance": "Built with AI assistance; no human preference/financial outcome claim.",
  "bounds": {
    "currency": [
      "AUD",
      "CAD",
      "EUR",
      "GBP",
      "NZD",
      "USD"
    ],
    "dates": "ValidYYYY-MM-DD,2000-01-01..2100-12-31; entire forecast must end<=2100-12-31",
    "horizon_days": {
      "min": 1,
      "max": 90
    },
    "minor_unit_amounts": "Safe integers; rule/override1..99999999900; checkpoint/aggregate projected balance-99999999900..99999999900",
    "rules_max": 60,
    "exceptions_max": 400,
    "later_checkpoints_max": 20,
    "history_max": 100,
    "UTF8_pretty_JSON_with_newline_max_bytes": 262144
  }
}
