{
  "schemaVersion": 1,
  "slug": "dog-age-calculator",
  "category": "health",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "5f63ea46d4e634d7133b87ba3a2a7e8fd9c1e82d0bae950b01fa4cae1d12c84c",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/dog-age-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "H = 15 × min(A,1) + 9 × min(max(A−1,0),1) + 5 × max(A−2,0)",
    "vars": [
      [
        "A",
        "dog age, years"
      ],
      [
        "H",
        "human-equivalent age"
      ]
    ],
    "note": "A includes months ÷ 12. General rule of thumb only: 15 human years for dog year one, 9 for year two, then about 5 per year; not a health or lifespan assessment."
  },
  "externalEvidence": {
    "reviewedAt": "2026-10-28",
    "sources": [
      {
        "name": "AVMA — Senior pet age and care",
        "url": "https://www.avma.org/resources-tools/pet-owners/petcare/senior-pets"
      }
    ],
    "referenceRole": "context",
    "implementationHash": "5f63ea46d4e634d7133b87ba3a2a7e8fd9c1e82d0bae950b01fa4cae1d12c84c",
    "basis": "H = 15 × min(A,1) + 9 × min(max(A−1,0),1) + 5 × max(A−2,0) P1 consolidation retains the core model and adds input modes or derived outputs. The migration report records the input/output union and known-answer checks.",
    "limitations": "The references provide context and limitations. They do not validate this page’s illustrative multipliers, lookup values or predictions. Added display totals and migration adapters are implementation behavior, not independently validated claims."
  },
  "contract": {
    "compute": "const mergedResult=(()=>{if((true&&![\"age\", \"birthdate\"].includes(String(ageInput))))return{__error:'inputError'};\nif(([\"age\"].includes(String(ageInput))&&(!Number.isFinite(dogYears)||dogYears<0||dogYears>30))||([\"age\"].includes(String(ageInput))&&(!Number.isFinite(dogMonths)||dogMonths<0||dogMonths>11)))return{__error:'inputError'};\nconst parse=s=>{const d=new Date(s+'T00:00:00Z');return /^\\d{4}-\\d{2}-\\d{2}$/.test(s)&&Number.isFinite(d.getTime())&&d.toISOString().slice(0,10)===s?d:null;};let age;if(ageInput==='birthdate'){const b=parse(birthDate),t=parse(today);if(!b||!t||b>t)return{__error:'inputError'};age=(t-b)/86400000/365.2425;}else if(ageInput==='age'){if(!Number.isFinite(dogYears)||dogYears<0||dogYears>30||!Number.isInteger(dogMonths)||dogMonths<0||dogMonths>11)return{__error:'inputError'};age=dogYears+dogMonths/12;}else return{__error:'inputError'};const humanYears=age<=1?age*15:age<=2?15+(age-1)*9:24+(age-2)*5;return{humanYears,dogAgeYears:age};\n})();return mergedResult.__error?{\"humanYears\":null,\"dogAgeYears\":null,...mergedResult}:mergedResult;",
    "inputs": [
      {
        "name": "ageInput",
        "type": "select",
        "default": "age",
        "options": [
          {
            "value": "age"
          },
          {
            "value": "birthdate"
          }
        ]
      },
      {
        "name": "dogYears",
        "type": "number",
        "default": 5,
        "min": 0,
        "max": 30,
        "step": 0.01,
        "slider": true,
        "showWhen": {
          "ageInput": [
            "age"
          ]
        },
        "requiredValue": true,
        "strictRange": true
      },
      {
        "name": "dogMonths",
        "type": "number",
        "default": 0,
        "min": 0,
        "max": 11,
        "step": 1,
        "slider": true,
        "showWhen": {
          "ageInput": [
            "age"
          ]
        },
        "requiredValue": true,
        "strictRange": true
      },
      {
        "name": "birthDate",
        "type": "date",
        "default": "@today-6y",
        "step": 1,
        "showWhen": {
          "ageInput": [
            "birthdate"
          ]
        },
        "requiredValue": true,
        "preserveEmpty": true
      },
      {
        "name": "today",
        "type": "date",
        "default": "@today",
        "step": 1,
        "showWhen": {
          "ageInput": [
            "birthdate"
          ]
        },
        "requiredValue": true,
        "preserveEmpty": true
      }
    ],
    "outputs": [
      {
        "name": "humanYears",
        "precision": 1,
        "unit": "years"
      },
      {
        "name": "dogAgeYears",
        "precision": 2,
        "unit": "years"
      }
    ],
    "interpret": null
  }
}
