saas-templatethe graph, actual size

What waits on what, and mostly nothing does

189 blocked_by edges over 455 dispatchable tickets. Drawn at the size the data actually is: 68 disconnected fragments, and a field of 348 tickets nothing points at.

fragments
68
largest
32nodes
nodes in a fragment
248
of those, still unbuilt
107of 248
no edge at all
348

The 29 fragments

141 of the 248 nodes below are already built, so the edge into them no longer holds anything back. They are drawn hollow and struck through, and they are on the page because leaving them out turned the eleven-node fragment into a single dot. docs/state.json carries no title for a built ticket, only its id and status, so a hollow node is labelled by id alone.

P0P1P2P3unscoredalready builtleft to right: the left node blocks the right one

32 nodes, 5 unbuilt
AUTH-004 - drafted, so it no longer blocks anythingAUTH-004AUTH-023 - drafted, so it no longer blocks anythingAUTH-023CLI-038 - drafted, so it no longer blocks anythingCLI-038CLI-039 - drafted, so it no longer blocks anythingCLI-039CLI-040 - drafted, so it no longer blocks anythingCLI-040CLI-051 - P0 - the examples gate declares BILLING_MODE and not WEB_BETA_PROMISE, so every page test in paid-notes 500sCLI-051CLI-053 - merged, so it no longer blocks anythingCLI-053COMP-061 - drafted, so it no longer blocks anythingCOMP-061COMP-079 - merged, so it no longer blocks anythingCOMP-079COMP-084 - merged, so it no longer blocks anythingCOMP-084COMP-085 - merged, so it no longer blocks anythingCOMP-085COMP-121 - merged, so it no longer blocks anythingCOMP-121COMP-149 - merged, so it no longer blocks anythingCOMP-149CORE-039 - drafted, so it no longer blocks anythingCORE-039CORE-044 - drafted, so it no longer blocks anythingCORE-044CORE-045 - drafted, so it no longer blocks anythingCORE-045CORE-046 - drafted, so it no longer blocks anythingCORE-046CORE-049 - merged, so it no longer blocks anythingCORE-049CORE-050 - merged, so it no longer blocks anythingCORE-050CORE-051 - merged, so it no longer blocks anythingCORE-051CORE-052 - P2 - A product can add a table and no gate asks what its retention isCORE-052CORE-059 - drafted, so it no longer blocks anythingCORE-059CORE-067 - P0 - The personal-data gate is table-level, so a new column on a declared table walks past itCORE-067CORE-069 - merged, so it no longer blocks anythingCORE-069CORE-071 - merged, so it no longer blocks anythingCORE-071CORE-116 - unscored - a core tier-zero test fails in every product that has a feature of its ownCORE-116CORE-124 - merged, so it no longer blocks anythingCORE-124OPS-058 - merged, so it no longer blocks anythingOPS-058OPS-218 - P2 - settings-audit checks a field is read, not that an operator can discover itOPS-218OPS-273 - merged, so it no longer blocks anythingOPS-273OPS-281 - merged, so it no longer blocks anythingOPS-281PROD-004 - drafted, so it no longer blocks anythingPROD-004
13 nodes, 10 unbuilt
CLI-054 - unscored - paid-notes demonstrates billing and the examples gate boots it in free beta, which lifts the wall it assertsCLI-054CLI-069 - merged, so it no longer blocks anythingCLI-069DOC-082 - P0 - The dashboard shows a stale page confidently when nothing is runningDOC-082OPS-057 - drafted, so it no longer blocks anythingOPS-057OPS-064 - merged, so it no longer blocks anythingOPS-064OPS-131 - P0 - GitHub Actions has started no job since 2026-09-14, so every CI red is the same redOPS-131OPS-132 - P3 - The postgres job is not in the required status checks, and the Terraform says there are three jobs when there are fiveOPS-132OPS-136 - P1 - An org-level CI runner that every product can leaveOPS-136OPS-139 - P2 - Moving CI onto our own box turns refused jobs into jobs queued foreverOPS-139OPS-178 - P3 - a self hosted CI runner is a bottleneck and a growing fixed bill unless scaling is designed inOPS-178OPS-183 - P0 - settle OPS-169's central claim by standing up postgres and running the suiteOPS-183OPS-215 - P0 - define when CI runs and when it does not, because per-push is what emptied the accountOPS-215OPS-226 - unscored - OPS-131's done_when asks gh run list for a --json field it does not have, so it cannot pass in any treeOPS-226
7 nodes, 2 unbuilt
AUTH-008 - drafted, so it no longer blocks anythingAUTH-008AUTH-018 - merged, so it no longer blocks anythingAUTH-018CLI-037 - P3 - A product carries the access-matrix generator and has no command that runs it, so the one artefact CC.06.02 asks for is the template's and not the product'sCLI-037COMP-010 - drafted, so it no longer blocks anythingCOMP-010COMP-063 - merged, so it no longer blocks anythingCOMP-063COMP-066 - drafted, so it no longer blocks anythingCOMP-066COMP-067 - P3 - The API console behind the admin surface, so /docs can be reachable in production by an operator who signed inCOMP-067
7 nodes, 5 unbuilt
CLI-095 - merged, so it no longer blocks anythingCLI-095CLI-096 - P1 - saas build --static emits an edge gate, so a private static site is private on every hostname including pages.devCLI-096CLI-097 - P1 - publish applies a site's declared access level, and refuses a private site the host cannot enforceCLI-097CLI-098 - P3 - a userless site's password and access level are set and rotated from the CLI, through publishCLI-098CLI-099 - P3 - draft publish: the next version behind its own password before it goes liveCLI-099COMP-163 - P1 - a site password gates every path of a server-rendered product, before accountsCOMP-163CORE-122 - merged, so it no longer blocks anythingCORE-122
7 nodes, 6 unbuilt
CLI-103 - P1 - saas recreate: rebuild a product on a newer template from its dossier, pre-user regime onlyCLI-103PROD-062 - P0 - The dashboard should become the first product built on the template, at tier zeroPROD-062PROD-109 - merged, so it no longer blocks anythingPROD-109PROD-110 - P1 - each product has a page in the portal showing its product layer and what recreating it needsPROD-110PROD-111 - P2 - the interview asks for the dossier fields it does not collect: name, regime, first user, site accessPROD-111PROD-112 - P3 - saas-app carries its own dossier in its repo rather than in the templatePROD-112PROD-114 - P2 - a product change to template-owned code becomes an upstream candidate for the templatePROD-114
6 nodes, 4 unbuilt
CORE-108 - merged, so it no longer blocks anythingCORE-108OPS-061 - P1 - The fly.io account is past its trial, so nothing in this repository can walk a deploy any moreOPS-061OPS-152 - P2 - a scaffolded product cannot restore from total loss, only back up and rehearseOPS-152OPS-257 - merged, so it no longer blocks anythingOPS-257OPS-258 - P2 - walk fly to hetzner on real accounts with a product's data moved across and fly decommissionedOPS-258OPS-259 - P3 - walk one instance to two on a real target, fly scale count 2 behind the platform proxyOPS-259
6 nodes, 5 unbuilt
OPS-301 - P3 - The runner refill loop runs from a laptop, so CI queues whenever the laptop sleepsOPS-301OPS-302 - P1 - Provision the chosen CI box and run the template's whole CI on it once, then walk the exitOPS-302OPS-303 - P2 - A product gets the self-hosted runner switch and runner.sh, not only the templateOPS-303OPS-305 - merged, so it no longer blocks anythingOPS-305OPS-306 - P3 - A job that may use docker is root on the runner box, until docker is rootlessOPS-306OPS-313 - P3 - a runner repository that goes public keeps its idle slots until the next refillOPS-313
5 nodes, 1 unbuilt
AUTH-037 - drafted, so it no longer blocks anythingAUTH-037AUTH-038 - drafted, so it no longer blocks anythingAUTH-038AUTH-043 - merged, so it no longer blocks anythingAUTH-043AUTH-044 - merged, so it no longer blocks anythingAUTH-044AUTH-049 - unscored - An account a squatter got verified before AUTH-044 keeps its flag and any role granted on itAUTH-049
5 nodes, 2 unbuilt
CLI-090 - merged, so it no longer blocks anythingCLI-090CORE-075 - P0 - Nine postgres tests are red on mainCORE-075OPS-130 - P1 - Six guards die only in the suite make verify never runsOPS-130OPS-278 - merged, so it no longer blocks anythingOPS-278OPS-282 - merged, so it no longer blocks anythingOPS-282
5 nodes, 0 unbuilt
COMP-005 - drafted, so it no longer blocks anythingCOMP-005COMP-037 - merged, so it no longer blocks anythingCOMP-037COMP-038 - merged, so it no longer blocks anythingCOMP-038COMP-156 - merged, so it no longer blocks anythingCOMP-156COMP-157 - merged, so it no longer blocks anythingCOMP-157
5 nodes, 1 unbuilt
COMP-016 - drafted, so it no longer blocks anythingCOMP-016COMP-077 - P1 - One place from which every alert to a user is producedCOMP-077COMP-153 - merged, so it no longer blocks anythingCOMP-153CORE-004 - drafted, so it no longer blocks anythingCORE-004CORE-105 - merged, so it no longer blocks anythingCORE-105
5 nodes, 2 unbuilt
COMP-083 - merged, so it no longer blocks anythingCOMP-083COMP-086 - merged, so it no longer blocks anythingCOMP-086COMP-088 - P3 - the email boundary's row names no mechanismCOMP-088COMP-089 - unscored - the invitation email's subject and body are declared at the egress seamCOMP-089CORE-070 - merged, so it no longer blocks anythingCORE-070
5 nodes, 1 unbuilt
COMP-136 - P1 - the signed-in app shell: nav, layout, settings pages and a component kit every product rebuildsCOMP-136COMP-139 - merged, so it no longer blocks anythingCOMP-139COMP-140 - merged, so it no longer blocks anythingCOMP-140COMP-141 - drafted, so it no longer blocks anythingCOMP-141COMP-142 - drafted, so it no longer blocks anythingCOMP-142
4 nodes, 3 unbuilt
COMP-144 - P2 - a tenant row and its members: several people inside one instance, with the operator kept out of the customer's admin roleCOMP-144COMP-145 - merged, so it no longer blocks anythingCOMP-145COMP-146 - P3 - a subscription has no quantity, so a customer cannot buy five members of anythingCOMP-146DOC-113 - P2 - adr-008 does not say the tenant is the paying customer, or that a person in two tenants has two accountsDOC-113
4 nodes, 4 unbuilt
COMP-227 - P1 - a product cannot tell where a sign-up came from: no source or campaign is kept on the accountCOMP-227COMP-230 - P1 - a product cannot tell Google Ads or Meta that an ad brought a sign-up or a payment, so no founder can run ads that optimiseCOMP-230COMP-231 - P1 - a product has no consent record, so nothing can gate ad tags or conversions on what a visitor agreed toCOMP-231COMP-232 - P2 - a founder cannot switch on a Google, Meta or LinkedIn tag without editing templates and the CSPCOMP-232
4 nodes, 1 unbuilt
CORE-062 - drafted, so it no longer blocks anythingCORE-062CORE-063 - merged, so it no longer blocks anythingCORE-063OPS-070 - merged, so it no longer blocks anythingOPS-070OPS-276 - P1 - The product-readiness and devops lens runs cannot pass on any tree, so no skeleton or cli ticket can reach reviewedOPS-276
4 nodes, 0 unbuilt
OPS-103 - drafted, so it no longer blocks anythingOPS-103OPS-104 - drafted, so it no longer blocks anythingOPS-104OPS-105 - merged, so it no longer blocks anythingOPS-105OPS-110 - drafted, so it no longer blocks anythingOPS-110
4 nodes, 0 unbuilt
OPS-235 - merged, so it no longer blocks anythingOPS-235PROD-068 - merged, so it no longer blocks anythingPROD-068PROD-085 - merged, so it no longer blocks anythingPROD-085PROD-086 - merged, so it no longer blocks anythingPROD-086
4 nodes, 4 unbuilt
PROD-006 - P1 - TimeMachine, focus sessions with a client that is not a browserPROD-006PROD-009 - P1 - TimeMachine, the session lifecycle a stopwatch does not havePROD-009PROD-010 - P3 - TimeMachine, the counter whose period the user choosesPROD-010PROD-011 - P1 - TimeMachine, one open session across devices that were offlinePROD-011
4 nodes, 3 unbuilt
PROD-065 - P1 - the interview artifacts have no production tooling, and the format is the integrationPROD-065PROD-081 - merged, so it no longer blocks anythingPROD-081PROD-082 - P1 - layer the token model the way components are layered, and decide whether it speaks DTCGPROD-082PROD-084 - P2 - an extension token has one value, not one per mode, so anything carrying a colour is wrong in darkPROD-084
4 nodes, 4 unbuilt
PROD-124 - P1 - the seat spec format: what a complete answer looks like, in one shape every role reusesPROD-124PROD-126 - P1 - the seat field routes nothing, so the interview cannot have more than one seatPROD-126PROD-127 - P1 - nothing judges whether the interview collected enough to proceedPROD-127PROD-128 - P1 - no seat has a toolkit inventory, so nobody knows which seats the template has not really builtPROD-128
3 nodes, 1 unbuilt
AUTH-024 - merged, so it no longer blocks anythingAUTH-024AUTH-035 - merged, so it no longer blocks anythingAUTH-035AUTH-036 - P3 - Erasure trusts our own cookie that Google re-asked, so deleting prompt=login from the URL still passesAUTH-036
3 nodes, 1 unbuilt
AUTH-032 - merged, so it no longer blocks anythingAUTH-032AUTH-033 - merged, so it no longer blocks anythingAUTH-033OPS-227 - unscored - Six tickets at security_impact high or critical carry no done_when, so nothing can ever verify themOPS-227
3 nodes, 1 unbuilt
CLI-044 - merged, so it no longer blocks anythingCLI-044CLI-045 - P3 - the component tests that need a database do not travel, and neither does a test-only dependencyCLI-045COMP-056 - drafted, so it no longer blocks anythingCOMP-056
3 nodes, 2 unbuilt
COMP-021 - drafted, so it no longer blocks anythingCOMP-021OPS-284 - P2 - A done_when that runs mutation_probe.py or check_breakages.py fails in the check_tickets sandbox on git ls-filesOPS-284OPS-382 - P3 - request_log _covers has a killing test and no mutation siteOPS-382
3 nodes, 1 unbuilt
COMP-048 - merged, so it no longer blocks anythingCOMP-048COMP-057 - merged, so it no longer blocks anythingCOMP-057CORE-056 - P1 - Every scaffolded product ships a failing /readyz test, so examples-gate is red for all of themCORE-056
3 nodes, 1 unbuilt
COMP-068 - drafted, so it no longer blocks anythingCOMP-068COMP-069 - drafted, so it no longer blocks anythingCOMP-069CORE-060 - P2 - A declared credential path that matches no route is inert and looks like protectionCORE-060
3 nodes, 2 unbuilt
COMP-111 - merged, so it no longer blocks anythingCOMP-111COMP-112 - P1 - installing five components changes not one byte of any existing pageCOMP-112COMP-117 - P2 - every bare text link is a 17-20px tap target against a 44px minimumCOMP-117
3 nodes, 0 unbuilt
COMP-135 - drafted, so it no longer blocks anythingCOMP-135CORE-064 - merged, so it no longer blocks anythingCORE-064CORE-099 - merged, so it no longer blocks anythingCORE-099
3 nodes, 0 unbuilt
COMP-147 - merged, so it no longer blocks anythingCOMP-147COMP-148 - merged, so it no longer blocks anythingCOMP-148CORE-106 - merged, so it no longer blocks anythingCORE-106
3 nodes, 2 unbuilt
CORE-018 - P3 - Five names in config/database.py have no caller, and the provides manifests are what make them look alive to the dead-code gatesCORE-018CORE-034 - P3 - DatabaseConfig writes the engine to two places, and copied core ships four speculative schema classesCORE-034CORE-035 - drafted, so it no longer blocks anythingCORE-035
3 nodes, 0 unbuilt
CORE-089 - merged, so it no longer blocks anythingCORE-089CORE-090 - merged, so it no longer blocks anythingCORE-090CORE-091 - merged, so it no longer blocks anythingCORE-091
3 nodes, 2 unbuilt
OPS-078 - merged, so it no longer blocks anythingOPS-078OPS-080 - P1 - a downgrade that deletes rows in raw SQL is costed at zeroOPS-080OPS-081 - P3 - a unique constraint is additive DDL that makes the old version's writes failOPS-081
3 nodes, 3 unbuilt
OPS-184 - P0 - Eight drifted sites stop make mutation measuring any of its seventy guardsOPS-184OPS-185 - P1 - The mutation probe is blind to decorator-applied guards and to route modulesOPS-185OPS-381 - P1 - a drifted mutation site is found only by running the slow gateOPS-381
3 nodes, 1 unbuilt
PROD-103 - merged, so it no longer blocks anythingPROD-103PROD-106 - P2 - the interview asks whether people sign in with Google, with a recommendation, and saas new configures itPROD-106PROD-113 - merged, so it no longer blocks anythingPROD-113
2 nodes, 1 unbuilt
AUTH-015 - merged, so it no longer blocks anythingAUTH-015OPS-275 - P2 - The deploy pre-check and three docs still say staging may use the console mailer, after AUTH-015 refuses itOPS-275
2 nodes, 1 unbuilt
AUTH-040 - drafted, so it no longer blocks anythingAUTH-040AUTH-046 - P3 - Registration answers 400 Email already registered, so it tells anyone whether an address has an accountAUTH-046
2 nodes, 2 unbuilt
CLI-002 - unscored - Component upgrade commandCLI-002CLI-041 - unscored - fold `saas upgrade` into `saas update --only`, so there is one merge mechanismCLI-041
2 nodes, 0 unbuilt
CLI-077 - drafted, so it no longer blocks anythingCLI-077CLI-078 - drafted, so it no longer blocks anythingCLI-078
2 nodes, 1 unbuilt
CLI-084 - P1 - saas feature's generated list routes fail the product's mypy: page_of takes Select[tuple[T]] and select(Model) is Select[T]CLI-084OPS-095 - drafted, so it no longer blocks anythingOPS-095
2 nodes, 1 unbuilt
CLI-085 - merged, so it no longer blocks anythingCLI-085OPS-260 - P2 - provision tenant n+1 and update a two-instance fleet, adr-008 has never run with two tenantsOPS-260
2 nodes, 1 unbuilt
COMP-059 - drafted, so it no longer blocks anythingCOMP-059PROD-023 - P1 - The shop's address is still one string, and the fields it should be exist nowPROD-023
2 nodes, 1 unbuilt
COMP-070 - merged, so it no longer blocks anythingCOMP-070COMP-159 - P2 - The billing mode is never logged at startup, so contracts/billing.md criterion 26 failsCOMP-159
2 nodes, 0 unbuilt
COMP-074 - merged, so it no longer blocks anythingCOMP-074PROD-041 - merged, so it no longer blocks anythingPROD-041
2 nodes, 2 unbuilt
COMP-075 - P2 - An LLM capability a product installs with saas add, rather than three adapters inside coreCOMP-075CORE-019 - P3 - The adapter layer has no caller after two shipped products, and every scaffolded project fails its own health check on two dead Settings fields belonging to itCORE-019
2 nodes, 1 unbuilt
COMP-103 - merged, so it no longer blocks anythingCOMP-103PROD-024 - P0 - A child's wishlist token is a path segment, so every page view writes a live bearer credential into the access logPROD-024
2 nodes, 0 unbuilt
COMP-109 - merged, so it no longer blocks anythingCOMP-109COMP-122 - merged, so it no longer blocks anythingCOMP-122
2 nodes, 1 unbuilt
COMP-118 - merged, so it no longer blocks anythingCOMP-118OPS-233 - P3 - The fly preflight checks that BILLING_WEBHOOK_SECRET is set and never what it isOPS-233
2 nodes, 0 unbuilt
COMP-119 - merged, so it no longer blocks anythingCOMP-119COMP-120 - drafted, so it no longer blocks anythingCOMP-120
2 nodes, 0 unbuilt
COMP-158 - merged, so it no longer blocks anythingCOMP-158COMP-160 - merged, so it no longer blocks anythingCOMP-160
2 nodes, 0 unbuilt
CORE-030 - drafted, so it no longer blocks anythingCORE-030CORE-031 - drafted, so it no longer blocks anythingCORE-031
2 nodes, 0 unbuilt
CORE-055 - merged, so it no longer blocks anythingCORE-055CORE-115 - merged, so it no longer blocks anythingCORE-115
2 nodes, 1 unbuilt
DOC-062 - merged, so it no longer blocks anythingDOC-062DOC-067 - P2 - The PRD and the TDD he ruled must-have have no ticketDOC-067
2 nodes, 1 unbuilt
DOC-110 - drafted, so it no longer blocks anythingDOC-110DOC-135 - P3 - 97 owner tickets date themselves by manual@sha and the mandate gate cannot read itDOC-135
2 nodes, 2 unbuilt
DOC-114 - P2 - DEV-CHECKLIST section A adds a component saas new already installed, so step 6 does nothingDOC-114DOC-115 - P2 - DEV-CHECKLIST step 8's op count is satisfied by a comment, so it passes on an empty migrationDOC-115
2 nodes, 0 unbuilt
DOC-132 - merged, so it no longer blocks anythingDOC-132DOC-133 - merged, so it no longer blocks anythingDOC-133
2 nodes, 1 unbuilt
OPS-017 - merged, so it no longer blocks anythingOPS-017OPS-042 - P1 - Nothing proves the whole chain, because no automated run goes from empty directory to a deployed URLOPS-042
2 nodes, 2 unbuilt
OPS-082 - P1 - every gate runs saas from an interpreter no founder hasOPS-082OPS-354 - P3 - the five walk gates still drive saas from the verify venvOPS-354
2 nodes, 0 unbuilt
OPS-087 - drafted, so it no longer blocks anythingOPS-087OPS-093 - merged, so it no longer blocks anythingOPS-093
2 nodes, 0 unbuilt
OPS-089 - drafted, so it no longer blocks anythingOPS-089OPS-092 - merged, so it no longer blocks anythingOPS-092
2 nodes, 0 unbuilt
OPS-119 - merged, so it no longer blocks anythingOPS-119OPS-122 - drafted, so it no longer blocks anythingOPS-122
2 nodes, 1 unbuilt
OPS-143 - drafted, so it no longer blocks anythingOPS-143OPS-238 - P2 - the criterion-proof gate's own self-test has never been shown able to failOPS-238
2 nodes, 1 unbuilt
OPS-144 - merged, so it no longer blocks anythingOPS-144OPS-150 - P1 - How a score gets revised after the world changes, and which signals can be recomputed rather than re-assertedOPS-150
2 nodes, 0 unbuilt
OPS-205 - merged, so it no longer blocks anythingOPS-205OPS-210 - merged, so it no longer blocks anythingOPS-210
2 nodes, 1 unbuilt
OPS-307 - merged, so it no longer blocks anythingOPS-307OPS-308 - P1 - an outside monitor account watches each production /healthz, and its URL is declared in saas.tomlOPS-308
2 nodes, 1 unbuilt
OPS-315 - merged, so it no longer blocks anythingOPS-315OPS-318 - P3 - an erasure ledger carries no product identity, so a foreign one is replayedOPS-318
2 nodes, 2 unbuilt
OPS-319 - P2 - check_product_ci --self-test prints FAIL lines that read as real findingsOPS-319OPS-348 - P1 - check_criterion_proof reads exit codes as pytest, so a checker's 1 and 2 are backwardsOPS-348
2 nodes, 2 unbuilt
PROD-087 - P0 - the interview never asks what the product is, so every question after it is unanswerablePROD-087PROD-088 - P0 - the interview is a continuing conversation, not a form that ends at onboardingPROD-088

348 tickets with no edge at all

One dot each, coloured by derived priority. Nothing blocks them and they block nothing, which is another way of saying prioritisation has to read every one of them. Hover for the id and the title.

AUTH-005AUTH-011AUTH-012AUTH-014AUTH-026AUTH-028AUTH-029AUTH-030AUTH-051AUTH-052AUTH-055AUTH-056AUTH-058CLI-003CLI-004CLI-032CLI-043CLI-046CLI-048CLI-049CLI-050CLI-055CLI-062CLI-063CLI-067CLI-082CLI-086CLI-100CLI-102CLI-108CLI-109COMP-002COMP-004COMP-006COMP-007COMP-011COMP-013COMP-014COMP-015COMP-020COMP-023COMP-026COMP-027COMP-028COMP-029COMP-030COMP-031COMP-032COMP-033COMP-039COMP-040COMP-041COMP-042COMP-043COMP-044COMP-049COMP-050COMP-052COMP-053COMP-054COMP-055COMP-064COMP-071COMP-073COMP-076COMP-082COMP-090COMP-094COMP-095COMP-107COMP-108COMP-110COMP-115COMP-129COMP-133COMP-143COMP-166COMP-172COMP-173COMP-178COMP-179COMP-180COMP-181COMP-183COMP-185COMP-186COMP-187COMP-188COMP-189COMP-190COMP-193COMP-194COMP-195COMP-197COMP-198COMP-199COMP-200COMP-201COMP-202COMP-203COMP-205COMP-206COMP-209COMP-215COMP-226COMP-228COMP-229COMP-233COMP-234CORE-008CORE-010CORE-012CORE-036CORE-040CORE-041CORE-042CORE-043CORE-058CORE-066CORE-078CORE-079CORE-092CORE-102CORE-114CORE-119CORE-130CORE-131CORE-132CORE-135DOC-001DOC-004DOC-006DOC-007DOC-008DOC-014DOC-016DOC-018DOC-021DOC-025DOC-026DOC-027DOC-031DOC-033DOC-034DOC-035DOC-038DOC-041DOC-044DOC-045DOC-047DOC-048DOC-055DOC-056DOC-057DOC-058DOC-059DOC-061DOC-068DOC-069DOC-070DOC-081DOC-083DOC-084DOC-085DOC-086DOC-087DOC-088DOC-089DOC-090DOC-091DOC-092DOC-093DOC-094DOC-095DOC-097DOC-098DOC-101DOC-105DOC-106DOC-111DOC-120DOC-128DOC-136DOC-137DOC-138DOC-139OPS-004OPS-006OPS-016OPS-031OPS-038OPS-039OPS-047OPS-048OPS-049OPS-050OPS-052OPS-053OPS-056OPS-084OPS-088OPS-091OPS-096OPS-106OPS-107OPS-108OPS-112OPS-116OPS-117OPS-118OPS-120OPS-121OPS-124OPS-137OPS-138OPS-142OPS-146OPS-151OPS-154OPS-156OPS-157OPS-158OPS-159OPS-160OPS-161OPS-162OPS-163OPS-164OPS-165OPS-166OPS-167OPS-168OPS-170OPS-171OPS-172OPS-173OPS-175OPS-176OPS-177OPS-179OPS-180OPS-181OPS-186OPS-187OPS-188OPS-190OPS-195OPS-199OPS-202OPS-203OPS-204OPS-216OPS-229OPS-237OPS-242OPS-248OPS-261OPS-264OPS-268OPS-270OPS-272OPS-274OPS-277OPS-279OPS-283OPS-285OPS-286OPS-288OPS-292OPS-295OPS-297OPS-304OPS-309OPS-310OPS-312OPS-316OPS-317OPS-328OPS-338OPS-346OPS-347OPS-349OPS-352OPS-353OPS-355OPS-356OPS-357OPS-358OPS-365OPS-366OPS-367OPS-368OPS-374OPS-377OPS-378OPS-380PROD-003PROD-005PROD-007PROD-042PROD-043PROD-044PROD-045PROD-046PROD-047PROD-048PROD-049PROD-050PROD-051PROD-052PROD-053PROD-054PROD-055PROD-060PROD-061PROD-070PROD-071PROD-072PROD-073PROD-074PROD-075PROD-076PROD-077PROD-078PROD-079PROD-080PROD-089PROD-090PROD-091PROD-092PROD-093PROD-094PROD-095PROD-096PROD-097PROD-099PROD-100PROD-101PROD-104PROD-105PROD-107PROD-108PROD-119PROD-120PROD-121PROD-122PROD-123PROD-125

From docs/state.json -> backlog.graph, with node status from backlog.tickets and backlog.built_ids_by_status. Components are the blocked_by graph treated as undirected, because the question is how entangled the backlog is and a chain is one lump whichever way its arrows point.