saas-templatethe graph, actual size

What waits on what, and mostly nothing does

62 blocked_by edges over 245 dispatchable tickets. Drawn at the size the data actually is: 29 disconnected fragments, and a field of 205 tickets nothing points at.

fragments
29
largest
11nodes
nodes in a fragment
89
of those, still unbuilt
40of 89
no edge at all
205

The 29 fragments

49 of the 89 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

11 nodes, 1 unbuilt
AUTH-004 - drafted, so it no longer blocks anythingAUTH-004AUTH-023 - drafted, so it no longer blocks anythingAUTH-023CLI-040 - drafted, so it no longer blocks anythingCLI-040CORE-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 - drafted, so it no longer blocks anythingCORE-049CORE-050 - drafted, so it no longer blocks anythingCORE-050CORE-051 - drafted, so it no longer blocks anythingCORE-051OPS-058 - P3 - A restored backup brings an erased person back, and nothing re-applies the erasureOPS-058PROD-004 - drafted, so it no longer blocks anythingPROD-004
7 nodes, 2 unbuilt
AUTH-008 - drafted, so it no longer blocks anythingAUTH-008AUTH-018 - drafted, 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 - drafted, 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
5 nodes, 4 unbuilt
COMP-083 - unscored - the seven surfaces every product has and nobody designsCOMP-083COMP-086 - unscored - An invitation is a link a founder copies, and there is no messageCOMP-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 - drafted, so it no longer blocks anythingCORE-070
4 nodes, 0 unbuilt
OPS-103 - drafted, so it no longer blocks anythingOPS-103OPS-104 - drafted, so it no longer blocks anythingOPS-104OPS-105 - drafted, so it no longer blocks anythingOPS-105OPS-110 - drafted, so it no longer blocks anythingOPS-110
4 nodes, 4 unbuilt
OPS-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-139
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
3 nodes, 1 unbuilt
CLI-044 - drafted, 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-005 - drafted, so it no longer blocks anythingCOMP-005COMP-037 - P1 - Nothing acts when a grace period expires, so a past_due subscription stays past_due forever and the customer finds out by being refusedCOMP-037COMP-038 - P1 - A webhook that fails to apply is only recovered by the provider's retry, and the shipped provider does not retryCOMP-038
3 nodes, 2 unbuilt
COMP-016 - P1 - The grace dunning branch keeps access and tells nobody whyCOMP-016COMP-077 - P1 - One place from which every alert to a user is producedCOMP-077CORE-004 - drafted, so it no longer blocks anythingCORE-004
3 nodes, 2 unbuilt
COMP-048 - drafted, so it no longer blocks anythingCOMP-048COMP-057 - P1 - A charge the provider accepted is rolled back with the request that failed after itCOMP-057CORE-056 - P1 - Every scaffolded product ships a failing /readyz test, so examples-gate is red for all of themCORE-056
3 nodes, 2 unbuilt
COMP-068 - drafted, so it no longer blocks anythingCOMP-068COMP-069 - P2 - A capability URL that carries its token in the query string is still copied into nextCOMP-069CORE-060 - P2 - A declared credential path that matches no route is inert and looks like protectionCORE-060
3 nodes, 2 unbuilt
COMP-079 - P0 - The invite holds an invitee's email before there is an account, so its declaration names a guest subjectCOMP-079CORE-067 - P0 - The personal-data gate is table-level, so a new column on a declared table walks past itCORE-067CORE-069 - drafted, so it no longer blocks anythingCORE-069
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, 2 unbuilt
OPS-078 - drafted, 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
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, 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, 0 unbuilt
COMP-061 - drafted, so it no longer blocks anythingCOMP-061CORE-059 - drafted, so it no longer blocks anythingCORE-059
2 nodes, 0 unbuilt
COMP-074 - drafted, so it no longer blocks anythingCOMP-074PROD-041 - drafted, 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, 0 unbuilt
CORE-030 - drafted, so it no longer blocks anythingCORE-030CORE-031 - drafted, so it no longer blocks anythingCORE-031
2 nodes, 1 unbuilt
CORE-039 - drafted, so it no longer blocks anythingCORE-039CORE-052 - P2 - A product can add a table and no gate asks what its retention isCORE-052
2 nodes, 0 unbuilt
CORE-062 - drafted, so it no longer blocks anythingCORE-062CORE-063 - drafted, so it no longer blocks anythingCORE-063
2 nodes, 2 unbuilt
CORE-075 - P0 - Nine postgres tests are red on mainCORE-075OPS-130 - P1 - Six guards die only in the suite make verify never runsOPS-130
2 nodes, 1 unbuilt
DOC-062 - drafted, 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
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, 0 unbuilt
OPS-057 - drafted, so it no longer blocks anythingOPS-057OPS-064 - drafted, so it no longer blocks anythingOPS-064
2 nodes, 0 unbuilt
OPS-087 - drafted, so it no longer blocks anythingOPS-087OPS-093 - drafted, so it no longer blocks anythingOPS-093
2 nodes, 0 unbuilt
OPS-089 - drafted, so it no longer blocks anythingOPS-089OPS-092 - drafted, so it no longer blocks anythingOPS-092
2 nodes, 0 unbuilt
OPS-119 - drafted, so it no longer blocks anythingOPS-119OPS-122 - drafted, so it no longer blocks anythingOPS-122

205 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-010AUTH-011AUTH-012AUTH-014AUTH-016AUTH-024AUTH-026AUTH-027AUTH-028AUTH-029AUTH-030CLI-003CLI-004CLI-032CLI-043CLI-046CLI-048CLI-049CLI-050CLI-051CLI-054CLI-055CLI-060CLI-062COMP-002COMP-004COMP-006COMP-007COMP-011COMP-013COMP-014COMP-015COMP-019COMP-020COMP-022COMP-023COMP-026COMP-027COMP-028COMP-029COMP-030COMP-031COMP-032COMP-033COMP-039COMP-040COMP-041COMP-042COMP-043COMP-044COMP-049COMP-050COMP-052COMP-053COMP-054COMP-055COMP-062COMP-064COMP-065COMP-070COMP-071COMP-073COMP-076COMP-082COMP-090COMP-091COMP-092COMP-093COMP-094COMP-095COMP-097COMP-098CORE-008CORE-010CORE-012CORE-017CORE-036CORE-040CORE-041CORE-042CORE-043CORE-048CORE-057CORE-058CORE-061CORE-065CORE-066CORE-072CORE-074DOC-001DOC-004DOC-005DOC-006DOC-007DOC-008DOC-009DOC-014DOC-016DOC-017DOC-018DOC-021DOC-024DOC-025DOC-026DOC-027DOC-031DOC-033DOC-034DOC-035DOC-038DOC-041DOC-044DOC-045DOC-047DOC-048DOC-055DOC-056DOC-057DOC-058DOC-059DOC-060DOC-061DOC-068DOC-069DOC-070DOC-076DOC-077DOC-080DOC-081OPS-004OPS-006OPS-012OPS-016OPS-031OPS-035OPS-036OPS-037OPS-038OPS-039OPS-047OPS-048OPS-049OPS-050OPS-051OPS-052OPS-053OPS-056OPS-061OPS-068OPS-075OPS-082OPS-084OPS-091OPS-096OPS-098OPS-101OPS-106OPS-107OPS-108OPS-111OPS-112OPS-113OPS-114OPS-115OPS-116OPS-117OPS-118OPS-120OPS-121OPS-124OPS-125OPS-127OPS-128OPS-129OPS-134OPS-135OPS-137OPS-138OPS-140OPS-141OPS-142OPS-145OPS-146OPS-147OPS-148PROD-003PROD-005PROD-007PROD-024PROD-039PROD-042PROD-043PROD-044PROD-045PROD-046PROD-047PROD-048PROD-049PROD-050PROD-051PROD-052PROD-053PROD-054PROD-055

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.