Skip to content

docs(readme): the examples demonstrate manifest shape, not recommended values - #201

Merged
ZacxDev merged 2 commits into
mainfrom
zach/examples-framing-not-values
Aug 5, 2026
Merged

docs(readme): the examples demonstrate manifest shape, not recommended values#201
ZacxDev merged 2 commits into
mainfrom
zach/examples-framing-not-values

Conversation

@ZacxDev

@ZacxDev ZacxDev commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

The tension

The ### Examples section of README.md introduced the two example manifests as
"a good reference for a correct manifest".

One of them, examples/buzz-generator.block.manifest.json, sets
page.buzzBudgetPerGen: 10. Guidance that just shipped reframed that field: it is a
per-generation safety ceiling against a malicious or compromised app draining the
viewer's Buzz — sized well above worst-case spend, not at an estimate of one run.
The canonical schema description (civitai#3629, now live at
https://civitai.com/schemas/app-block/v1.json) says so explicitly, and #199 moved the
page-money scaffold default 40 → 300.

So 10 sits under a heading that endorses it, with no context. A reader following the
README to "a good reference for a correct manifest" cannot tell whether it is a
well-sized ceiling or an estimate.

What makes it look bad: 10 is also the platform fallback used when the field is
omitted — the one the canonical description calls "below almost any real
generation". A value indistinguishable from the unset default reads as unconsidered.
(Measurement later showed it is adequate for this particular cheap app — see below —
but a reader has no way to know that from the file.)

Why the value was deliberately NOT changed

Two independent reasons, either sufficient on its own:

  1. It would falsify the provenance claim. The README says these are copied from the
    civitai-block-* apps. That is the entire reason they earn their place — they are
    real. Editing the number turns them into synthetic examples still wearing a
    "copied from" label, which is a worse defect than the one being fixed.
  2. 10 turns out to be RIGHT. This was priced during review rather than guessed —
    see below. A buzz-generator generation costs 3 Buzz, so 10 is a ~3.3×
    ceiling: correct in kind, if thin against the canonical "several times your expected
    cost". Changing it was never warranted.

The fix is therefore to the framing, not the data. No manifest byte changed.

What buzz-generator actually costs — 3 Buzz (measured)

Rather than assume, this got priced from two independent authorities that agree:

  • Production data. block_spend_attribution joined to app_blocks has exactly one
    row for buzz-generator: buzz_amount = 3, model_id 101055 (SDXL 1.0),
    2026-06-24. Neighbouring SDXL-1.0 rows from other apps price at 2–3, corroborating.
  • The orchestrator price table. The app hardcodes SDXL 1.0 and sends prompt only;
    the server fills 1024², Euler, 25 steps, quantity 1. The generic SD factor product
    4 × (25/30) × 0.8 = 2.67 → ceil = 3. No base constant on this path.

So the field is a ~3.3× ceiling over real cost — a correct ceiling, not the
estimate-shaped mistake it superficially resembles. This is precisely why the value was
not edited on a hunch: the number that looked wrong was fine.

It is still not a value to copy, which is what the new prose says — the right ceiling
is a function of your generation's cost, not this app's.

What the framing now says

  • Kept the provenance, minus one inaccurate word — see the correction below.
  • Replaced "a good reference for a correct manifest" with a pointer at manifest
    shape: required fields, $schema wiring, the page/iframe blocks, and scope
    declarations with justifications.
  • Added a buzzBudgetPerGen pointer that sends the reader to the canonical
    schema's own field description
    rather than to this example's number, and states
    plainly that the values here are those apps' own choices, not recommendations.
  • Noted that notepad has no budget at all — verified: it declares only
    apps:storage:read/write, takes no ai:write:budgeted scope, and has no
    buzzBudgetPerGen key. The caveat applies to exactly one of the two files, so the
    prose says which.

The pointer targets the published URL (already the $schema value in both examples)
rather than the CLI's vendored copy, deliberately — see the CI note below.

Second commit: "shipping" was inaccurate

Pricing the app turned up a separate defect in the sentence this PR originally set out
to preserve. app_blocks in production says:

block_id version status
buzz-generator 0.1.1 suspended
notepad 0.1.1 suspended

approved is a real, populated state (9 of 21 app_blocks hold it), so suspended is
not a lifecycle default — neither example is a shipping app. buzz-generator has
one lifetime generation, run by its own author (voided / self_spend).

So "copied from the shipping civitai-block-* apps" asserted more than is true.
Second commit drops the word: "copied from the civitai-block-* dogfood apps". The
provenance point — these are real apps' manifests, not synthesised ones — is intact,
and is still the reason they earn their place.

What examples_test.go does and does not guarantee

The README said the examples "validate clean (examples_test.go asserts this so the
claim stays true)". True, but the test only reaches schema conformance10
satisfies exclusiveMinimum: 0 perfectly happily. The test was guarding the syntax of
the provenance claim while sitting directly under, and appearing to underwrite, a
quality claim it never touches.

Fixed in the prose: the sentence now says the assertion is "schema conformance only,
which says nothing about whether a value is well-sized." The test's own doc comment
gained a matching SCOPE — paragraph.

No heuristic budget test was added, on purpose. Any threshold that would flag 10
has to guess at correct sizing per app, and would fire on legitimately cheap ones. The
right fix is that the prose stops claiming more than the test checks.

Confirmed there is no existing sizing check to lean on either: internal/validate/warnings.go
warns only when buzzBudgetPerGen is absent (or set without the budgeted scope) — a
low-but-present value produces no warning. So a reader copying this example gets no
signal from tooling at all, which is exactly why the prose has to carry it.

Gates

  • go build ./... — clean.
  • go test ./... -v -count=11332 === RUN, 1330 --- PASS, 2 --- SKIP, 0
    --- FAIL
    across 16 ok packages; no panic: test timed out. Counted, not read
    from an exit code.
  • Negative control on the harness: setting buzzBudgetPerGen: -5 in an example makes
    TestExampleManifestsValidateClean fail with this test's own error
    (example notepad… should validate clean, got errors: [/page/buzzBudgetPerGen: exclusiveMinimum: got -5, want 0]), so its green is meaningful. Reverted.
  • gofmt -l . clean, go vet ./... clean.

Diff is docs-only plus one comment: README.md (+11/−2) and examples_test.go
(+7, doc comment only — no assertion, control flow, or test data changed). No .json
under examples/ was modified.

Pre-existing CI red, unrelated to this PR

check canonical schema (scripts/check-canonical-schema.sh) currently fails on
main
: the vendored schema/app-block.manifest.schema.json (11,941 B) has drifted
from the live canonical (13,196 B) because civitai#3629's rewritten
buzzBudgetPerGen description shipped and the CLI has not re-vendored yet. The vendored
copy still carries the old one-line "Optional per-generation Buzz budget…" text.

This branch touches only README.md and examples_test.go, so it neither causes nor
fixes that. It is presumably what .github/workflows/revendor-canonical-schema.yml is
for. Flagging it so a red check here isn't misattributed — and it is a second reason the
new prose points at the published schema URL rather than the CLI's embedded copy,
which would currently hand the reader the stale wording.

Attribution is measured, not inferred. schema-drift passed on main at
2026-08-04T23:22:23Z (run 30959751797, commit 8aab331). Re-running that exact job
on that exact unmodified commit
at 2026-08-05T00:55Z now fails. Nothing in the
repo changed between the two runs — the canonical schema served at civitai.com did,
when civitai#3629 reached production. So the check is red on main right now,
independent of this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01R7ZCxbgcsv3WfsSJrYdSCi

ZacxDev and others added 2 commits August 4, 2026 22:51
…d values

The Examples section called the two shipped manifests "a good reference for a
correct manifest". That reads as an endorsement of their VALUES, and one value
is now in tension with guidance that just shipped: buzz-generator sets
page.buzzBudgetPerGen: 10, which is also the platform fallback the canonical
schema describes as "below almost any real generation".

Reframe rather than edit the data. The examples are valuable precisely because
they are copied verbatim from the shipping apps; changing the number would turn
them into synthetic examples wearing a "copied from" label. And nobody has
priced buzz-generator, so 10 is not established as wrong.

So: keep the provenance, point at manifest SHAPE, and send the reader to the
canonical schema's own field description for budget sizing. Note that notepad
has no budget at all (it doesn't take the budgeted scope).

Also make examples_test.go's comment honest about its reach: it asserts schema
conformance, which 10 satisfies regardless of how it was sized. Deliberately
NOT adding a heuristic budget threshold — any such check would have to guess at
correct sizing per app and would fire on legitimately cheap apps.

Docs-only plus one comment; no manifest values changed.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01R7ZCxbgcsv3WfsSJrYdSCi
…pps are suspended

Verified against the prod app_blocks table: buzz-generator AND notepad are both
status=suspended, not approved. `approved` is a real state (9 apps hold it), so
suspended is not a lifecycle default — neither example is a shipping app. They
are dogfood apps, which is still exactly why their manifests are worth shipping
as examples, but "shipping" is a claim the data does not support.

Drop the word. Provenance (these are copied from real apps, not synthesised) is
preserved and is what earns them their place.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01R7ZCxbgcsv3WfsSJrYdSCi
@ZacxDev
ZacxDev force-pushed the zach/examples-framing-not-values branch from f1138c9 to 56025cf Compare August 5, 2026 03:51
@ZacxDev
ZacxDev merged commit 497ded2 into main Aug 5, 2026
10 checks passed
@ZacxDev
ZacxDev deleted the zach/examples-framing-not-values branch August 5, 2026 03: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.

1 participant