Skip to content

[Feature:TAGrading] Backend for submission clustering#12886

Merged
bmcutler merged 39 commits into
Submitty:mainfrom
GarvitKhandelwal31:grading-cluster-backend
Jun 29, 2026
Merged

[Feature:TAGrading] Backend for submission clustering#12886
bmcutler merged 39 commits into
Submitty:mainfrom
GarvitKhandelwal31:grading-cluster-backend

Conversation

@GarvitKhandelwal31

@GarvitKhandelwal31 GarvitKhandelwal31 commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Why is this Change Important & Necessary?

This PR lays the architectural foundation, Doctrine entities, and database schema support for the upcoming submission clustering project.

What is the New Behavior?

  1. Database Schema: Adds a new database migration to create three tables (grading_cluster_config, grading_cluster, and grading_cluster_members).
  2. Doctrine Entities: Creates three Doctrine entities mapped to those tables.
  3. API Controller: Adds a new controller file to handle the generation and fetching of clusters.

Note: Currently, our design allows for global clustering only. If a TA creates a clustering for student submissions using a particular algorithm, it will be visible to all TAs. If they generate a new clustering using another algorithm, the code automatically destroys any previous clustering configuration for that gradeable and creates a new one.

Database Schema Overview

For a deeper dive into the database schema, please refer to the below explanation-

We use three tables to accomplish this:

1. grading_cluster_config
Stores the unique clustering configuration for a gradeable. Because g_id is unique, we can only have one active clustering configuration at a time per gradeable.

id g_id algorithm
1 hw1 algo1
2 hw2_team_project algo2

2. grading_cluster
Defines the individual clusters generated for a specific config. A TA can assign or update a cluster_name to this cluster at any moment.

id config_id (FK) cluster_name
10 1 (links to hw1) Cluster A
11 1 (links to hw1) Cluster B
12 2 (links to hw2) Group 1
13 2 (links to hw2) Group 2

3. grading_cluster_members
Stores the members (users or teams) that belong to a cluster. It tracks the student's active submission version at the time of clustering. It also utilizes a CHECK constraint to ensure that either user_id or team_id is filled out, but never both.

id cluster_id (FK) user_id team_id active_version
100 10 (Cluster A) student1 NULL 1
101 10 (Cluster A) student2 NULL 2
102 11 (Cluster B) student3 NULL 3
104 12 (Group 1) NULL team_alpha 1
105 13 (Group 2) NULL team_beta 2

What steps should a reviewer take to reproduce or test the bug or new feature?

Since there is no frontend UI yet, you can test the backend pipeline using the browser's developer console.

  1. Run submitty_install in vagrant (to apply the migrations).
  2. Login as an instructor and navigate to any gradeable page.
  3. Open the browser developer console.

To create clusters:
let formData = new FormData();
formData.append('csrf_token', csrfToken);
formData.append('algorithm', 'dummy_split');

fetch(buildCourseUrl(['gradeable', '<GRADEABLE_ID>', 'create_clustering']), {
method: 'POST',
body: formData
})
.then(res => res.json())
.then(console.log);

To fetch them-
fetch(buildCourseUrl(['gradeable', '<GRADEABLE_ID>', 'clustering']))
.then(res => res.json())
.then(console.log);

Over here please verify that the students with registration section NULL and have late submissions are also included.

Automated Testing & Documentation

Added tests to verify the methods in the controller.

Other information

Migrations are included, so please ensure you run submitty_install before reviewing or testing the PR locally.

@codecov

codecov Bot commented Jun 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 14.78873% with 121 lines in your changes missing coverage. Please review.
✅ Project coverage is 21.36%. Comparing base (0b452ab) to head (d1598f9).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##               main   #12886      +/-   ##
============================================
- Coverage     21.38%   21.36%   -0.03%     
- Complexity     9946     9990      +44     
============================================
  Files           268      274       +6     
  Lines         37158    37300     +142     
  Branches        499      499              
============================================
+ Hits           7948     7969      +21     
- Misses        28715    28836     +121     
  Partials        495      495              
Flag Coverage Δ
autograder 21.16% <ø> (ø)
js 1.99% <ø> (ø)
migrator 100.00% <ø> (ø)
php 20.41% <14.78%> (-0.03%) ⬇️
python_submitty_utils 80.08% <ø> (ø)
submitty_daemon_jobs 91.13% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@GarvitKhandelwal31
GarvitKhandelwal31 marked this pull request as draft June 4, 2026 09:59
@automateprojectmangement automateprojectmangement Bot moved this from Seeking Reviewer to Work in Progress in Submitty Development Jun 4, 2026
@GarvitKhandelwal31 GarvitKhandelwal31 changed the title [Feature:TAGrading] Add backend infrastructure [Feature:TAGrading] Backend infrastructure for AI grading Jun 4, 2026
@GarvitKhandelwal31
GarvitKhandelwal31 marked this pull request as ready for review June 5, 2026 18:19
@automateprojectmangement automateprojectmangement Bot moved this from Work in Progress to Seeking Reviewer in Submitty Development Jun 5, 2026
Comment thread site/app/controllers/grading/GradingClusterController.php Outdated
Comment thread site/app/controllers/grading/GradingClusterController.php Outdated
Comment thread site/app/controllers/grading/GradingClusterController.php Outdated
Comment thread site/app/controllers/grading/GradingClusterController.php Outdated
Comment thread site/app/controllers/grading/GradingClusterController.php Outdated
Comment thread site/app/controllers/grading/GradingClusterController.php
Comment thread site/app/libraries/database/DatabaseQueries.php Outdated
Comment thread site/app/libraries/database/DatabaseQueries.php Outdated
Comment thread site/app/libraries/database/DatabaseQueries.php Outdated
Comment thread site/app/models/gradeable/GradingCluster.php Outdated
@github-project-automation github-project-automation Bot moved this from Seeking Reviewer to Work in Progress in Submitty Development Jun 7, 2026

@williamjallen williamjallen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another round of comments. I'll have more once these are addressed. In addition to the inline comments, please:

  1. Change the PR title to reflect the fact this is not AI grading, but rather submission clustering
  2. Mark all comments you've addressed as "resolved" as you go so reviewers can easily see what you've responded to and what remains to be done.

Comment thread migration/migrator/migrations/course/20260604000000_grading_clusters.py Outdated
Comment thread migration/migrator/migrations/course/20260604000000_grading_clusters.py Outdated
Comment thread migration/migrator/migrations/course/20260604000000_grading_clusters.py Outdated
Comment thread migration/migrator/migrations/course/20260604000000_grading_clusters.py Outdated
Comment thread migration/migrator/migrations/course/20260604000000_grading_clusters.py Outdated
Comment thread migration/migrator/migrations/course/20260604000000_grading_clusters.py Outdated
Comment thread site/app/controllers/grading/GradingClusterController.php
Comment thread site/app/controllers/grading/GradingClusterController.php Outdated
Comment thread site/app/entities/grading_cluster/GradingCluster.php
Comment thread site/app/libraries/database/DatabaseQueries.php
@GarvitKhandelwal31 GarvitKhandelwal31 changed the title [Feature:TAGrading] Backend infrastructure for AI grading [Feature:TAGrading] Backend infrastructure for submission clustering Jun 14, 2026
@GarvitKhandelwal31 GarvitKhandelwal31 changed the title [Feature:TAGrading] Backend infrastructure for submission clustering [Feature:TAGrading] Backend for submission clustering Jun 14, 2026
@GarvitKhandelwal31
GarvitKhandelwal31 marked this pull request as draft June 14, 2026 12:50
@NicholasCiuica

NicholasCiuica commented Jun 25, 2026

Copy link
Copy Markdown
Member

Yeah you are actually correct on this, it depends on instructor to instructor, whether she would want to allow late submission students to be graded or not. I would say the better approach would be to exclude them , primarily the reason being that most of the students would actually make submission within the deadline and if there some students , then they can clustered separately also. I will just make some amendments to the query and then we should be good, will also discuss in the standup. I also discussed this with William once, another problem with late submissions is that after some days there count could increase, this might create inconsistencies bcoz the TA who is grading on a previously graded cluster might be grading wrong.

I have just spoken with Barb about this issue, and she mentioned that students with late submissions should always be included in the clustering by default. However, if a student uploads a new submission after the initial clustering, that student should be removed from their cluster to prevent a version conflict in grading. She mentioned possibly adding a timestamp attribute to the clustering, so that clustered students submitting again after that timestamp can be removed. This feature would mostly be for students that got a due date exception and need to submit after clustering has already begun.

@bmcutler

Copy link
Copy Markdown
Member

@GarvitKhandelwal31

Thanks for the schema document. For permanent archival purposes, can you please insert the example directly into the PR message notes rather than a external google drive document which may be deleted/unavailable.

As I said in our meeting, the reason I was confused about the table purposes was that they are in a different order -- alphabetical by title -- in the .sql document. I understand them now.

Name change suggestion: (this is not a required change, what do others @williamjallen, @NicholasCiuica think?)
Grading Cluster Config -> TAgrading_cluster_config
grading_cluster - > TAgrading_cluster_groups
grading_cluster_members -> TAgrading_cluster_group_members
note: this has the advantage that the alphabetical ordering is also the logical ordering of the tables.

Also, I've chatted with other folks and I'm leaning towards using the vocabulary of "we perform a clustering" and then "the students are in groups" as a result. What do we think?

And yes, to follow up on the discussion with @NicholasCiuica
We should record the time the clustering is created (in the TAgrading_cluster_config table).
And also record what version of the students submission is active at the time of clustering (in the TAgrading_cluster_group_members table).
And then any new submissions after the clustering timestamp will not be in any group. And any student who changes their active version after the clustering timestamp should be removed from the group (or be invalid/ignored).

Note that a student's submission status being "late" or "too late/bad" should not be taken into account with the grouping. You should ignore that when doing the grouping.

Similarly, I suggest we ignore whether a student is in the NULL registration section for now. Personally I do like using instructor/TA submissions as examples when we are grading or explaining how we will grade to our staff, so I would like any NULL section or teaching staff submissions to be treated like a regular student in the clustering.

It's ok to delay the addition of the timestamp and other edits to a future PR.

@bmcutler bmcutler moved this from Awaiting Maintainer Review to Work in Progress in Submitty Development Jun 26, 2026
@williamjallen

Copy link
Copy Markdown
Member

@bmcutler

Name change suggestion: ...
Grading Cluster Config -> TAgrading_cluster_config
grading_cluster - > TAgrading_cluster_groups
grading_cluster_members -> TAgrading_cluster_group_members

Table names should be all lower snake case IMO. I don't think it's a good idea to prefix these tables with "TA". If you think it's important to include "TA" in the names, what about prefixing with "ta_", e.g., ta_grading_cluster_config?

note: this has the advantage that the alphabetical ordering is also the logical ordering of the tables.

I can't think of a reason why the ordering of the tables is particularly useful beyond this single PR where they're being added. I don't think the alphabetical order should influence our naming choices in any way.

Also, I've chatted with other folks and I'm leaning towards using the vocabulary of "we perform a clustering" and then "the students are in groups" as a result. What do we think?

I like that, assuming we don't want to use groups in a different way elsewhere in the future.

It's ok to delay the addition of the timestamp and other edits to a future PR.

It seems reasonable to include them here IMO.

@bmcutler

Copy link
Copy Markdown
Member

The ordering of the tables also appears in SQL toolbox in the schema documentation, which for instructors who explore the database is the first exposure to a complicated structure. Naming these tables well (and coincidental alphabetic organization) is good.

The capitalization & spacing was not my focus, sure yes, use "ta_grading_" as the prefix.

@NicholasCiuica

Copy link
Copy Markdown
Member

Also, I've chatted with other folks and I'm leaning towards using the vocabulary of "we perform a clustering" and then "the students are in groups" as a result. What do we think?

I feel it would be better to stick with "clusters" as the name to make it very obvious that clusters are a result of the clustering action. Calling them groups sounds vague in comparison, and and to me it seems too similar to teams.

Grading Cluster Config -> TAgrading_cluster_config
grading_cluster - > TAgrading_cluster_groups
grading_cluster_members -> TAgrading_cluster_group_members

The following is what I imagine as the clearest names for the new tables added given the original wording, and they also flow nicely alphabetically.

Grading Cluster Config -> ta_grading_clustering_configs
grading_cluster -> ta_grading_clusters
grading_cluster_members -> ta_grading_clusters_members

@GarvitKhandelwal31

Copy link
Copy Markdown
Contributor Author

Also, I've chatted with other folks and I'm leaning towards using the vocabulary of "we perform a clustering" and then "the students are in groups" as a result. What do we think?

I feel it would be better to stick with "clusters" as the name to make it very obvious that clusters are a result of the clustering action. Calling them groups sounds vague in comparison, and and to me it seems too similar to teams.

Yeah I agree, I don't think it would be nice to call them "groups". I would say "cluster" is not that bad after all, also if you would like any change, changing it to "buckets" might be better than calling it "groups" would be better. But again I am not very supportive of this idea too. I think we should keep it simple , "TA create clusters", and as a result student submissions are "clustered"

@bmcutler

Copy link
Copy Markdown
Member

@NicholasCiuica @GarvitKhandelwal31
I also initially thought "after clustering, students are in clusters" made perfect sense.
But then I was talked into using "groups".
Let's go with clusters :)

(We can always refactor the code/DB/UI later if group consensus changes.)

@GarvitKhandelwal31
GarvitKhandelwal31 marked this pull request as ready for review June 26, 2026 17:02
@automateprojectmangement automateprojectmangement Bot moved this from Work in Progress to Seeking Reviewer in Submitty Development Jun 26, 2026

@NicholasCiuica NicholasCiuica left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done a quick rereview. The code reorganization/name changes look good, and after some testing the new timestamp/active version logic looks good as well (I clustered, made another submission on a student, and saw that they were removed from their cluster).

The only potential issue I see now, which I don't know if I've seen before, is that if a GET clustering call is made with an invalid course code, a "success" response is returned, but whenever a POST create_clustering call is made with an invalid course code, an "error" response is returned, which I'd assume would be the behavior for both cases. Is it expected behavior that a clustering call on an invalid course should be a success? Please see the images below for the output I saw.

Image Image

@automateprojectmangement automateprojectmangement Bot moved this from Seeking Reviewer to In Review in Submitty Development Jun 26, 2026
@GarvitKhandelwal31

GarvitKhandelwal31 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

@bmcutler @williamjallen

And yes, to follow up on the discussion with @NicholasCiuica We should record the time the clustering is created (in the TAgrading_cluster_config table). And also record what version of the students submission is active at the time of clustering (in the TAgrading_cluster_group_members table). And then any new submissions after the clustering timestamp will not be in any group. And any student who changes their active version after the clustering timestamp should be removed from the group (or be invalid/ignored).

I just had a few more things to say-
Do we actually need the created_at timestamp in config table? Perhaps not. In the current logic I am checking whether the current active submission is equal to active version the student has set to. What I mean to say is that say originally student had active version as 1, our database recorded that, now student changes submission to 2 (during a get request he will not be in any cluster), but again if the student changes active version to 1 (student is again in).

Well I would say this behaviour suits because the student submissions are immutable themselves, the version number is linked to a specific submission.

Another edge case I was thinking of-
Lets say the TA is currently on the grading page with clustering mode on, now while he is grading and checking submissions and all, there comes a student who changes the active version number. This might be or might not be a problem. We could simply say, okay, nothing was really lost, the TA currently graded a stale version of a student. Another approach could be that while saving the grades, we could make a function in ElectronicGraderController and check that whether or not active version has changed or not.

@bmcutler

Copy link
Copy Markdown
Member

I just had a few more things to say- Do we actually need the created_at timestamp in config table? Perhaps not. In the current logic I am checking whether the current active submission is equal to active version the student has set to. What I mean to say is that say originally student had active version as 1, our database recorded that, now student changes submission to 2 (during a get request he will not be in any cluster), but again if the student changes active version to 1 (student is again in).

Well I would say this behaviour suits because the student submissions are immutable themselves, the version number is linked to a specific submission.

You are correct, we may not strictly need the timestamp of clustering to be stored. But since we may eventually allow multiple clusterings of the same gradeable to be in use at the same time (TA A who is grading Problem 1 will want to cluster based on the student answers to problem 1, which TA B who is grading Problem 2 will want to use a different clustering). I think it might be good to know when a cluster was created. And eventually, who created it, and what they would like to name it...

Another edge case I was thinking of- Lets say the TA is currently on the grading page with clustering mode on, now while he is grading and checking submissions and all, there comes a student who changes the active version number. This might be or might not be a problem. We could simply say, okay, nothing was really lost, the TA currently graded a stale version of a student. Another approach could be that while saving the grades, we could make a function in ElectronicGraderController and check that whether or not active version has changed or not.

This is the topic of "version conflict"
https://submitty.org/student/submission/submission_version_conflict
https://submitty.org/grader/grader_version_conflict

So yes, manual grades using the one-at-a-time current interface and manual grades using the new cluster grading interface should both work the same if a student changes the version after any partial or complete manual grade has been recorded for their assignment.

@bmcutler
bmcutler merged commit 007eed8 into Submitty:main Jun 29, 2026
99 of 103 checks passed

@NicholasCiuica NicholasCiuica left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested it once more and the error I found last review has been fixed.

jndlansh pushed a commit to jndlansh/Submitty that referenced this pull request Jul 1, 2026
### Why is this Change Important & Necessary?
This PR lays the architectural foundation, Doctrine entities, and
database schema support for the upcoming submission clustering project.

### What is the New Behavior?
1. **Database Schema**: Adds a new database migration to create three
tables (`grading_cluster_config`, `grading_cluster`, and
`grading_cluster_members`).
2. **Doctrine Entities**: Creates three Doctrine entities mapped to
those tables.
3. **API Controller**: Adds a new controller file to handle the
generation and fetching of clusters.

*Note: Currently, our design allows for global clustering only. If a TA
creates a clustering for student submissions using a particular
algorithm, it will be visible to all TAs. If they generate a new
clustering using another algorithm, the code automatically destroys any
previous clustering configuration for that gradeable and creates a new
one.*

### Database Schema Overview
For a deeper dive into the database schema, please refer to the below
explanation-

We use three tables to accomplish this:

**1. `grading_cluster_config`**
Stores the unique clustering configuration for a gradeable. Because
`g_id` is unique, we can only have one active clustering configuration
at a time per gradeable.
| id | g_id | algorithm |
|----|------|-----------|
| 1  | hw1  | algo1     |
| 2  | hw2_team_project | algo2 |

**2. `grading_cluster`**
Defines the individual clusters generated for a specific config. A TA
can assign or update a `cluster_name` to this cluster at any moment.
| id | config_id (FK) | cluster_name |
|----|----------------|--------------|
| 10 | 1 (links to hw1) | Cluster A    |
| 11 | 1 (links to hw1) | Cluster B    |
| 12 | 2 (links to hw2) | Group 1      |
| 13 | 2 (links to hw2) | Group 2      |

**3. `grading_cluster_members`**
Stores the members (users or teams) that belong to a cluster. It tracks
the student's active submission version at the time of clustering. It
also utilizes a `CHECK` constraint to ensure that either `user_id` or
`team_id` is filled out, but never both.
| id | cluster_id (FK)| user_id  | team_id    | active_version |
|----|----------------|----------|------------|----------------|
| 100| 10 (Cluster A) | student1 | NULL       | 1              |
| 101| 10 (Cluster A) | student2 | NULL       | 2              |
| 102| 11 (Cluster B) | student3 | NULL       | 3              |
| 104| 12 (Group 1)   | NULL     | team_alpha | 1              |
| 105| 13 (Group 2)   | NULL     | team_beta  | 2              |

### What steps should a reviewer take to reproduce or test the bug or
new feature?
Since there is no frontend UI yet, you can test the backend pipeline
using the browser's developer console.

1. Run `submitty_install` in vagrant (to apply the migrations).
2. Login as an instructor and navigate to any gradeable page.
3. Open the browser developer console.

**To create clusters:**
let formData = new FormData();
formData.append('csrf_token', csrfToken);
formData.append('algorithm', 'dummy_split');

fetch(buildCourseUrl(['gradeable', '<GRADEABLE_ID>',
'create_clustering']), {
    method: 'POST',
    body: formData
})
.then(res => res.json())
.then(console.log);

To fetch them-
fetch(buildCourseUrl(['gradeable', '<GRADEABLE_ID>', 'clustering']))
.then(res => res.json())
.then(console.log);

Over here please verify that the students with registration section NULL
and have late submissions are also included.

### Automated Testing & Documentation
Added tests to verify the methods in the controller.

### Other information
Migrations are included, so please ensure you run submitty_install
before reviewing or testing the PR locally.
prestoncarman added a commit that referenced this pull request Jul 1, 2026
* main: (78 commits)
  [Bugfix:TAGrading] Auto-open single file (#12625)
  [Feature:InstructorUI] Add sortable columns to manage students (#12957)
  [Dependency] Bump php-ds/php-ds from 1.7.0 to 2.0.1 in /site (#12827)
  [Refactor:TAGrading] Events Infrastructure & StatusBanner (#12941)
  [Dependency] Bump sqlalchemy from 2.0.48 to 2.0.51 in /.setup/pip (#12884)
  [Bugfix:Developer] trust hashicorp for vagrant install (#12968)
  [Feature:TAGrading] Backend for submission clustering (#12886)
  [Bugfix:InstructorUI] Missing Subsection in the Edit User form (#12955)
  [Bugfix:Submission] Warning Banners Accessibility Fix (#12956)
  [Bugfix:System] Preserve signup fields (#12939)
  [Bugfix:InstructorUI] Fix Csv Download of Subsections (#12954)
  [Bugfix:InstructorUI] Fix Manage Students Toggle Columns (#12953)
  [Feature:TAGrading] Persistent Auto-Open (#12931)
  [Bugfix:Submission] Dot File Upload (#12924)
  [Refactor:System] Declutter workers (#12815)
  [Bugfix:Developer] save/restore autograding_containers.json (#12952)
  [Bugfix:InstructorUI] Create Course Validation (#12949)
  [Testing:Notifications] Fix grade_inquiries.spec.js (#12950)
  [UI/UX:System] Add fullscreen button vue component (#12936)
  [Bugfix:TAGrading] Student Name Resize (#12946)
  ...

# Conflicts:
#	.pylintrc
bmcutler pushed a commit that referenced this pull request Jul 20, 2026
### Why is this Change Important & Necessary?
This PR adds a daemon job to support asynchronous submission clustering.

### What is the New Behavior?
Now the submission clustering algorithms run asynchronously.
In this PR we have also removed some the files that would not be needed
now that was introduced in #12886.

### What steps should a reviewer take to reproduce or test the bug or
new feature?
1. Run submitty_install
2. Run php unit test (in site folder)-
vendor/bin/phpunit
tests/app/controllers/grading/GradingClusterControllerTester.php
 
 
 3. Run python unit test -
 cd /usr/local/submitty/GIT_CHECKOUT/Submitty/sbin/submitty_daemon_jobs
 python3 -m unittest tests/test_grading_clustering.py
 
Test if backend is fine-
1) First inside site folder to see the logs-
tail -f /var/local/submitty/logs/daemon_job_queue/$(date +%Y%m%d).txt

2) Go to any gradeable, in the browser console, hit a post request-
let formData = new FormData();
formData.append('csrf_token', csrfToken);
formData.append('algorithm', 'dummy_split');

fetch(buildCourseUrl(['gradeable', '<GRADEABLE_ID>',
'create_clustering']), {
method: 'POST',
body: formData
})
.then(res => res.json())
.then(console.log);

Please check the daemon log-
<img width="1435" height="142" alt="image"
src="https://github.com/user-attachments/assets/85cbaa8f-3a79-4add-8df9-83829fb7d71d"
/>

3) Make a get request to verify the clusters formed-
fetch(buildCourseUrl(['gradeable', '<GRADEABLE_ID>', 'clustering']))
.then(res => res.json())
.then(console.log);

### Automated Testing & Documentation
The core Python clustering logic is covered by unit tests in
`sbin/submitty_daemon_jobs/tests/test_grading_clustering.py`. The PHP
Controller is covered by
`tests/app/controllers/grading/GradingClusterControllerTester.php`.

### Other information
Please run submitty_install before reviewing.
jndlansh pushed a commit to jndlansh/Submitty that referenced this pull request Jul 20, 2026
### Why is this Change Important & Necessary?
This PR adds a daemon job to support asynchronous submission clustering.

### What is the New Behavior?
Now the submission clustering algorithms run asynchronously.
In this PR we have also removed some the files that would not be needed
now that was introduced in Submitty#12886.

### What steps should a reviewer take to reproduce or test the bug or
new feature?
1. Run submitty_install
2. Run php unit test (in site folder)-
vendor/bin/phpunit
tests/app/controllers/grading/GradingClusterControllerTester.php
 
 
 3. Run python unit test -
 cd /usr/local/submitty/GIT_CHECKOUT/Submitty/sbin/submitty_daemon_jobs
 python3 -m unittest tests/test_grading_clustering.py
 
Test if backend is fine-
1) First inside site folder to see the logs-
tail -f /var/local/submitty/logs/daemon_job_queue/$(date +%Y%m%d).txt

2) Go to any gradeable, in the browser console, hit a post request-
let formData = new FormData();
formData.append('csrf_token', csrfToken);
formData.append('algorithm', 'dummy_split');

fetch(buildCourseUrl(['gradeable', '<GRADEABLE_ID>',
'create_clustering']), {
method: 'POST',
body: formData
})
.then(res => res.json())
.then(console.log);

Please check the daemon log-
<img width="1435" height="142" alt="image"
src="https://github.com/user-attachments/assets/85cbaa8f-3a79-4add-8df9-83829fb7d71d"
/>

3) Make a get request to verify the clusters formed-
fetch(buildCourseUrl(['gradeable', '<GRADEABLE_ID>', 'clustering']))
.then(res => res.json())
.then(console.log);

### Automated Testing & Documentation
The core Python clustering logic is covered by unit tests in
`sbin/submitty_daemon_jobs/tests/test_grading_clustering.py`. The PHP
Controller is covered by
`tests/app/controllers/grading/GradingClusterControllerTester.php`.

### Other information
Please run submitty_install before reviewing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

4 participants