Skip to content

Catch the frozen builder written on its receiver, count the corpora, give onboarding its missing pages - #153

Merged
oblomov-dev merged 6 commits into
mainfrom
claude/abap2ui5-repo-analysis-c2qhj9
Aug 18, 2026
Merged

Catch the frozen builder written on its receiver, count the corpora, give onboarding its missing pages#153
oblomov-dev merged 6 commits into
mainfrom
claude/abap2ui5-repo-analysis-c2qhj9

Conversation

@oblomov-dev

Copy link
Copy Markdown
Member

Part of an ecosystem-wide pass over the two goals: make it maximally easy for AI agents, and for people, to build abap2UI5 apps.

Seven frozen-builder calls were published, and the gate could not see them

The fragment gate anchored on the closing paren of a previous chain step, so it saw )->input( ) and was blind to the identical page->input( ) — which is exactly the shape a fragment showing ONE control is naturally written in. Seven calls on four pages outlived the migration that cleared every mid-chain call in the tree:

page calls
cookbook/cheat_sheet.md view->button( ), view->_generic( )
configuration/setup/style_css.md view->button( )
cookbook/model/device_model.md page->input( )
cookbook/expert_more/smart_controls.md three page->smart_*( )

All seven are members of z2ui5_cl_xml_view (src/99, frozen) and of no other class. Teaching them is the regression this ecosystem guards hardest against, because a model trained on old material writes them by default — and they were republished verbatim into the generated llms-full.txt, the file that exists to fight exactly that.

The gate now reads receiver-style calls too. Receiver names cannot be recognised in general, so the set of view-node variables is derived per fence — anything assigned out of the builder, anything calling one of the five verbs — seeded with view and page. Verified: it reports all seven and exits 1, and passes clean on the corrected tree.

CI did not run what npm run check runs

check is five steps; check.yml had no npm test, so test/catalogue.test.mjs — the pin added because the catalogue parser broke twice in silence — was the one check no pull request had to pass.

Numbers, counted instead of typed

generate-llms.mjs hardcoded "152 complete apps" and "~400 ports" next to a page of this same site giving three different figures. They are counted now, through the same parser the sample links go through, and the phrase simply carries no number when a catalogue is not at hand. resources/samples.md said 431 for samples-controls and 615 in total against a published 430 and 614; npm run check:counts holds all four figures to the catalogues from now on.

The onboarding path had a hole where the tooling should be

A reader following the sidebar built their first apps with no gate, no repo and no editor support, then was told all of it existed. Three pages:

  • Your Project — between Hello World and Full Example, because that is where the question turns from "how do I write this" to "where does it live". quickstart.md ended with a class typed into a system; app-template starts at "Use this template", and nothing joined them.
  • The linter — under Technical Insight → Tool, next to abapGit and abaplint, which had pages while this project's own linter did not.
  • Building with AI — the priming problem, the two llms.txt, ai-mcp, the extension's MCP servers.

The agent tip in tooling.md pointed at the framework's llms.txt; the site publishes its own and never linked it, while the framework's own file says the site's "is the better map of the prose".

How to test

npm run check   # six steps: test, check:version, docs:build, check:examples, check:samples, check:counts

check:version cannot reach api.github.com from a sandbox and says so rather than passing silently — the three in-repo places are still checked against each other.


Generated by Claude Code

claude added 6 commits August 17, 2026 21:23
… pages

The fragment gate anchored on the closing paren of a previous chain step, so
it saw `)->input( )` and was blind to the identical `page->input( )`. That is
the shape a fragment showing ONE control is naturally written in - which is
why the migration that cleared every mid-chain call in the tree left seven
frozen calls standing on four pages, published to every reader and to the
generated llms.txt:

  cheat_sheet.md         view->button( ), view->_generic( )
  style_css.md           view->button( )
  device_model.md        page->input( )
  smart_controls.md      page->smart_variant_management( ), _filter_bar( ),
                         _table( )

All seven are members of z2ui5_cl_xml_view (src/99) and of no other class;
none exists on z2ui5_cl_ui5_view_builder (src/02), whose whole API is ele,
tag, a, end, stringify. Teaching them is the one regression this ecosystem
guards hardest against, because a model trained on old material writes them
by default - the linter carries a frozen-view-builder rule for exactly this.

Rewritten with the current builder. The cheat sheet's warning was about a
`_generic( t_prop = )` quirk that no longer exists, so it now covers the trap
that replaced it: an ABAP flag reaches the view as `X` through `v` and as
`true`/`false` only through `b`. smart_controls.md gained the `xmlns`
declarations its controls need, taken from samples-stack app 478.

The gate now also reads receiver-style calls. Receiver names cannot be
recognised in general, so the set of view-node variables is derived per fence
- anything assigned out of the builder, anything calling one of the five verbs
- and seeded with `view` and `page`, which a one-control fragment uses with no
chain around it to derive from. Verified: it reports all seven original calls
and exits 1, and passes clean on the corrected tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XY3AoWMiCC52cuQjbce4SU
package.json defines `check` as five steps; check.yml ran four. The missing one
was `npm test` - the pin on the sample-catalogue parser, added because that
parser stopped matching TWICE and both times answered wrongly ("`...app_493` is
not in the sample catalogue") instead of failing. So the one check that exists
because something broke in silence was the only one no pull request had to
pass, which is the same failure mode a second time.

check:version gains the `!cancelled()` guard the later steps already have, so a
failing unit test still lets the rest of the run report rather than hiding four
answers behind the first one.

README.md and AGENTS.md both described `check` as three things. Corrected to
the five, with the note that the workflow and the script have to stay in step,
and AGENTS.md now records what check:examples refuses after the previous commit
- a chain step on its receiver as well as mid-chain - and where the catalogue
parser and its pin live.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XY3AoWMiCC52cuQjbce4SU
The tip in Getting Started -> Tooling pointed at the framework repository's
llms.txt and called it "a map of this documentation". That file says otherwise
in its own opening lines: it points readers who arrive from a search back here,
calls this site's llms.txt "the better map of the prose", and describes itself
as "the map of the CODE".

This site generates and publishes its own llms.txt and llms-full.txt on every
build - the README documents them - and no page linked either one. So the one
tip aimed at agents sent them away from the index built for exactly that
purpose. Both are now named, with one sentence on which answers which question.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XY3AoWMiCC52cuQjbce4SU
generate-llms.mjs opens with the reason it generates rather than commits:
"nothing here is a claim about another repository that could go stale between
builds". Twelve lines of it were exactly that - "152 complete apps" and "~400
ports", hand-typed, next to docs/resources/samples.md giving different figures
for the same corpora. llms.txt is the one file in this repository written to be
quoted verbatim by something that cannot check it, so a stale number there is
the most expensive kind to keep.

They are counted now, through the same parser the sample links go through -
which counts APPS: samples-stack lists eight supporting classes in tables of
their own, and those are not samples and do not parse into a pointer.

When a catalogue is not at hand the phrase carries no number at all. That path
is real, not theoretical: deploy.yml checked out no sample repository, so the
published file would have been the numberless one every time. It now takes
SAMPLES.md alone out of samples and samples-controls, sparse and shallow, with
continue-on-error - an unreachable repository costs the deploy a figure, never
the site. The generator prints which counts it took, because "no checkout" and
"counted" produce different files and both are valid.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XY3AoWMiCC52cuQjbce4SU
Getting Started ran Introduction -> Use Cases -> Quickstart -> Hello World ->
Full Example -> Tooling -> What's Next, and Tooling was the first mention of
the template, the linter, the extension and the MCP server. A reader who
stopped once their first app ran - which is the point Quickstart ends at - met
none of them. There was also no documented step between "I typed a class into
my system", where Quickstart stops, and "I have an abapGit repository with
gates", which is where app-template starts.

Three pages:

Your Project (/get_started/project_setup) closes that gap: what the template
contains, the four commands to a first green check with no SAP system in the
loop, `npm run rename` and the two decisions it deliberately leaves open. It
sits between Hello World and Full Example, because that is where the reader's
question changes from "how do I write this" to "where does it live" - after
Full Example would repeat the same mistake one chapter later.

abap2UI5-linter (/technical/tools/linter) is the reference the Tooling summary
had no room for: the two gates, why a view nothing can see before runtime needs
its own linter at all, --fix, and the baseline that makes adoption on a grown
codebase possible. It goes under Technical Insight -> Tool with abapGit,
abaplint and the rest - the only tool there this project wrote itself.

Building with AI (/get_started/ai) states the priming problem plainly - a model
asked for an abap2UI5 app writes the frozen builder, because that is what the
public corpus shows - and then the corrections in rising order of effort: the
two llms.txt and which maps what, AGENTS.md in the repository, the gates an
agent can run itself, ai-mcp, and the extension's two MCP servers.

Written for the person setting the assistant up, not for the assistant: the
agent-facing copy stays in llms.txt, per this repository's AGENTS.md. Every
object, command, flag, rule id and setting named was read out of app-template,
linter, ai-mcp and vscode-extension. Quickstart, Tooling and What's Next now
point at the three.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XY3AoWMiCC52cuQjbce4SU
resources/samples.md is the page that answers "which of the three sample
repositories do I search?", and it opens with a total - "615 working apps, in
three repositories" - over a table giving one count per repository. Every one
of those is typed by hand and describes a repository whose CI cannot see this
page. Two had drifted: samples-controls stood at 431 against a published 430,
and the total at 615 against 614.

Verified against raw.githubusercontent.com/<repo>/main, not against the local
checkouts, because that is what the page's own links point at.

generate-llms.mjs answers this by counting and leaving the number out when the
catalogue is absent. A prose page cannot do that - the sentence is written, not
generated - so the figure stays and check:counts holds it, through the same
countCatalogue( ) the generated file uses. Nothing here gets a second opinion
about what a sample is.

Skipping is per repository: with only `samples` at hand it checks that one,
names the two it could not read, and leaves the total alone, since a total
needs all three. CI now sparse-checks out SAMPLES.md from samples-controls and
samples-stack for the full check - both continue-on-error, so an unreachable
repository costs a figure and never the run.

  check:counts   4 claims, 4 checked - OK
  npm run check  six steps, all green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XY3AoWMiCC52cuQjbce4SU
Copilot AI lite review requested due to automatic review settings August 18, 2026 05:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@oblomov-dev
oblomov-dev merged commit f69446a into main Aug 18, 2026
1 check passed
@oblomov-dev
oblomov-dev deleted the claude/abap2ui5-repo-analysis-c2qhj9 branch August 18, 2026 05:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants