Skip to content

Automatic Case Distribution

Craig Reese edited this page Jun 4, 2024 · 57 revisions

Goal

When a Veterans Law Judge requests cases that are ready for a decision, those cases are drawn from the Board's various dockets according to a set of rules. Prior to the implementation of the Appeals Modernization Act in February 2019, there was only a single docket, and the distribution of cases could be done by hand. With AMA in place, there are now four dockets, and the rules for distribution have reached a level of complexity that this task now must be automated.

This pages describes the rules by which cases are distributed.

Concepts

Docket

A docket is a line. We can generally think of a docket like a first-in, first-out (FIFO) queue, however there are some exceptions to this rule. One is that a case must be "ready" to be distributed, i.e. it must have no other tasks to be completed before a decision is written. So a ready case will be distributed before a non-ready case, even if the non-ready case is ahead of it on the docket. The Board is also allowed a small amount of wiggle room so that it doesn't have to strictly observe docket order at the cost of efficiency; before AMA this was known as the "docket range," a number of cases that were close enough to the front of the line to be considered eligible to be distributed.

Priority

If an appellant is suffering a serious illness, in financial distress, or for another sufficient cause, their appeal can be Advanced on the Docket, or prioritized. If the appellant is older than 75, their appeal is automatically AOD; otherwise, they must file a motion requesting this status.

Board decisions can be appealed to the Court of Appeals for Veterans Claims. If CAVC disagrees with the Board's decision, they will remand it back to the Board for another decision. These post-CAVC remands are also prioritized.

There is no differentiation between the various reasons for prioritizing cases. All priority cases are prioritized equally.

Genpop

Before AMA, if a judge held a hearing with the appellant, that same judge would be required to write the decision on the appeal. We would say that this appeal is "tied to the judge." A Veteran could waive this right, enabling their appeal to go to any judge. They would be asked to do this if the judge retired, for example. At this point, their case would be deemed "genpop" — eligible to go to any judge.

Under AMA, this is no longer a requirement under law. The link between the VLJ that originally held the hearing has been removed so that cases can be distributed as soon as possible.

The only link that still exists is for legacy hearing cases, as required by law.

In the app, appeals that meet at least one of these conditions are considered genpop:

  • All AMA appeals
  • All legacy appeals without a hearing
  • Legacy appeal where a hearing is not tied to an active judge

Batch size

When a judge requests a distribution of cases, they will receive a certain number of cases in their queue. This number is called the batch size. It is a multiple of the number of attorneys on the judge's team (currently 3 x the number of attorneys). If the judge does not have their own team, for example if they are a DVC, they receive a set number of cases known as an alternative batch size (currently 15 cases).

We also can calculate a number called a total batch size, which is the sum of all of the individual judge's batch sizes. The total batch size is used as a denominator for calculating things like the optimal percentage of priority cases to distribute.

Legacy docket range

The legacy docket combines hearing and non-hearing appeals. As a result, it is not optimal to always grab the frontmost case; there may be cases farther back on the docket that can only be distributed to this specific judge, and it will be advantageous to overall timeliness to distribute them ahead of genpop cases that could be worked by anybody. But we still need to respect docket order, and we do this, similar to how the legacy docket was manually managed, by calculating a docket range. This is the range of cases on the legacy docket that are close enough to the front of the line to be distributed.

The legacy docket range is equal to the total batch size, minus the count of priority cases, times the legacy docket proportion (see Docket Proportions below). A hearing case within that range is considered eligible to be distributed to its judge as if it was at the front of the line.

Ready

Cases considered "ready" for distribution must have all pre-distribution tasks completed.

For AMA Appeals, this is simply determined by the state of the appeal's distribution task. If this task has a status of "assigned", all child tasks that must be completed for distribution are either complete or cancelled, meaning the appeal is ready for distribution.

Here is an example of an AMA appeal's task tree that is ready for distribution: case ready for distribution edited

For legacy appeals, the appeal must meet the following conditions to be considered ready to distribute:

  1. The appeal must be active at the board (bfmpro of the vacols case is "ACT")
  2. The appeal must be in case storage (bfcurloc of the vacols case is "81" or "83")
  3. The appeal must not belong to a special team at the board (bfbox of the vacols case is null)
  4. The appeal must not have any open blocking vacols diaries (tskdcls is null (diary is open) and tskactcd is one of 'EXT', 'HCL', or 'POA' of any associated vacols diary record (diary is a blocking diary type))
  5. The appeal must not have any open blocking vacols mail (mlcompdate is null (mail task is open) and mltype is NOT one of '02', '05', '08', or '13' of any associated vacols mail record (mail task is a blocking distribution type))
appeal = LegacyAppeal.find_by(vacols_id: 3856200)

VACOLS::CaseDocket.priority_ready_appeal_vacols_ids.include? appeal.vacols_id
=> false
# Appeal is considered either not ready or not priority

appeal.aod?
=> true
# Is priority

appeal.location_code
=> "81"
# Appeal is in case storage, one of the conditions for "ready to distribute"

VACOLS::Case.find_by(bfkey: appeal.vacols_id).bfmpro
=> "ACT"
# Appeal is active, one of the conditions for "ready to distribute"

VACOLS::Case.find_by(bfkey: appeal.vacols_id).bfbox
=> nil
# Case does not belong to a special team, one of the conditions for "ready to distribute"

VACOLS::Note.where(tsktknm: appeal.vacols_id, tskdcls: nil, tskactcd: ['EXT', 'HCL', 'POA']).count
=> 0
# No blocking diary items in vacols, one of the conditions for "ready to distribute"

VACOLS::Mail.where(mlfolder: appeal.vacols_id, mlcompdate: nil).pluck(:mltype)
=> ["07"]
# There is an open blocking mail item in vacols, meaning this case is not ready to distribute

Affinity

Some Appeals have an "affinity window," meaning that Appeal will only be distributed to a specific judge for a certain amount of time. The affinities are:

  • CAVC Remands: should be distributed to the judge who wrote the original decision
  • AMA Hearing Docket Appeals: should be distributed to the judge who held the hearing for that appeal

To determine the judges that have affinity, we will:

  • For CAVC Remands, join the original Appeal via the cavc_remands table, then joining the original Appeal's JudgeDecisionReviewTask and get the assigned_to value from that task
  • For AMA Hearing Docket Appeals, join the most recent hearing, then use the judge_id field (corresponding to the User table ID value) for a hearing with a disposition of held

After determining the judge, we need to check to see if the affinity window has elapsed. Prior to the release of APPEALS-44793 Case Distribution Affinity Calculations in FY24Q3, we used the Appeal's distribution_task.assigned_at value. APPEALS-44793 implemented a new model called AppealAffinity:

  • The value in appeal_affinity.affinity_start_date will be compared to the current time at the time of a distribution to determine if the Appeal has been waiting to distribute to its judge with affinity for more than the lever values for the relevant scenario. If an Appeal meets the requirements to be held as an affinity appeal, it must have an appeal_affinity.affinity_start_date, otherwise it will not be distributed

To populate the AppealAffinity values, we triggers an asynchronous job called UpdateAppealAffinityDatesJob after distributions complete which will:

  • Get the DistributedCase records for Appeals which were distributed
  • Join the Appeals to get their receipt_date values
  • Group them by [docket, priority] on the distributed_cases records
  • Select the most recent receipt_date value for each grouping
  • Using those receipt_date values, retrieve all Appeals in the database which are of the [docket, priority] combination that have the same or older receipt_date
  • For retrieved Appeals, create a new AppealAffinity record with the current time as the affinity_start_date

This is done to simulate a "rolling docket number". We don't want affinities determined by when the appeal was made ready to distribute, but instead by when the appeal is actually going to be selected for distribution. This is because non-priority Appeals may be ready to distribute for months before they reach the front of the line, in which case the affinity hold would already have elapsed if we used the distribution task.

For CAVC Remands which are on the Hearing docket, a new hearing is not always required, so a HearingTask subtree is not created by default. For these Appeals, they will use the cavc_affinity_days rules instead of the ama_hearing_case_affinity_days rules

The affinity day values are controlled via the Case Distribution Admin UI.

AMA dockets

The Appeals Modernization Act created two new dockets, in addition to the existing "legacy" docket, and allowed VA to create as many additional dockets as it wants. VA decided to make one additional docket, bringing the total number to four.

  1. Legacy docket. The original flavor docket. This docket contains appeals of decisions before AMA took effect. As there was previously only one docket, the legacy docket contains both hearing and non-hearing appeals. It also has an open record, meaning that evidence can be added to an appeal at any time.
  2. Direct Review docket. This AMA docket contains appeals where the Veteran has decided they do not want to add new evidence and do not want a hearing. To encourage people to use this option, the Board has promised that the average number of days to complete appeals on this docket will be 365 days, one year.
  3. Evidence Submission docket. On this AMA docket, a Veteran can add evidence during the 90 days after they begin their appeal. There is no timeliness goal for this docket.
  4. Hearing Request docket. On this AMA docket, the Veteran has requested a hearing with a judge. They can also submit evidence at their hearing, or during the 90 days after the hearing.

Push Priority Appeals To Judges Job

TL;DR

  • Runs at 1am EST on Mondays
  • Distributes priority cases to Judge Teams who have allow priority push enabled
  • Triggers other asynchronous jobs to run when completed:
    • UpdateAppealAffinityDatesJob (described in the Affinities section above)
  • If it fails
    • Confirm that Request More Cases is working
    • This is rarely rerun on failure in prod and requires Board Approval to rerun in prod

What it does (high level):

  • Retrieves all judges whose JudgeTeam has accepts_priority_pushed_cases = true
  • Retrieves all priority distributions in the past 30 days
  • Calculates a "priority target" by adding the number of ready genpop priority Appeals to the number of priority push cases that all judges have received in the past 30 days and dividing that by how many priority push distributions have occurred in the past 30 days
    • This is attempting to "level out" the number of cases being distributed to the judges, so that over the course of a month the judges should all receive approximately the same number of priority push cases
  • Uses this priority target to determine the number of cases to be distributed to each judge
    • If the number cases to be distributed doesn't match the number of ready genpop Appeals, the "leftover" cases will be added to the number of cases to be distributed to the judges who were calculated to receive the fewest cases in the current run of the job
  • Creates and executes a new Distribution for each judge, passing in the number of cases to be distributed and push_priority: true

After the job completes, it pulls a statistics about the job and sends them to #appeals-job-alerts in the "Office of CTO @ VA" Slack workspace

Request More Cases

  • Allows Judges to manually request more cases
  • Distributes Priority and non-priority cases

Specialty Case Team Distribution

The Specialty Case Team is an organization that handles special issues on Appeals. These appeals are currently distributed alongside other appeals without affecting the total docket count that a judge would receive. It is available to all 3 AMA docket types, but not a legacy docket and is currently only implemented for AMA appeals. The check for which appeals qualify as SCT appeals is based on the request issue benefit types defined in this constant json file client/constants/SPECIALTY_CASE_TEAM_BENEFIT_TYPES.json.

The task tree is similar to a typical distributed appeal except the top level task will be a SpecialtyCaseTeamAssignTask instead of a JudgeAssignTask. Example tree below:

image

Current Algorithm

By Docket Date

Presentations

Further reading

Clone this wiki locally