Skip to content

Registry reads per predicate, and a CLI loader that keeps every battery's manifest - #1

Merged
Abica merged 2 commits into
mainfrom
registry-reads
Oct 31, 2026
Merged

Abica merged 2 commits into
mainfrom
registry-reads

Conversation

@Abica

@Abica Abica commented Oct 31, 2026

Copy link
Copy Markdown
Member

What

Registry: reads. Each battery with an input contract now publishes, for every exported predicate, the contract facts that predicate can read through the battery's own clauses (check_inputs.reads_for, emitted by build_registry.py beside inputs).

A default is not a fact, so a proof that falls back on one leaves nothing for a host to point at. Without reads, a host had to report every default in the contract on every answer: a days-overdue answer listed the late-fee default. With it, a host reports only the defaults and gaps the question's predicates can reach. Batteries without a contract get no reads, and hosts that ignore the key are unaffected.

CLI: batteries.pl loader. battery install and battery remove now keep a batteries.pl that includes every installed battery, with battery_module/3, battery_export/3 and battery_input/6 declared discontiguous. Consulting battery files one by one redefined those predicates with each file, so only the last battery's manifest and contract survived. Apps now load everything with consult('batteries.pl'). A batteries.pl the user wrote is never overwritten, and the loader is removed with the last battery.

CLI: hyphenated ids. The seven batteries whose id is hyphenated while their directory is not (invoice-rules in invoice_rules/, and six others) were missing from battery list and could not be installed. The directory is now looked up under either spelling.

Checked

  • make check passes; build_registry.py --check is clean.
  • reads spot-checked against invoice-rules:
    • days_overdue reaches no billing setting;
    • late_fee reaches the three fee settings;
    • escalation_level reaches the two thresholds.
  • Seven exported predicates read no contract fact, as expected: hooks (assign_reject, part_exempt) and pure functions of their arguments (bulk_discount/3, hier_own).
  • CLI: 11 tests pass, including new ones for the loader, removal, a user-owned batteries.pl and hyphenated ids.
  • Loader verified by hand in SWI-Prolog and Scryer with two contract batteries: 15 + 10 battery_input entries kept in both.

Notes

  • Scryer rejects ensure_loaded and consult as directives and panics on include with multifile, which is why the loader uses include with discontiguous.
  • Scryer resolves include/1 against the working directory, so Scryer users start it from the install directory; the loader header says so.
  • Scryer bug: enumerating battery_input/6 with an unbound battery under discontiguous skips entries. Querying a given battery is correct.

Abica added 2 commits October 30, 2026 18:13
A default is not a fact, so a proof that falls back on one leaves nothing for
a host to point at, and DataGrout listed every default in a battery's
contract on every answer (late_fee_flat on a days_overdue question).
check_inputs.reads_for follows each exported predicate through the battery's
own clauses and records the contract facts it can read; build_registry.py
writes them as `reads`, beside `inputs`.
Consulting battery files one by one redefined battery_module/3,
battery_export/3 and battery_input/6 with each file, so only the last
battery's manifest and contract survived (invoice_rules kept 0 of its 15
contract entries once pricing_rules loaded). install and remove now keep a
batteries.pl that includes every installed battery with those predicates
declared discontiguous: all clauses kept in SWI-Prolog and in Scryer, which
rejects ensure_loaded/consult as directives and panics on include+multifile.
A user-written batteries.pl is left alone.

The seven batteries whose id is hyphenated while their directory is not
(invoice-rules lives in invoice_rules/) were missing from list and install;
the directory is looked up under either spelling.

The CHANGELOG records this and the registry's new `reads`.
@Abica
Abica merged commit 65d4c36 into main Oct 31, 2026
3 checks passed
@Abica
Abica deleted the registry-reads branch October 31, 2026 01:20
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