A code-to-column change-impact knowledge graph for AI coding agents.
Every number in this document was produced by running the engine, and every row names the command that produces it again. The second half of the page, the list of what is not verified, matters more than the first: a tool whose only durable difference is honesty has to be honest about its own evidence.
scripts/generality-gate.mjs runs this engine, unchanged and with no
per-project configuration, over a pinned corpus of real repositories nobody
here wrote it for, and prints what it reached.
The engine’s own tests prove that each rule does what it says on a fixture chosen to exercise it. They cannot tell you whether the SET of rules adds up to something that works on a repository nobody here has read. That question has one honest answer, which is to run it and count, and the answer is only worth anything if it repeats: the same commits, the same flags, the same numbers, so a change that quietly loses a DAO layer shows up as a smaller number rather than as nothing at all.
node scripts/generality-gate.mjs --fetch # clone or check out every pin, then run
node scripts/generality-gate.mjs --fetch --no-run # clone only
node scripts/generality-gate.mjs # run over whatever is cloned
node scripts/generality-gate.mjs --only mall,litemall
node scripts/generality-gate.mjs --accept # rewrite the baseline, printing the diff
test/generality_gate.test.mjs compares the result against
test/fixtures/generality-gate.baseline.json and fails when a repository
reaches less than it did. A rise changes nothing until somebody runs
--accept: a number that improves silently is a number nobody checked. The
clones live under the cache directory, about 1 GB in all, never inside this
repository, and each run gets its own registry so the gate cannot write into
yours.
Six counts are guarded. Five of them are floors, and a drop in any fails the suite.
| Repository | Pinned at | Endpoints reaching a statement | Tables reached | Columns reached | Frontend calls resolved | Screens reaching a table | Endpoint to column pairs |
|---|---|---|---|---|---|---|---|
| jeecgboot/JeecgBoot | 74364054 |
744 / 969 | 73 / 177 | 836 / 2092 | 562 / 963 | 25 / 181 | 15997 |
| jishenghua/JSH_ERP | ad6cf886 |
330 / 339 | 32 / 32 | 409 / 413 | 165 / 221 | 0 / 7 | 13179 |
| apache/dolphinscheduler | 499fd068 |
204 / 239 | 42 / 65 | 457 / 622 | 219 / 233 | 0 / 44 | 6216 |
| macrozheng/mall + mall-admin-web | 0504e86b + 81fc17e5 |
205 / 239 | 49 / 76 | 461 / 669 | 145 / 153 | 44 / 54 | 3868 |
| linlinjava/litemall | a1ef964a |
198 / 219 | 34 / 34 | 376 / 376 | 172 / 191 | 40 / 89 | 4223 |
| yangzongzhuan/RuoYi-Vue + RuoYi-Vue3 | 13db1fce + 838965c5 |
123 / 147 | 22 / 33 | 224 / 305 | 122 / 142 | 8 / 21 | 1613 |
| jeequan/jeepay | ba371119 |
126 / 134 | 22 / 23 | 302 / 314 | 0 / 0 | 0 / 5 | 3554 |
| xuxueli/xxl-job | e74c784f |
31 / 42 | 7 / 8 | 70 / 71 | 24 / 31 | 6 / 11 | 528 |
| mybatis/jpetstore-6 | ebb36b39 |
11 / 22 | 12 / 13 | 77 / 86 | 52 / 53 | 16 / 16 | 243 |
| spring-projects/spring-petclinic | 818c4136 |
15 / 17 | 7 / 7 | 24 / 24 | 12 / 13 | 3 / 8 | 196 |
| spring-petclinic-microservices | 3858f9c6 |
13 / 15 | 7 / 7 | 24 / 24 | 14 / 14 | 8 / 9 | 99 |
The table and column counts above were taken before RM67, when a census still counted a table or a column reached only through a guessed edge. Four of them are lower now (jeecg-boot, dolphinscheduler, jeepay, spring-petclinic-microservices); the RM67 section has the numbers and the declaration that restores each.
Six more repositories joined this corpus in RM55 and are measured in their own section, which keeps the measurement taken BEFORE any rule was written for them beside the one after. Two more joined in RM63, a WebSquare client and a system whose logic sits in stored routines, and their section does the same.
The last column is the sixth, and it is guarded the other way up. It adds up, over every endpoint, how many distinct columns that one endpoint reaches, and a rise of more than five percent fails the suite. It is here because the five floors are all union counts over the whole project, and a union count cannot see reach that smears sideways: when one generic base method resolved in every subclass at once, jeecg carried 9,400 false endpoint-to-column pairs, not one of them naming a column some other endpoint did not already reach on its own. Every floor above stayed exactly where it is written, and the gate stayed green. The pair sum is the number that moved, 25,397 down to 15,997 when the rule was fixed, and it is guarded now so the next one fails instead.
The other half of a gate run is what each pack said about itself before anybody asked it a question.
| Repository | catalog | statements | jpa | mybatisPlus | column | code | web | screen |
|---|---|---|---|---|---|---|---|---|
| jeecg-boot | shipped | shipped | not-shipped | degraded | shipped | shipped | shipped | shipped |
| jsh-erp | shipped | shipped | not-shipped | not-shipped | shipped | shipped | degraded | shipped |
| dolphinscheduler | shipped | shipped | not-shipped | degraded | shipped | shipped | shipped | degraded |
| mall | shipped | shipped | not-shipped | not-shipped | shipped | shipped | shipped | shipped |
| litemall | shipped | shipped | not-shipped | not-shipped | shipped | shipped | degraded | shipped |
| ruoyi-vue | shipped | shipped | not-shipped | not-shipped | shipped | shipped | shipped | degraded |
| jeepay | shipped | shipped | not-shipped | degraded | shipped | shipped | not-shipped | not-shipped |
| xxl-job | shipped | shipped | not-shipped | not-shipped | shipped | shipped | shipped | degraded |
| jpetstore-6 | shipped | shipped | not-shipped | not-shipped | shipped | shipped | shipped | shipped |
| spring-petclinic | shipped | not-shipped | degraded | not-shipped | degraded | shipped | shipped | degraded |
| petclinic-ms | shipped | not-shipped | degraded | not-shipped | degraded | shipped | shipped | shipped |
degraded on mybatisPlus there is the naming strategy: no profile in the
corpus declares one, so the engine assumes MyBatis-Plus’s own default, grades
every name it derived that way HEURISTIC, and says so. degraded on web is
the frontend prefix: nothing in the source states it, so the engine matched
candidates against the routes and took the best fit, which is a guess and is
graded as one. degraded on screen is a router the server fills in at run
time, which means the screens in the source are not the screens the product has.
“204 of 239 endpoints reach a statement” says the engine connected 204 chains. Whether the other 35 touch no database at all (a login, a file upload, a health check) or whether the engine lost one of their calls is a question only reading them answers, and the round that adds a repository to this table is the round that reads them. It is not a benchmark and it is not a claim of correctness.
Three of those frontend numbers are new in RM47, and none of them came from a
flag. The petclinic gateway ships its frontend as <script src> tags with no
package.json anywhere: 22 files, nine screens and thirteen $http calls that
the lane refused to open until this round, so both of its frontend columns said
“no frontend read”. cascade init now calls a directory of frontend sources the
tree says it serves a web root and writes it into the profile. xxl-job gains a
web lane over 19 loose scripts and reads two call sites out of them, neither
resolving to a route it serves, which is why its web axis is degraded rather
than shipped; jeecg-boot picks up five more call sites the same way, none of
them resolving either. jeepay is the case that stays where it was on purpose:
its static/cashier/js is a webpack build, and a .js with a .js.map beside
it is output rather than a frontend somebody keeps here. See
the web lane.
Four of them are new in RM48, and none of them came from a flag either. Three
of these projects have no frontend router at all: a @Controller returns a view
name, a template engine renders it, and the page’s own <form>, its links and
its inline <script> are what talk to the backend. spring-petclinic, xxl-job
and jpetstore-6 had zero screens for exactly that reason, and now have 8, 11
and 16. jpetstore’s 20 JSP pages yield 52 resolved calls out of 53 and every one
of its 16 pages reaches a table, which is why it is the one project here whose
screen axis reads shipped. jeecg-boot gains 15 pages beside the 166 screens
its Vue frontend’s router declares, and jeepay 5 payment pages it had none of.
Ten of jpetstore’s sixteen page names, and five of petclinic’s eight, are not
literals at the return statement at all: they are a static final String the
controller declares (return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;) or a private
method of the same class whose returns are literals (petclinic’s
addPaginationModel). Both are read out of ONE file, so both are EXACT like any
other literal. What is still not read is a name that would need another file or
a data-flow answer: 2 of petclinic’s returns ("redirect:/owners/" +
owner.getId()) and 2 of xxl-job’s, which is why those two read degraded.
One entry is worth reading as a limit rather than as a score. jeecg-boot
declares 173 routes, 87 of them the framework’s own demo pages, and fetches
every business screen at run time from a route named after permissions
rather than after menus. No spelling in the server-menu rule matches it, so its
screen axis reads shipped and “19 of 166 screens reach a table” reads as a
shortfall rather than as a description of a product whose screens are mostly not
in its source. Adding that project’s own spelling to the rule would be a rule
that works on that project and nowhere else, so the table stays generic and this
is written down instead.
The eleven repositories above are the frameworks the world writes in. They are not the market this product is for. So RM55 cloned the public repositories that are — eGovFrame, which every Korean public sector project is required to build on, a Nexacro client over an eGovFrame backend, and one modern Korean OSS as a control — and measured them before writing a line of code for them. That first measurement is kept here beside the one after, so anyone can see which numbers the round moved and which it did not.
| Repository | Pinned at | Endpoints reaching a statement | Tables reached | Columns reached | Frontend calls resolved | Screens reaching a table | Endpoint to column pairs |
|---|---|---|---|---|---|---|---|
| egovframe-common-components | a88a3e31 |
0 / 1193 | 0 / 184 | 0 / 1956 | 0 / 13 | 0 / 1 | 0 |
| egovframe-enterprise-business-template | cfccbe89 |
0 / 219 | 0 / 35 | 0 / 288 | 0 / 4 | 0 / 0 | 0 |
| egovframe-msa-edu | 777f697c |
90 / 163 | 20 / 25 | 191 / 270 | 2 / 217 | 0 / 0 | 394 |
| egovframe-web-sample | 8f37555e |
5 / 6 | 1 / 1 | 5 / 5 | 0 / 0 | 0 / 0 | 5 |
| nexacro-sample-egov | deb90f90 |
6 / 21 | 2 / 5 | 9 / 46 | 0 / 0 | 0 / 0 | 27 |
| naver/ngrinder | 2a6da299 |
30 / 124 | 7 / 9 | 92 / 114 | 66 / 77 | 0 / 19 | 900 |
Two of those rows are the finding. 219 routes and 205 statements, 1,193 routes and 1,256 statements, and not one edge between them: nothing a route reached ended at a table. The product was useless on eGovFrame, and the causes were three, each verified by reading the trees:
selectList("CmmnDetailCodeManageDAO.selectCmmnDetailCodeList",
vo). There is no mapper interface anywhere, and the engine bound a statement
only through one.egov-com-servlet.xml rather than in
application.yml.| Repository | Endpoints reaching a statement | Tables reached | Columns reached | Frontend calls resolved | Screens reaching a table | Endpoint to column pairs | Wall |
|---|---|---|---|---|---|---|---|
| egovframe-common-components | 999 / 1193 | 165 / 179 | 1640 / 1818 | 765 / 811 | 470 / 657 | 9568 | 50 s |
| egovframe-enterprise-business-template | 163 / 219 | 30 / 35 | 210 / 288 | 122 / 135 | 55 / 84 | 1889 | 4 s |
| egovframe-msa-edu | 90 / 163 | 20 / 25 | 191 / 270 | 2 / 217 | 0 / 0 | 394 | 1 s |
| egovframe-web-sample | 5 / 6 | 1 / 1 | 5 / 5 | 0 / 0 | 0 / 2 | 5 | 1 s |
| nexacro-sample-egov | 2 / 21 | 2 / 5 | 9 / 46 | 0 / 0 | 0 / 0 | 9 | 1 s |
| ngrinder | 30 / 124 | 7 / 9 | 92 / 114 | 66 / 77 | 0 / 19 | 900 | 1 s |
The one number that went DOWN is the one worth reading. nexacro-sample-egov
fell from 6 endpoints reaching a statement to 2, and its pair count from 27 to 9,
while the tables and columns it reaches did not move at all. That project
declares one SampleService interface with two implementations — one over
iBATIS, one over MyBatis — and one LargeDataService with three. Every
controller reached all of them through the interface, so four routes claimed to
run MyBatis statements that their own @Resource(name = "sampleService") says
they never touch. Reading the bean name removed exactly those four, and the two
that remain (/sampleMybatisSelectVO.do, /sampleMybatisLargeData.do) are the
two routes wired to the MyBatis implementation. Verified by running the same
commit with the rule switched off and listing both sets.
msa-edu and ngrinder did not move by one number, which is the other half of the result: neither has a mapper XML, an XML view resolver or a vendor DDL tree, so none of the three rules had anything to fire on. Their frontends (two Next.js applications and a Nexacro client) are still unread, and that is the next round.
The eleven repositories above this section did not move by one number either.
RM55 fixed what a route reaches; it left the frontends and half the SQL. RM56 took those: one vendor’s mapper XML, iBATIS 2 in the SQL lane, a Nexacro client in the web lane, and Next.js file routing.
| Repository | Endpoints reaching a statement | Tables reached | Columns reached | Frontend calls resolved | Screens reaching a table | Endpoint to column pairs | Wall |
|---|---|---|---|---|---|---|---|
| egovframe-common-components | 999 / 1193 | 165 / 179 | 1680 / 1862 | 765 / 811 | 470 / 657 | 9647 | 22 s |
| egovframe-enterprise-business-template | 163 / 219 | 30 / 35 | 218 / 288 | 122 / 135 | 55 / 84 | 2099 | 2 s |
| egovframe-msa-edu | 90 / 163 | 20 / 25 | 191 / 270 | 2 / 217 | 0 / 56 | 394 | 1 s |
| egovframe-web-sample | 5 / 6 | 1 / 1 | 5 / 5 | 0 / 0 | 0 / 2 | 5 | 0 s |
| nexacro-sample-egov | 10 / 21 | 5 / 5 | 46 / 46 | 7 / 7 | 4 / 30 | 100 | 1 s |
| ngrinder | 30 / 124 | 7 / 9 | 92 / 114 | 66 / 77 | 0 / 19 | 900 | 1 s |
Read row by row:
transaction(…) calls
matched to a .do route.<isNotEmpty> branch structure whose
flattened form holds two SELECTs end to end
(ConectStatsDAO.selectConectStats), which is the flattener’s own limit and
not a vendor’s. The statement count falls 205 → 201 because four
loginDAO.* statements are commented out in the MySQL copy and live only
in the six this project does not run: statements that do not exist for this
deployment. Columns reached rise 210 → 218 for the same reason the parse
failures fell.pages/api counted and read as the
server handlers they are. Its call resolution does not move, and the reason
is not this round’s: its frontend calls /portal-service/api/v1/… through an
API gateway whose RewritePath filter uses a named capture group, which the
gateway-route reader refuses with GATEWAY_ROUTE_UNREADABLE. Until that
prefix is read, the calls name paths no route in the pack serves.<sqlMap>, a Nexacro form or a pages/ tree, so
none of the four rules had anything to fire on.The eleven repositories above this section do not move by one number, all sixteen pack digests are identical, and 3,028 recorded answers are byte-identical.
Two entries trip the ceiling the gate guards the other way up:
endpointColumnPairs rises 1,889 → 2,099 on the business template and 9 → 100
on the Nexacro sample. Both are the same cause as the rises above — statements
that now parse, and a client whose screens now reach tables — rather than reach
smearing sideways, and both are on the held-out six.
BBSAddedOptionsDAO.insert…,
BBSLoneMasterDAO.select…): a component whose Java is shipped and whose SQL is
not. They are listed by name in laneStats.statementIds.unknownSamples rather
than invented.docs/setup/sql-lane.md.RewritePath=/portal-service/(?<segment>.*), /$\{segment}
uses a named capture group the gateway-route reader refuses
(GATEWAY_ROUTE_UNREADABLE), so nothing strips the service prefix off the
calls. That is a gateway rule, not a frontend one, and it is untouched.RM56 read msa-edu’s 56 screens and left its calls at 2 of 217. The two causes were both general, and neither was Korean: a gateway rewrite written the way Spring’s own reference writes it, and one hop between a page and the module its API calls live in.
| Repository | Endpoints reaching a statement | Tables reached | Columns reached | Frontend calls resolved | Screens reaching a table | Endpoint to column pairs | Wall |
|---|---|---|---|---|---|---|---|
| egovframe-common-components | 999 / 1193 | 165 / 179 | 1680 / 1862 | 765 / 811 | 470 / 657 | 9647 | 21 s |
| egovframe-enterprise-business-template | 163 / 219 | 30 / 35 | 218 / 288 | 122 / 135 | 55 / 84 | 2099 | 2 s |
| egovframe-msa-edu | 90 / 163 | 20 / 25 | 191 / 270 | 23 / 217 | 12 / 56 | 394 | 1 s |
| egovframe-web-sample | 5 / 6 | 1 / 1 | 5 / 5 | 0 / 0 | 0 / 2 | 5 | 1 s |
| nexacro-sample-egov | 10 / 21 | 5 / 5 | 46 / 46 | 7 / 7 | 4 / 30 | 100 | 1 s |
| ngrinder | 30 / 124 | 7 / 9 | 92 / 114 | 66 / 77 | 0 / 19 | 900 | 1 s |
Only msa-edu moves, and it moves twice.
RewritePath=/portal-service/(?<segment>.*), /$\{segment} and its five
siblings, and they were refused for a reason the round before got wrong. The
replacement was already read: what was not is that Path=/portal-service/**
names the prefix /portal-service while the pattern writes
/portal-service/, prefix plus separator, so the pattern did not match the
prefix and the reader said so. Both spellings are the same prefix rule, and
reading them alike took the six routes from a GATEWAY_ROUTE_UNREADABLE
diagnostic each to six entries with the service each forwards to, and calls
resolved from 2 of 217 to 23.@service and write contentService.get(id); the calls are in
service/*.ts, in an exported object of functions. The .ts was never the
problem — the resolver already tried .ts first, the @service alias already
resolved and .ts modules already carried CALLS edges. What was missing was
the member: the bridge read svc.method() on an imported object as a call to
nothing it had read, because the key alone (get) does not say which object
it belongs to. The worker now records the owner, and the bridge matches on it:
7 CALLS edges to 100, 31 RENDERS to 81, and screens reaching a table from
0 of 56 to 12.shipped to degraded on msa-edu, and that is
the honest direction. Its call to /api/v1/menus now matches a route, so
the run can see that the app fetches part of its menu at run time and says
that the 62 declared screens are not the whole product. Before the gateway
fix it could not see that and said nothing.rules.duplicateCheckRule,
formApi.doQueryField), which are hops that were always there; not one
guarded number moves.The round trip, end to end, on the /content/{id} screen: RENDERS (EXACT, the
route declaration names the component) to ContentItem, CALLS (SOUND_SET, the
member contentService.save through an export * barrel) to Content.ts#save,
CALLS_HTTP (SOUND_SET, axios, the declared gateway prefix taking
/portal-service off the front) to POST /api/v1/contents, HANDLES (EXACT) to
ContentApiController#save, two MAY_CALL hops to ContentRepository#save,
IMPLEMENTS_STMT (EXACT), and the table content, written.
A URL built on a module constant is still nothing but holes. 73 of msa-edu’s
217 call sites resolve to a template like {*}/{*}, because
axios.get(`${POSTS_URL}/${id}`) records the leading ${POSTS_URL} as a
hole. The worker names the hole (base: "POSTS_URL") and knows the constant’s
value in the same file, but nothing substitutes it, so the path names no route
and the walk stops at the API function. That is why the portal’s own
/board/{skin}/{board}/view/{id} reaches five service functions and no
endpoint. It is a general gap in the URL reader, not a gateway or a member rule,
and it is untouched here.
The gap the round before left on the table: a frontend does not write its paths
at the call site. It writes them once at the top of the file and every call is
that name plus what the caller passes, so axios.get(`${POSTS_URL}/${id}`)
read letter by letter is {*}/{*} and names no route. A hole that is a name the
file can follow to text is now filled in, and the edge says what went in.
| Repository | Endpoints reaching a statement | Tables reached | Columns reached | Frontend calls resolved | Screens reaching a table | Endpoint to column pairs | Wall |
|---|---|---|---|---|---|---|---|
| egovframe-msa-edu | 90 / 163 | 20 / 25 | 191 / 270 | 137 / 217 | 33 / 56 | 394 | 1 s |
| jeecgboot/JeecgBoot | 744 / 969 | 73 / 177 | 836 / 2092 | 584 / 963 | 25 / 181 | 15997 | 14 s |
Two repositories move, both upward, and every other number in the corpus is where it was.
Api.getDictItems, Api.promptGenerate), which is the same shape written
as an enum instead of a const.process.env one file away, so nothing in the
source states them.The round trip on the portal’s /board/{skin}/{board}/view/{id}, which reached
no endpoint at all before: RENDERS (EXACT, the file-tree page declaration) to
[id].tsx#BoardView, CALLS (SOUND_SET, the member boardService.getPostById
through an @service import) to Board.ts#getPostById, CALLS_HTTP (SOUND_SET,
axios, POSTS_URL put into `${POSTS_URL}/view/${boardNo}/${postsNo}` and
the declared gateway prefix taking /board-service off the front) to
GET /api/v1/posts/view/{boardNo}/{postsNo}, HANDLES (EXACT) to
PostsApiController#findViewById, two MAY_CALL hops (SOUND_SET, field receiver)
to PostsRepository.findById, IMPLEMENTS_STMT (EXACT), and the table posts.
The page reaches four tables in all: board, posts, posts_read, comment.
A constant another module exports is followed only when it is a literal.
The bridge resolves the specifier and reads the exported constant, and every
unit test for it passes, but no repository in the corpus exercises it: the eight
import-bound holes left in msa-edu all lead to export const X = process.env.X,
which is a deployment value and is left alone on purpose. A constant whose own
value is built out of another hole (const BANNER_URL = `/api/${SITE_ID}/banners`)
is reported by what stopped it and is not followed further.
A single-page app changes the screen by asking its own router, and the browser
sends nothing. Every rule in the web lane saw a path-shaped argument and called
it a request, so router.push('/auth/login') came out as a call to a route
nothing serves. The sinks are now declared per router and read as navigations.
The Frontend calls column is the end of all three fixes this round made (the
navigation pack, the imported constant, the string method); the paragraphs below
say which took which.
| Repository | Frontend calls | Calls resolved | Navigations | To a screen | Screens reaching a table | Endpoint to column pairs |
|---|---|---|---|---|---|---|
| egovframe-msa-edu | 217 -> 173 | 137 | 68 | 62 | 33 / 56 | 394 |
| jsh-erp | 221 -> 193 (the constant fix, not a navigation) | 165 | 8 | 3 | 0 / 7 | 13179 |
| litemall | 191 -> 177 | 172 | 56 | 37 | 40 / 89 | 4223 |
| jeecgboot/JeecgBoot | 963 -> 938 | 584 | 30 | 15 | 25 / 181 | 15997 |
| naver/ngrinder | 77 -> 69 | 66 -> 63 | 14 | 7 | 0 / 19 | 900 |
| macrozheng/mall | 153 -> 151 | 145 | 32 | 32 | 44 / 54 | 3868 |
| ruoyi-vue | 142 -> 138 | 122 -> 121 | 5 | 4 | 8 / 21 | 1613 |
| egovframe-common-components | 811 -> 810 | 765 | 66 | 0 | 470 / 657 | 9647 |
| egovframe-enterprise-business-template | 135 -> 134 | 122 | 27 | 0 | 55 / 84 | 2099 |
| dolphinscheduler | 233 | 219 | 33 | 18 | 0 / 44 | 6216 |
| xxl-job | 31 | 24 | 5 | 3 | 6 / 11 | 528 |
$router.push('/script/detail/.gitconfig.yml') (which had
matched GET /script/detail/**), $router.push(`/perftest/${id}`) (seven
edges, one call site) and $router.push('/script/list/'); ruoyi-vue loses
router.push('/login'), which had matched POST /login. All four are a
vue-router path that happens to be spelled like a route the same application
serves, which is what an application whose screens mirror its routes looks
like. Nothing else in the corpus loses a resolved call.endpointColumnPairs, screens reaching a
table, tables, columns and endpoints reaching a statement are identical on all
seventeen. Fourteen of the sixteen pack digests are identical; the two that
move are the two registered projects with a web lane, jsh-erp and litemall.location.href in a JSP’s inline script and no route declaration makes
those pages screens, so all 93 are counted and recorded nowhere. That is the
honest answer: the count says the act happened, and there is no screen node to
hang it on.router.push('/404'), which Next’s own error page answers
and which the next-pages pack deliberately leaves out of the screen list; one
relative push('view'); and three whose target is a value handed in from
outside the file.A string method is never an HTTP sink. Five of the MSA template’s nineteen
unanswered paths were pathname.startsWith('/auth/login/naver') and
pathname.indexOf('/refresh'): the argument really is a path, so the URL rule
cannot help, and the METHOD name is what settles it. Reading it that way takes
the template’s call sites 178 to 173 and its unanswered paths 19 to 14, jeecg-boot
950 to 938, ruoyi-vue 141 to 138, and one call each off the two eGovFrame
repositories, jsh-erp and litemall. No repository loses a resolved call, and
endpointColumnPairs, screens reaching a table, tables, columns and endpoints
reaching a statement are identical on all seventeen.
What this round left on the table. A <router-link to=…> is written in a
single-file component’s <template>, and the worker parses a component’s
<script> blocks and not its markup, so that sink is declared and never fires.
Neither does router.push on an application’s OWN router module
(import router from '@/router'), which would need the module traced to a
createRouter(...) the way an axios instance is traced. And a location.href
in a server-rendered page IS a request in a way a router push is not: one such
site in ngrinder (a CSV download) is now counted as a navigation that names no
screen rather than as a call.
A URL that IS an imported constant. RM58 filled the holes a template was
left with and left a URL argument that is the imported name itself resolving to
nothing, counted importedConstant. All 27 of jsh-erp’s importedConstant
unresolved sites were that, and not one was a URL: they are browser-storage keys
read through a verb-named method (Vue.ls.get(ACCESS_TOKEN), where
ACCESS_TOKEN is 'Access-Token'). Reading the value settles the call in both
directions: 221 call sites to 194, 56 unresolved to 29, the same 165 resolved,
and 27 more counted under notUrlShaped, which is where a call that never was
one belongs. sound stays 0 there because every one of jsh-erp’s resolved calls
goes through a prefix chosen by match count, and an auto prefix grades the whole
edge HEURISTIC.
Two shapes measured and deliberately not built. A MyBatis session fetched
and used in one expression (getSqlSession().selectList("X.y", vo)) has zero
sites in all seventeen repositories, and the two getSqlSession() calls that
exist fetch a JDBC connection for table metadata. A Nexacro transaction’s in and
out datasets (75 in the sample) are data flow inside the browser, and what
impact needs is the call, which the transaction record already carries.
The eGovFrame standard is a form whose address is assigned in JavaScript and submitted from JavaScript, and until this round the lane read none of it. Three of the seventeen entries are written that way, and one of them — the framework’s own sample — went from reaching nothing at all to reaching everything it has.
| Repository | Frontend calls | Calls resolved | Screens reaching a table | Endpoint to column pairs |
|---|---|---|---|---|
| egovframe-web-sample | 0 -> 8 | 0 -> 8 | 0 / 2 -> 2 / 2 | 5 |
| egovframe-enterprise-business-template | 134 -> 357 | 122 -> 333 | 55 / 84 -> 72 / 84 | 2099 |
| egovframe-common-components | 810 -> 2156 | 765 -> 2074 | 470 / 657 -> 550 / 657 | 9647 |
| apache/dolphinscheduler | 233 -> 234 | 219 | 0 / 44 | 6216 |
| jeecgboot/JeecgBoot | 938 -> 936 | 584 | 25 / 181 | 15997 |
| the other twelve | unchanged | unchanged | unchanged | unchanged |
var pagetitle = "<spring:message code="comCmm.unitContent.20"/>";, and
'<c:url value='/images/…'/>'), which ends the string early and costs the
whole block. Measured: 348 blocks in 347 of the 739 pages on the common
components and 21 of 90 on the business template, all of those two shapes.
The tags are now taken out before the script is parsed, and 0 pages fail on
either repository.$.ajax and friends in pages that used not to parse). On
the sample: 8 form submits and nothing else, which is the whole of what that
application does.action, never the address a pagination function
assigned above it. Measured before the rule was scoped, 11 of 139 form-submit
edges on the business template and 56 of 569 on the common components had
borrowed a neighbour’s address; after it, 0. Across every page read, the
business template’s submits take their address from an assignment in scope 177
times and from the form element 12 times, and 8 find none; the common
components’ 1254, 67 and 143. A submit with no address is counted
(formSubmitsWithoutAddress: 8 and 134 on the rendered pages) and places no
edge.<form> element. A form the page does not declare leaves the
method unknown, the route is matched against ANY, and the evidence says the
form element was not found.location.href in a JSP is the browser fetching a route.
The business template goes 27 -> 4 and the common components 66 -> 8. What is
left is location.href = "" (a reload, 4 on each), an address that is nothing
but a page expression, and on the common components two that name a screen. RM59’s sentence that the sink alone decides was wrong for the
browser global, and this is the measurement that says so.webCalls moves on exactly two other entries, and both are right.
dolphinscheduler gains one: utils/downloadFile.ts builds a <form>, assigns
form.action = param.url and submits it, which is a request this lane could
not see before and still cannot follow (the address is a parameter, so it is
counted unresolved). jeecg-boot loses two: router.push('/online/...') and
router.push('/myapps/...') on a name imported from its own router module,
which the untraced-call rule had been reading as HTTP calls to routes nothing
serves. Neither was resolved before, so webCallsResolved is identical on all
seventeen.Where the screens lead, by the rule that found them. Navigations rise on six entries and the new sources are the whole of the rise:
| Repository | Navigations | hook | receiver | global | router-module | router-link |
|---|---|---|---|---|---|---|
| litemall | 56 -> 76 | 0 | 55 | 1 | 0 | 20 |
| naver/ngrinder | 14 -> 31 | 0 | 13 | 1 | 0 | 17 |
| ruoyi-vue | 5 -> 20 | 3 | 0 | 2 | 7 | 8 |
| jeecgboot/JeecgBoot | 30 -> 35 | 19 | 0 | 11 | 0 | 5 |
| macrozheng/mall | 32 -> 38 | 32 | 0 | 0 | 0 | 6 |
| jsh-erp | 8 -> 12 | 0 | 5 | 3 | 0 | 4 |
| apache/dolphinscheduler | 33 -> 34 | 32 | 0 | 1 | 1 | 0 |
| egovframe-msa-edu | 68 -> 68 | 68 | 0 | 0 | 0 | 0 |
router.push is mostly not what it looks like. Counted as text,
dolphinscheduler has 35 of them, jeecg-boot 39, mall-front 32 and
ruoyi-vue-front 26. Read, almost all of dolphinscheduler’s and all of
mall-front’s are const router = useRouter(), which RM59 already followed;
only 1 and 0 respectively go through an imported module. ruoyi-vue’s 7 do, and
jeecg-boot’s do not: its router module exports a NAMED router assigned at run
time (export let router = null; … setRouter(r)), and following a mutable
binding to a value another function assigns would be a guess. That is the
measured limit of this rule.endpointColumnPairs, tables, columns, statements and
endpoints reaching a statement are identical on all seventeen. Fourteen of the
sixteen pack digests are identical; the two that move are jsh-erp and litemall,
the two registered projects whose components hold a <router-link>, and every
recorded MCP answer for both is byte for byte what it was apart from the build
digest it quotes.RM60 named what it did not read, and both turned out to be spellings rather than missing ideas.
A submit whose method nobody could name. On the business template 47 form
submits and on the common components 281 matched their route against ANY.
Read one by one, most named their form in a way the rule did not follow:
document.all['x'], getElementById('x') || document.forms['x'], a
<form:form modelAttribute="x"> with no id (Spring renders id="x"), and a
form the page built with document.createElement('form') whose method was
assigned BEFORE its address. After those four:
| Repository | Submits with no method | HEURISTIC form-submit edges |
|---|---|---|
| egovframe-enterprise-business-template | 47 -> 12 | 45 -> 10 |
| egovframe-common-components | 281 -> 98 | 276 -> 95 |
Of the 98 left on the common components, 29 are a form handed in as a
parameter, 25 name a form the page does not declare, 24 use a variable declared
outside the function, 12 reach the frame around the page, and 8 are other
spellings. document.all['formList'] also placed one call that was not placed
before (EgovCntcInsttDetail.jsp), so the common components read 2157 calls,
2075 resolved, and 555 of 657 screens reach a table (550 before); the business
template reaches 73 of 84 (72).
export let router: Router = null as unknown as Router and fills it in
setRouter(r). The rule now reads a module-level name DECLARED with
vue-router’s Router type as a router, and follows a named import through
re-exports (src/router/index.ts re-exports it from src/router/router.ts).
jeecg-boot’s navigations go from 35 to 54, 19 through the router module. Its
call sites do not change, and neither does any other repository’s navigation
count. Removing the type annotation drops every one of them on both a cold and an
incremental run: the setter is never followed.Everything above is what the engine READ. This is what two eGovFrame
applications DID, and how much of it the pack already said. Each was built from
its pinned clone, deployed on Tomcat 10.1 with the OpenTelemetry Java agent
2.31.1 and its in-memory HSQLDB, and driven in a headless browser: the web sample
through every button of its two screens, the enterprise business template signed
in as its administrator, through 27 list screens and their search buttons, and
then through every route without a path variable (130). Nothing in either
application was changed apart from the business template’s Globals.DbType,
which its own comment says to set to hsql to run without a database.
| web sample | business template | |
|---|---|---|
| trust level | RUNTIME_PASS | GOLDEN_FAIL |
endpoint -> tables, cases a run labelled |
6 of 6 routes, 6 right | 107 of 238 routes, 106 right |
method -> statements |
6 of 6, all right | 70, all right |
| screen-to-route pairs a browser recorded | 7, each a form-submit edge the pack had |
14, each an edge the pack had |
The one route the business template got wrong is /EgovPageLink.do. Its
handler returns a view name taken from a list a Spring XML declares
(egovPageLinkWhitelist) by the index the request carries, so no literal says
which page it renders, and the menu tables that page imports are not reached. One
miss in 107 puts the Wilson lower bound at 0.9489 against a 0.95 target, and
the verdict says FAIL rather than rounding.
What the runs found wrong in the engine, each fixed in this release and each shown on the numbers above:
UPDATE SAMPLE, the HSQLDB
span reports sample, and the two were compared as different tables: every
observed statement of the web sample was marked as touching a table only the
run saw;otel-methods now says so;POST /addSample.do touched IDS
through egovIdGnrService, a bean no mapper mentions (rule
egov-id-generator);IMPLEMENTS_STMT edge the Java lane drew; the method’s own name joined none of
the business template’s 57 statement observations;loginDAO.actionLogin in
namespace="loginDAO") was prefixed twice, and 112 of the business template’s
statements bound nothing;<c:import url="/sym/mms/EgovHeader.do"/> runs the header route inside the
page’s own request: 20 of the first 26 routes exercised read the menu tables,
and the pack reached none of them (rule template-import);;jsessionid= in the path, and knew a page by only one of the routes that
render it;What the runs left is honest and named: 116 hops a servlet filter wrapped
around a controller (RUNTIME_ONLY, shown and never walked, the shape an aspect
has), the schema scripts HSQLDB runs at start-up (no method above that SQL), and
the requests for a web font on another host. Neither application’s
column -> endpoints or statement -> columns can be labelled by a run, and both
are listed as not shown rather than counted against the level.
On the corpus the three eGovFrame rows move up and nothing else does:
| Repository | Endpoints reaching a statement | Tables reached | Columns reached | Screens reaching a table |
|---|---|---|---|---|
| egovframe-web-sample | 5 / 6 | 1 / 1 -> 2 / 2 | 5 / 5 | 2 / 2 |
| egovframe-enterprise-business-template | 163 -> 188 / 219 | 30 / 35 -> 32 / 36 | 218 -> 223 / 288 | 73 -> 77 / 84 |
| egovframe-common-components | 999 / 1193 | 165 -> 166 / 179 | 1680 -> 1682 / 1862 | 555 / 657 |
endpointColumnPairs rose past the gate’s ceiling on the business template
(2099 -> 4417) and the common components (9647 -> 10131), and both were accepted:
the rise is the menu tables every page imports and the key table every insert
advances, which are the relations the runs above recorded. The sixteen pack
digests of the registered projects are identical.
Two things a Korean SI system is written in were missing from everything above: a WebSquare client, and business logic kept in stored routines that a mapper only calls. One public repository of each was cloned, pinned and measured with the engine as it stood, before a rule was written, and again after.
| Repository | Pinned at | Endpoints reaching a statement | Tables reached | Columns reached | Frontend calls resolved | Screens reaching a table | Endpoint to column pairs |
|---|---|---|---|---|---|---|---|
| inswave/WRM-Public | 19e0c19c |
82 / 96 | 27 / 27 | 205 / 222 | 0 / 0 -> 111 / 119 | 0 / 2 -> 40 / 159 | 277 |
| sindohmes/mes4u | ed57f3db |
110 / 115 | 29 / 30 -> 41 / 43 | 307 / 387 -> 483 / 673 | 113 / 148 | 0 / 47 | 618 -> 1409 |
WRM-Public is WebSquare’s own sample application over an eGovFrame backend.
Before, the lane read none of its .xml pages. The product had two screens, the
two views a controller returns to host the WebSquare engine, and not one frontend
call. After, every page is a screen at the address the application opens it by.
Of the 119 calls that carry an address, 111 reach a route this pack serves, and
the eight that do not are what they look like:
*.pwkjson addresses of another product, which no controller
here serves;/sample/404
on purpose.Three more calls name a submission the page never declares, or hand over an
options object this lane cannot read, and they are counted, not dropped. 110 of
the 159 pages send nothing, and 79 of those screens are page templates under
cm/template. The repository ships no DDL, so a column is attributed only where
a statement names it.
mes4u is a manufacturing execution system on Spring Boot, MyBatis and
PostgreSQL. Its schema is one pg_dump of 33 tables and 45 PL/pgSQL functions,
and 29 of its 135 statements call one of them. Before, the catalog
was parsed as MySQL, because nothing told init otherwise, and not one of the 33
tables was read. After, the dialect is PostgreSQL, read off the schema’s own text,
and a call reaches the tables of the function and of what the function calls:
statements that reach a table go from 105 to 131 of 135, and 854 edges run
through a routine, each SOUND_SET. The endpoint-to-column pairs more than double.
That rise is the point: every column a function touches is now reached by every
endpoint above the statement that calls it.
What the gate itself caught while these two were added, both fixed before the rows were recorded:
basis, and a pack of this client
failed its own digest check when it was read back from disk;What is left, and named:
VUE_APP_BASE_API, which its three .env files set three
different ways, so the prefix is chosen by how many calls it matches, and all 117 call edges
that reach a route are HEURISTIC. The web axis says so, and names
gatewayRoutes as the key to declare;src/main/resources/static/js/, and 27
of its screens are declared twice, once in the source and once in the bundle;ref and target data lists are not read.The seventeen rows already in the corpus did not move by one number, and the sixteen pack digests of the registered projects are identical.
Until RM67 a walk that reached a statement counted every table and column the
statement touched, whatever the grade of the edge to it, while flow drew only
the ones the mode admits. Now every census counts a statement’s tables and
columns the way flow draws them: through the EXECUTES, READS and WRITES
edges the mode’s floor admits. A name a rule only assumed (an entity with no
@Table, a MyBatis-Plus field with no @TableField, under no declared naming
strategy) is graded HEURISTIC, so the default conservative census no longer
counts it. The pinned corpus moved in these counts and no others:
| Repository | Tables reached | Columns reached |
|---|---|---|
| dolphinscheduler | 42 (unchanged) | 457 -> 444 |
| egovframe-msa-edu | 20 -> 0 | 191 -> 0 |
| eladmin | 26 (unchanged) | 230 -> 123 |
| jeecg-boot | 73 -> 67 | 836 -> 467 |
| jeepay | 22 (unchanged) | 302 -> 48 |
| mes4u | 41 (unchanged) | 483 -> 415 |
| ngrinder | 7 (unchanged) | 92 -> 78 |
| spring-petclinic-microservices | 7 (unchanged) | 24 -> 20 |
| ruoyi-vue-pro | 548 (unchanged) | 8010 -> 15 |
Nothing was lost. A mode=heuristic census counts them all again (jeecg-boot:
73 tables, 836 columns), and declaring the naming strategy the project runs with
makes those names EXACT: jpa.namingStrategy for JPA entities,
mybatisPlus.namingStrategy for MyBatis-Plus. The analysis names the one it
assumed (PROFILE_DEFAULT_ASSUMED). egovframe-msa-edu is the plain case: every
one of its 20 reached tables is an @Entity with no @Table, and the project
configures no strategy anywhere.
Three more counts moved in this round. The baseline keeps the first two where they were, so a run with the corpus reports them until the declaration is made; it takes the third, which no declaration restores:
jpa.namingStrategy
restores them./admin-api prefix,
which the backend’s routes lack until pathPrefixes is declared. The analysis
names the code that sets it (SETTING_IN_CODE,
YudaoWebAutoConfiguration.java:53). Before, the calls matched routes through
a prefix chosen by counting matches, a guess.let that a hook and a form-data step assign again
(VAxios.request), so whether the URL survives that step is not settled by
the code, and those calls are HEURISTIC, each edge naming the step
(evidence.sink.unsettled). mode=heuristic still reaches 27.Until this round the census walked 8 hops from a handler and stopped, and a walk that had more to go counted it as cut. Now every walk goes as far as the graph goes, and a node cap of 4000 is the guard (concepts.md). On the pinned corpus no census walk reached the node cap, the slowest census took the same time uncapped (130 ms on ruoyi-vue-pro), and these counts rose:
| Repository | What rose |
|---|---|
| dolphinscheduler | endpoints reaching a statement 204 -> 215, statements 259 -> 265, tables 42 -> 43, columns 444 -> 451 |
| ruoyi-vue-pro | endpoints reaching a statement 2638 -> 2671, statements 2525 -> 2548 |
| egovframe-msa-edu | endpoints reaching a statement 90 -> 91 |
| egov-business-template | screens reaching a table 77 -> 78 |
| ruoyi-vue | screens reaching a table 8 -> 9 |
| jeecg-boot | statements reached 748 -> 749 |
The same round reads every method and path a Spring mapping annotation names
(java-lane.md), which moved
jeecg-boot’s own test pins: routes with one handler 969 -> 1016, endpoints
970 -> 1017, endpoints reaching a statement 744 -> 790. When the gate baseline
was recorded again after the round, three numbers moved for a reason other than
a gain. Endpoint-to-column pairs rose past the 5% budget on jeepay (3554 ->
3824), jeecg-boot (15997 -> 17231) and ngrinder (900 -> 1082), because the
routes a multi-value mapping names are routes of their own (endpoints 134 ->
138, 970 -> 1017, 124 -> 136) and each reaches what its sibling reaches; per
route the pairs move 26.5 -> 27.7, 16.5 -> 16.9 and 7.3 -> 8.0. mes4u’s screens
fell 50 -> 31: the 19 that went were children composed under a wildcard
(/*/dashboard, /*/defect) because their parent was found by line only;
found by line and column they compose to /mdm/defect and the rest, which were
already there. Its screens reaching a table stay 0.
Trace walked up, endpoint_impact and screen_impact now read one walk up, and
src/core/walk_agreement.mjs compares their rows, column by column and table by
table, with each other and with the census. Before the walks were merged,
spring-petclinic had 17 of its 24 columns, and jpetstore-6 49 of its 86, whose
screens one answer named and another did not (forest-blog 77, jeecg-boot 42,
xxl-job 31, jeepay 4). After it, no column of the 26 Java corpus packs or the 4
TypeScript ones does. The suite runs the check on hand-built graphs, on the
three golden fixture trees in every mode, and on spring-petclinic, jpetstore-6
and the mall pack when they are checked out.
The gate baseline was recorded again after the round. Each number that moved past its budget was bisected to one commit and read against the source:
CREATE TABLEs it could not read before (51 stub tables become
1). The common code table COMTCCMMNDETAILCODE is one of them, and 424 routes
join it. Pairs on columns the old pack also had rose by 5384, all from tables
that were stubs; no column was lost. Real reach, not inflation.conservative 78 -> 52: 27 PerfTest columns
carry the project’s own @Cloneable marker, which the JPA lane does not know,
so their columns became guesses. Pairs are unchanged.conservative 44 -> 0: every call rests on
the default port 8080. Declaring servers restores 44 of 54.gatewayRoutes {"*": ""} it is 23 of 181.Three real projects, each pinned to a commit and checked end to end.
node --test test/mall_demo.test.mjs # the MyBatis + Spring MVC golden
node --test test/jpetstore.test.mjs # the HSQLDB + MyBatis golden
node --test test/petclinic.test.mjs # the JPA golden
Each skips out loud without its fixture, naming both the fixture and the command that produces it. CI clones all three at pinned commits and fails if any of those tests skips, because a permanent self-omission on a fresh clone is a defect rather than a pass.
Built from a fresh clone at a new absolute path, through the documented no-flag
path, with a profile cascade init wrote on the spot:
| What | The number |
|---|---|
| pack | 12674 nodes, 19269 edges, lanes [sql,java], digest 99141d55e969 |
| census | 239 endpoints, 906 mapper statements, 76 tables, 669 columns, 10784 symbols |
| reach | 205 of 239 endpoints reach a statement, 208 statements, 49 tables, 461 columns |
pms_product.price |
18 statements, 8 writing and 10 reading, all EXACT |
| the same column, upward | 27 endpoints, 12 of them under /product/*, all SOUND_SET |
| ERD | 27 relationships over 76 tables, joining 32 of them |
| transactions | 35 @Transactional boundaries, the largest reaching 15 tables |
| coupling | 32 API groups, 22 of them participating, 61 coupled pairs, 267 coupled columns |
With its Vue admin frontend added by one --web-src flag, the same tree becomes
13032 nodes and 19797 edges, digest 7994e1a5fd22, and adds 54 screens, 145
resolved frontend calls out of 153, and 44 screens that reach a table.
| What | The number |
|---|---|
| census | 22 endpoints, 25 mapper statements, 13 tables, 86 columns |
| reach | 11 of 22 endpoints reach a statement, 12 tables, 77 columns |
| pages | 20 JSP templates, 16 of them a controller names, 52 of 53 call sites resolved |
Its schema is HSQLDB, which routes to sqlglot’s ANSI parser rather than to a
dialect parser of its own, so this golden is what exercises that path. It is
also the plainest server-rendered application in the corpus: not one line of
JavaScript, and every screen it has is a JSP file a @Controller named.
| What | The number |
|---|---|
| census | 17 endpoints, 6 statements, 7 tables, 24 columns |
| reach | 15 of 17 endpoints reach a statement, 7 tables, 24 columns |
| pages | 12 Thymeleaf templates, 8 of them a controller names |
It has no mapper XML at all: every statement in it is one the JPA bridge derived
from an entity mapping, a derived query name or a @Query.
It is also the project a real OpenTelemetry agent capture is kept for
(test/fixtures/otel/petclinic-agent.log, ten routes), and that recording is
what moved these numbers. Of the ten routes it observed, six read tables the pack
did not name, for two reasons: the JPA lane stopped at the entity the repository
method names instead of following the eager associations that come back with it,
and nothing in the graph led to a @ModelAttribute method, which is where two of
those routes load their owner. Both are read now, and all ten routes score. The
two routes the pack still answers nothing for are the welcome page and the crash
page, which run no SQL.
The claim that a reused analysis equals a fresh one is a test rather than a
promise. test/incremental.test.mjs builds a synthetic Spring, MyBatis and
MySQL project inside a git repository, mutates a random subset of its files each
round with a seeded PRNG, and requires the incremental pack to equal a cold pack
byte for byte.
node --test test/incremental.test.mjs
node --test test/overlay_integration.test.mjs
The second one holds the other half: the working-tree overlay may over-approximate, and it may not omit. It compares the overlay against a full re-analysis of the same bytes and fails on anything the overlay missed.
| Claim | How it is held |
|---|---|
| the same commit, catalog, engine and profile produce the same pack digest on any machine | test/mall_demo.test.mjs rebuilds mall from a fresh clone at a different absolute path and compares the digest |
| an edited pack, receipt, fact set or gate state is refused rather than used | test/calibration_tamper.test.mjs, twelve cases including a dropped fact set, an expired receipt and a flipped golden |
no credential is ever written to .cascade/, the pack, the receipt, the registry or a log |
test/catalog_fetch.test.mjs runs a fetch end to end and greps every written file and both captured streams |
catalog fetch refuses to connect without --yes |
the same test |
| the JavaScript and Python identifier folds agree | test/identifier_case.test.mjs, 20 names by 3 rules by 11 dialects, running both implementations |
These are not “probably fine”.
mysql:8, but it has never run on the machine this was built on, so CI’s
db job is the first real execution of any of it.node:vm against a DOM stub; the canvas mount,
the WebGL context and the 3D renderer are unverified, and 3D has only ever
been seen under software rendering.cascade init reports what it has no lane for; it does not analyse
it.mysql. jpetstore has been analysed both ways, as mysql and as
hsqldb, and the two produce the same pack digest, so the ANSI path is
exercised. The profile also accepts postgres, oracle and h2; no golden
runs those, and their identifier rules are unit-tested rather than measured on
a real schema.npm test prints the table and a
reviewer reads it.The changelog carries the same two lists round by round, with the command behind every number: CHANGELOG.md.