# get_nonrecurring_scoping_accuracy

## What it answers

Compare non-recurring actual hours or ABR with total project scope, including task categories for hours. Defaults to client grouping and Active/Complete statuses. Returns at most 100 rows by default (maximum 500); use offset for further pages. Actuals cover all recorded monthly time, not only project dates. Includes diagnostics, timer coverage and time/mapping import freshness. groupBy accepts serviceLine, client, project or product (default client); statuses accepts Pending, Active or Complete (default Active/Complete). A project with a blank Status counts as Active, so it is included whenever Active is selected, including by default. Bounded rows have kind: summary or project and camel-case attributes serviceLine, client, project, product; do not sum summary and project rows together. Use pagination.nextOffset as offset with the same effective options. Read report.diagnostics.unmatchedProjectNames and report.latestTimerData. Read definitions, window coverage, diagnostics and time/mapping freshness before interpreting actuals against plan. Also read report.diagnostics.unmatchedTimeRowCount (non-recurring only). Read parakeeto://methodology for shared response conventions and INVALID_ARGUMENT guidance.

Read-only.

## Arguments

| Argument | Type | Required | Default | Allowed values |
| --- | --- | --- | --- | --- |
| `account` | string (uuid) | no | — | — |
| `includeDefinitions` | boolean | no | `true` | — |
| `measure` | string | yes | — | `"hours"`, `"abr"` |
| `limit` | integer | no | `100` | `minimum: 1`; `maximum: 500` |
| `offset` | integer | no | `0` | `minimum: 0`; `maximum: 9007199254740991` |
| `groupBy` | string | no | `"client"` | `"serviceLine"`, `"client"`, `"project"`, `"product"` |
| `statuses` | array of string | no | `["Active","Complete"]` | — |

## Returned fields

The result is an envelope: `ok: true` with `data`, or `ok: false` with `error`. Error codes: `MODEL_CALCULATOR_ACCESS_REQUIRED`, `PAYROLL_GRID_MISSING`, `PAYROLL_GRID_REQUIRED`, `PROJECT_GRID_REQUIRED`, `EXPENSE_GRID_REQUIRED`, `PAYROLL_ENTRY_REFERENCE_STALE`, `ACCOUNT_NOT_FOUND`, `ACCOUNT_CONFIGURATION_MISSING`, `NO_IMPORTED_TIME`, `NOTHING_IMPORTED`, `ACCOUNT_REQUIRED`, `NO_REACHABLE_ACCOUNTS`, `FEATURE_NOT_ENTITLED`, `PERMISSION_DENIED`, `CALCULATION_FAILED`, `INTERNAL_ERROR`, `INVALID_ARGUMENT`.

- `data`: object
  - One of:
    - Variant 1 (`measure` is `"hours"`):
      - `data.account`: string (uuid)
      - `data.freshness`: array of object
        - `data.freshness[].source`: string (`"time-entries"`, `"role-task-mappings"`, `"annual-days"`, `"dashboard-inputs"`)
        - `data.freshness[].everCompleted`: boolean
        - `data.freshness[].completedAt`: string (date-time) or null
      - `data.gridFreshness`: array of object
        - `data.gridFreshness[].kind`: string (`"payroll"`, `"expense"`, `"project"`)
        - `data.gridFreshness[].gridId`: string (uuid)
        - `data.gridFreshness[].name`: string
        - `data.gridFreshness[].storage`: string (`"sheet"`, `"database"`)
        - `data.gridFreshness[].sheetRefreshedAt`: string (date-time) or null
      - `data.definitions`: object, optional
        - `data.definitions.presentation`: string
        - `data.definitions.abr`: string
        - `data.definitions.variance`: string
        - `data.definitions.totals`: string
        - `data.definitions.freshness`: string
        - `data.definitions.actuals`: string
        - `data.definitions.windows`: string, optional
        - `data.definitions.projectBounds`: string, optional
      - `data.caveats`: array of object
        - One of:
          - Variant 1 (`code` is `"import-never-completed"`):
            - `data.caveats[].code`: string (`"import-never-completed"`)
            - `data.caveats[].message`: string
            - `data.caveats[].source`: string (`"time-entries"`, `"role-task-mappings"`, `"annual-days"`, `"dashboard-inputs"`)
          - Variant 2 (`code` is `"unmatched-projects"`):
            - `data.caveats[].code`: string (`"unmatched-projects"`)
            - `data.caveats[].message`: string
            - `data.caveats[].hours`: string (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.caveats[].totalHours`: string (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.caveats[].hoursShare`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.caveats[].hoursDenominator`: string
            - `data.caveats[].projectNames`: array of string
            - `data.caveats[].unmatchedTimeRowCount`: string, optional (pattern `^\d+$`)
          - Variant 3 (`code` is `"outside-selection-projects"`):
            - `data.caveats[].code`: string (`"outside-selection-projects"`)
            - `data.caveats[].message`: string
            - `data.caveats[].hours`: string (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.caveats[].totalHours`: string (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.caveats[].hoursShare`: string or null (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.caveats[].hoursDenominator`: string
            - `data.caveats[].projectNameCount`: integer (`minimum: 0`)
          - Variant 4 (`code` is `"reversed-project-dates"`):
            - `data.caveats[].code`: string (`"reversed-project-dates"`)
            - `data.caveats[].message`: string
            - `data.caveats[].projectName`: string
            - `data.caveats[].group`: string
            - `data.caveats[].groupBy`: string (`"serviceLine"`, `"client"`, `"project"`, `"product"`)
            - `data.caveats[].groupProjectIndex`: integer (`minimum: 0`)
            - `data.caveats[].startDate`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
            - `data.caveats[].endDate`: string (pattern `^\d{4}-\d{2}-\d{2}$`)
      - `data.pagination`: object
        - `data.pagination.limit`: integer (`exclusiveMinimum: 0`)
        - `data.pagination.offset`: integer (`minimum: 0`)
        - `data.pagination.totalRows`: integer (`minimum: 0`)
        - `data.pagination.returnedRows`: integer (`minimum: 0`)
        - `data.pagination.omittedRows`: integer (`minimum: 0`)
        - `data.pagination.nextOffset`: integer or null (`minimum: 0`)
        - `data.pagination.truncated`: boolean
        - `data.pagination.message`: string
      - `data.groupBy`: string (`"serviceLine"`, `"client"`, `"project"`, `"product"`)
      - `data.statuses`: array of string
      - `data.measure`: string (`"hours"`)
      - `data.report`: object
        - `data.report.diagnostics`: object
          - `data.report.diagnostics.unmatchedTimeRowCount`: string (pattern `^\d+$`)
          - `data.report.diagnostics.unmatchedProjectNames`: array of string
        - `data.report.latestTimerData`: string or null, optional (pattern `^\d{4}-\d{2}-\d{2}$`)
        - `data.report.taskCategories`: array of string
        - `data.report.rows`: array of object
          - `data.report.rows[].kind`: string (`"summary"`, `"project"`)
          - `data.report.rows[].group`: string
          - `data.report.rows[].attributes`: object
            - `data.report.rows[].attributes.serviceLine`: string or null, optional
            - `data.report.rows[].attributes.client`: string or null, optional
            - `data.report.rows[].attributes.project`: string or null, optional
            - `data.report.rows[].attributes.product`: string or null, optional
          - `data.report.rows[].startDate`: string or null, optional (pattern `^\d{4}-\d{2}-\d{2}$`)
          - `data.report.rows[].endDate`: string or null, optional (pattern `^\d{4}-\d{2}-\d{2}$`)
          - `data.report.rows[].overall`: object
            - `data.report.rows[].overall.actual`: string (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.report.rows[].overall.plan`: string (pattern `^-?\d+(?:\.\d+)?$`)
          - `data.report.rows[].taskCategories`: map of string to object
            - `data.report.rows[].taskCategories.*`: object
              - `data.report.rows[].taskCategories.*.actual`: string (pattern `^-?\d+(?:\.\d+)?$`)
              - `data.report.rows[].taskCategories.*.plan`: string (pattern `^-?\d+(?:\.\d+)?$`)
    - Variant 2 (`measure` is `"abr"`):
      - `data.account`: string (uuid)
      - `data.freshness`: same shape as `data.freshness`
      - `data.gridFreshness`: same shape as `data.gridFreshness`
      - `data.definitions`: same shape as `data.definitions`, optional
      - `data.caveats`: same shape as `data.caveats`
      - `data.pagination`: same shape as `data.pagination`
      - `data.groupBy`: string (`"serviceLine"`, `"client"`, `"project"`, `"product"`)
      - `data.statuses`: array of string
      - `data.measure`: string (`"abr"`)
      - `data.report`: object
        - `data.report.diagnostics`: same shape as `data.report.diagnostics`
        - `data.report.latestTimerData`: string or null, optional (pattern `^\d{4}-\d{2}-\d{2}$`)
        - `data.report.rows`: array of object
          - `data.report.rows[].kind`: string (`"summary"`, `"project"`)
          - `data.report.rows[].group`: string
          - `data.report.rows[].attributes`: same shape as `data.report.rows[].attributes`
          - `data.report.rows[].startDate`: string or null, optional (pattern `^\d{4}-\d{2}-\d{2}$`)
          - `data.report.rows[].endDate`: string or null, optional (pattern `^\d{4}-\d{2}-\d{2}$`)
          - `data.report.rows[].values`: object
            - `data.report.rows[].values.agi`: string (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.report.rows[].values.hours`: object
              - `data.report.rows[].values.hours.actual`: string (pattern `^-?\d+(?:\.\d+)?$`)
              - `data.report.rows[].values.hours.plan`: string (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.report.rows[].values.actualAbr`: string or null, optional (pattern `^-?\d+(?:\.\d+)?$`)
            - `data.report.rows[].values.plannedAbr`: string or null, optional (pattern `^-?\d+(?:\.\d+)?$`)

On failure:

- `error`: object
  - `error.code`: string (`"MODEL_CALCULATOR_ACCESS_REQUIRED"`, `"PAYROLL_GRID_MISSING"`, `"PAYROLL_GRID_REQUIRED"`, `"PROJECT_GRID_REQUIRED"`, `"EXPENSE_GRID_REQUIRED"`, `"PAYROLL_ENTRY_REFERENCE_STALE"`, `"ACCOUNT_NOT_FOUND"`, `"ACCOUNT_CONFIGURATION_MISSING"`, `"NO_IMPORTED_TIME"`, `"NOTHING_IMPORTED"`, `"ACCOUNT_REQUIRED"`, `"NO_REACHABLE_ACCOUNTS"`, `"FEATURE_NOT_ENTITLED"`, `"PERMISSION_DENIED"`, `"CALCULATION_FAILED"`, `"INTERNAL_ERROR"`, `"INVALID_ARGUMENT"`)
  - `error.argument`: string, optional (`minLength: 1`)
  - `error.message`: string
  - `error.accounts`: array of object, optional
    - `error.accounts[].id`: string (uuid)
    - `error.accounts[].name`: string
  - `error.payrollGrids`: array of object, optional
    - `error.payrollGrids[]`: same shape as `error.accounts[]`
  - `error.projectGrids`: array of object, optional
    - `error.projectGrids[]`: same shape as `error.accounts[]`
  - `error.expenseGrids`: array of object, optional
    - `error.expenseGrids[]`: same shape as `error.accounts[]`
  - `error.context`: object, optional
    - `error.context.account`: object
      - Further fields: see the response.
    - `error.context.imports`: array of object
      - Further fields: see the response.
    - `error.context.hasTimeEntries`: boolean
    - `error.context.reports`: array of object
      - Further fields: see the response.

## Definitions

Returned in `definitions` when `includeDefinitions` is true (the default). Each value is the definition text for that field.

- `presentation`
- `abr`
- `variance`
- `totals`
- `freshness`
- `actuals`
- `windows`
- `projectBounds`

## Caveats

- `import-never-completed`. Also carries `source`.
- `unmatched-projects`. Also carries `hours`, `totalHours`, `hoursShare`, `hoursDenominator`, `projectNames`, `unmatchedTimeRowCount`.
- `outside-selection-projects`. Also carries `hours`, `totalHours`, `hoursShare`, `hoursDenominator`, `projectNameCount`.
- `reversed-project-dates`. Also carries `projectName`, `group`, `groupBy`, `groupProjectIndex`, `startDate`, `endDate`.
- `import-never-completed`. Also carries `source`.
- `unmatched-projects`. Also carries `hours`, `totalHours`, `hoursShare`, `hoursDenominator`, `projectNames`, `unmatchedTimeRowCount`.
- `outside-selection-projects`. Also carries `hours`, `totalHours`, `hoursShare`, `hoursDenominator`, `projectNameCount`.
- `reversed-project-dates`. Also carries `projectName`, `group`, `groupBy`, `groupProjectIndex`, `startDate`, `endDate`.

Read every caveat before interpreting a figure. See [methodology](</methodology.md>) on how to communicate caveats and data-quality conditions.

## Example call

```json
{
  "name": "get_nonrecurring_scoping_accuracy",
  "arguments": {
    "measure": "hours"
  }
}
```

Add `account` with an identifier from `list_accounts`; omit it only when the connection reaches exactly one account.
