DocsStart here

Reading your survey

The survey is the whole picture: what Tibyaan can prove about your app, what it refused, and exactly why. It is written for you, to decide whether to adopt. Here is how to read it.

A real survey

This is the output of a real scan, unedited. Lines that start with + are proven reads. Lines that start with - are refusals, each with its cause in brackets and a located reason.

tibyan scan examples/erp-backend
Discovered (25):
  by-id (16):
    + Contact: getContact -> ContactServiceImpl#findById; returns the entity Contact directly (section 4.1) (partial: 3 fields skipped)
    + ContactCategory: getContactCategory -> ContactCategoryServiceImpl#findById; returns the entity ContactCategory directly (section 4.1) (partial: 1 fields skipped)
    + ContactGroup: getContactGroup -> ContactGroupServiceImpl#findById; returns the entity ContactGroup directly (section 4.1) (partial: 1 fields skipped)
    ... (+13 more discovered by id; every one shown in full in the linked ledger)
  list (9):
    + listAccount -> AccountServiceImpl#findAll
    + listContact -> ContactServiceImpl#findAll (paged)
    ... (+7 more discovered list reads)
Failed (9):
  - EmailTemplate [NO_IDENTIFIER]: entity 'EmailTemplate' has @Id 'type' of type 'EmailTemplateType', which does not map to a bindable primitive, so no read-by-id capability is modeled (Volume 5 section 4.1). (partial: 1 fields skipped)
  - OutboundEmail [NO_BACKING_METHOD]: no service method backs read capability 'getOutboundEmail' for entity 'OutboundEmail'.
  - OutboundNotification [NO_BACKING_METHOD]: no service method backs read capability 'getOutboundNotification' for entity 'OutboundNotification'.
  - Quote [AMBIGUOUS_BINDING]: read capability 'getQuote' for entity 'Quote' is backed by more than one candidate: [QuoteServiceImpl#findById (entity-returning), QuoteServiceImpl#getInvoice (view-returning byte[])]. (partial: 2 fields skipped)
  - SMSMessage [NO_BACKING_METHOD]: no service method backs read capability 'getSMSMessage' for entity 'SMSMessage'. (partial: 1 fields skipped)
  - Delivery [NO_BACKING_METHOD]: no service method backs read capability 'getDelivery' for entity 'Delivery'. (partial: 1 fields skipped)
  - DeletedUser [NO_BACKING_METHOD]: no service method backs read capability 'getDeletedUser' for entity 'DeletedUser'.
  - User [AMBIGUOUS_BINDING]: read capability 'getUser' for entity 'User' is backed by more than one candidate: [UserService#findById (entity-returning), UserService#findByUsername (entity-returning)].
  - InventoryTransaction [NO_BACKING_METHOD]: no service method backs read capability 'getInventoryTransaction' for entity 'InventoryTransaction'.
List-refused (1):
  - ProductCategory [LIST_AMBIGUOUS]: list capability 'listProductCategory' has more than one list-all candidate: [ProductCategoryServiceImpl#findAll, ProductCategoryServiceImpl#findAll].
Totals: discovered 25 (by-id 16, list 9), failed 9 (by cause: NO_IDENTIFIER 1, NO_BACKING_METHOD 6, AMBIGUOUS_BINDING 2), list-refused 1, skipped-by-parse 0, partial 13 (22 fields skipped), mis-bound 0

Unedited output of the ERP benchmark survey (2026-07-17). Elisions are marked in the text and only shorten the discovered lists; every refusal is shown in full. The per-entity ledger is public (opens in a new tab).

Discovered

A discovered line names the capability, the entity, and the binding: the real class and method the tool will call. Two kinds of read are discovered today.

  • by-id: a read of one entity by its primary key, for example getContact bound to ContactServiceImpl#findById.
  • list: the unfiltered list of an entity, for example listAccount bound to AccountServiceImpl#findAll. A (paged) mark means the read returns a page, and the generated description says the page envelope is not modeled.

A (partial: N fields skipped) mark means some fields of the source entity are not represented in the model. The binding is still proven. The omission is disclosed rather than hidden: the generated OpenAPI schema names the fields that were left out.

Refusal causes

Every refusal carries one cause. None of them is an error in your code: each is the tool declining to guess.

CauseWhat it means
NO_BACKING_METHODNo service method structurally backs this read, so nothing is exposed.
AMBIGUOUS_BINDINGTwo or more methods both fit the shape of the read; the tool refuses rather than pick one.
NO_IDENTIFIERThe entity has no identifier that maps to a bindable primitive, so a read-by-id cannot be formed.
COMPOSITE_KEYThe entity's identifier is a composite key, so no single-identifier read-by-id is formed.
LIST_AMBIGUOUSMore than one list-all candidate exists; the tool will not choose between them.

Files that would not parse are listed separately as skipped-by-parse, each one named. The scan never aborts on a bad file, and a partial result never passes itself off as a complete one.

What is never discovered, by design

Writes and actions, and filtered reads such as findByStatus or search. A filter's meaning is a claim the tool cannot verify from structure, so it is not presented as verified. A person can carry such a read through attestation.

The totals line

The last line summarises the run:

totals
discovered N (by-id A, list B), failed, list-refused, skipped-by-parse, partial, mis-bound
FieldRead it as
discoveredProven reads, split into by-id and list. These are what would ship.
failedEntities whose read-by-id was refused, broken down by cause.
list-refusedEntities whose list read was refused.
skipped-by-parseSource files that could not be parsed. Each is named above.
partialEntities modeled with some fields left out, with the count of fields skipped.
mis-boundTools bound to the wrong method. This is the absolute bar: it must be 0, on every run.

When your project has an attestations file, the survey also reports attested entries and drafts as their own classes. They are counted apart and never summed into the discovered total.

A shareable report

Add --report to write the same survey as Markdown: a summary table, the operable subset with its bindings, the refusals grouped with their located reasons, and the single most common blocker. It is read-only, like the scan itself.

shell
java -jar tibyan-cli-0.3.0-jar-with-dependencies.jar scan /path/to/your-app --report survey.md

If you ran the preview on a real application, the maintainer would like to see the numbers: every real survey shapes what gets built next. The address is on the security page.

scan versus generate

They do two different jobs, which is why one shows more than the other.

  • scan is the survey. It prints everything: every discovered capability, every refusal with its cause, every skipped file.
  • generate and the Maven plugin produce the artifact. They emit only the proven capabilities, because the manifest is what an agent will act on. A refusal is a deliberate absence from the artifact.

If you only ran generate and wonder where a read went, run scan to see the reason.

The authoritative text is docs/CLI.md (opens in a new tab) in the repository. If this page and that document ever disagree, the repository wins.