Under the Hood: render the report in-product instead of handing users a raw JSON file
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
Research direction
Start with under-the-hood/strato/columns/underTheHoodReport.User.strato:155-158, 180-243, and 296-332, then read under-the-hood/thrift/uth_serving.thrift:10-14, 25-34, 53-57, 99-108. Check how UthReferenceMonthMhPublisherJob.scala supplies cohort data and determine which serving-layer fields and count shapes must reach the response. Done means the repository's serving layer exposes an agreed report shape; the frontend is outside this repository.
Written by the indexing model from the issue text.
Description
The README says the tool will be shaped by feedback, so here is a report on the download path.
What an eligible account gets today
x.com/i/under_the_hood renders a title, two eligibility checkmarks and a Download button. Clicking it hands over the reportJson string from UserUnderTheHoodReport verbatim, as a JSON blob. There is no rendered view of the report anywhere in the product.
Shape of the payload (values synthetic):
{
"notes": "You can learn more about instances when a post's reach may be limited by reading our open-source code at ...",
"period": { "startDate": "2026-08-01", "endDate": "2026-08-31", "timezone": "UTC" },
"generatedAt": "2026-09-09T23:59:59Z",
"postCount": "412",
"postLabels": [
{
"label": "SPAM_HIGH_RECALL",
"about": "Post detected by automated systems as one that may contain spam.",
"effect": "Post hidden from recommendations to non-followers.",
"posts": "1",
"totalPostsInMonth": "412",
"percentageOfPosts": "0.24%"
}
],
"accountLabels": [],
"totalAccountLabels": 0
}
Everything needed for a human-readable view is already computed. postLabelRow in under-the-hood/strato/columns/underTheHoodReport.User.strato:180-212 already attaches plain-English about and effect text per label, and percentageOfPosts is already a formatted display string rather than a number. That prose is then serialized into a file and handed over.
So the gap is presentation, not data. The audience for this tool is every eligible account, not the subset of people who open .json files.
Ask
Render the report on the page in X's own UI: a period header, a plain state line ("No labels were applied to your account in August 2026" vs "2 labels"), then one card per label showing the label's human name, its about, its effect, and the count with its percentage. Keep the JSON download as a secondary action for people who want the raw file.
An account that is clean should be able to learn that in one glance without downloading anything.
Four things the served report drops that a rendered view would want
All four are computed upstream and discarded at the serving layer, so they are worth settling before a UI is designed:
-
Per-day timeline.
UthPostLabelAggregate.daysis alist<UthDayCarriedRemoved>carryingdayOfMonth(under-the-hood/thrift/uth_serving.thrift:10-14, 53-57), butsumCarriedcollapses it to a single integer (underTheHoodReport.User.strato:155-158). "1 post, sometime in August" answers much less than a sparkline showing which day. -
removedis never read.UthDayCarriedRemovedcarries bothcarriedandremoved;sumCarriedsums onlycarried. A label that was applied and later lifted is therefore indistinguishable from one that was never applied, which is exactly the case a worried author most wants resolved. -
countryCodesis not a field. It reachespostLabelRow(:182) andaccountLabelRow(:218) only to be interpolated into the takedown label's name and its about/effect sentences (:205-207,:241-243). For the legal-withholding data added in the September update, "which country" deserves a structured field, not a sentence a UI has to parse back out. -
No peer context.
UthReferenceCohortStatscomputesmeanandp10/p25/p50/p75/p90/p99per label perUthFollowerClass(uth_serving.thrift:25-34, 99-108), published byUthReferenceMonthMhPublisherJob.scala. ButreferenceMonthdoes not appear anywhere inunderTheHoodReport.User.strato, so none of it reaches the user. Without it a reader has no way to judge whether their rate is normal. One line, "typical for accounts your size: 0.4%", turns a number into an answer.
One shape issue worth fixing regardless of the UI
totalPostLabels and totalAccountLabels are emitted only when the corresponding list is empty (underTheHoodReport.User.strato:296-332), so the object has four different key sets depending on which lists are populated. Every consumer has to branch on key presence. Emitting both counts unconditionally would be simpler for a UI and for anyone parsing the file.
On a PR
I have not opened one because the page's frontend is not in this repository: under-the-hood/ ships the daily jobs and the serving layer only. Happy to send a PR for the serving-layer items (1-4 and the count shape) if that is useful.
Verified against main on 2026-09-20: the live page, the UserUnderTheHoodReport GraphQL response, and the checked-in under-the-hood/ sources. Related but distinct: #39 (label-source provenance).
- Dominant language
- Rust
- Stars
- 33.3k
- Forks
- 5.4k
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 1
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from xai-org/x-algorithm
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
xai-org/x-algorithm#210 · 3 comments ·
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
xai-org/x-algorithm#207 ·
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
xai-org/x-algorithm#206 ·
-
Difficulty 5/5 Over a week Newbie friendliness 42/100
xai-org/x-algorithm#205 ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
xai-org/x-algorithm#203 ·
All issues in xai-org/x-algorithm
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100