Skip to content

Commit c776fbc

Browse files
author
Doug Ransom
committed
Release v0.0.1.dev18
1 parent c4fa218 commit c776fbc

12 files changed

Lines changed: 84 additions & 18 deletions

File tree

‎.agents/AGENTS.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ All Prolog code (regardless of target engine) MUST follow the universal style an
4242
- Prefer coroutining (`freeze/2`, `when/2`) to suspend goals until variables are instantiated, preferring [`CLP(Z)`](https://github.com/mthom/scryer-prolog/blob/master/src/lib/clpz.pl)/`dif/2` over manual coroutining where specialized constraints apply.
4343
- **Direct Reification over `if_/3` for Booleans**: Always prefer direct reified predicates (e.g. `=(X, Y, Truth)`, `memberd_t/3`, `tpartition/4`) over wrapping boolean assignments inside `if_/3` (e.g. use `=(X, Y, Truth)` instead of `if_(X = Y, Truth = true, Truth = false)`). Reserve `if_/3` strictly for selecting non-boolean values (`if_(G, Val = 'yes', Val = 'no')`) or executing conditional branches with distinct control paths.
4444
- **Prefer `cond_t` over `if_` / `->` (DRY Principle)**: Aggressively prefer `cond_t` over `if_` and `->` when choosing between choices or values based on a test. Use `cond_t` to avoid repeating the same variable or assignment in both the true and false clauses of `if_` (Don't Repeat Yourself principle).
45+
- **Meta-Predicate Declarations (`meta_predicate`)**: When defining module-level predicates that accept callable goals (`0`), closures (`1`..`N`), DCG non-terminals (`//` or `2`), or module-sensitive terms (`:`), always insert explicit `:- meta_predicate` declarations directly below the module header. Use exact closure arities for higher-order arguments and standard specifiers (`+`, `-`, `?`, `*`) for non-callable data arguments to prevent unwanted caller module expansion.
4546
- **Declarative AI Workflow**: [.agents/skills/prolog-declarative-workflow/SKILL.md](.agents/skills/prolog-declarative-workflow/SKILL.md)
4647
- Use declarative reasoning based on unification, constraints, and backtracking (never imperative thinking).
4748
- Specify mode (`+`/`-`), determinism (`det`, `semidet`, `nondet`), and choice-point expectations.

‎.agents/references/prolog_guidelines.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,29 @@ Prefer higher-order predicates and closures over primitive recursive list traver
108108
- **Higher-Order DCGs (`call//N`)**: Parameterize DCG rules with closures or non-terminals using `call//N` (e.g. `call(Goal, Arg)` inside `-->`) to avoid writing duplicate grammar traversals.
109109
- **Lambda Expressions (`library(lambda)`)**: Use `:- use_module(library(lambda)).` and lambda abstractions (`\X^...`, `\X^Y^Goal`) for inline transformations, filtering, and mapping without creating single-use helper predicates.
110110

111+
### Meta-Predicate Declarations (`meta_predicate`)
112+
113+
When exporting or defining predicates inside a module that accept callable arguments (goals `0`, closures `1`..`N`, DCG rules `//` or `2`, dynamic goals `:`), always insert explicit `:- meta_predicate` declarations directly after the module header:
114+
115+
- **Module Name Expansion**: Tells the module system to resolve meta-arguments in the context of the *caller module* rather than the library module, preventing runtime `existence_error` exceptions.
116+
- **Precise Arity Specifiers**:
117+
- `0`: 0-argument goal (executed with `call(Goal)` or direct evaluation).
118+
- `1`..`9`: Closures receiving $N$ additional arguments (e.g. `2` for `maplist/3`, `2` for `tfilter/3`, `3` for `foldl/4`).
119+
- `//` or `2`: DCG non-terminal closures expanded with difference lists.
120+
- `+`, `-`, `?`, `*`: Regular non-callable data arguments.
121+
- **Avoid Anti-Patterns**: Never declare `meta_predicate` on pure data predicates, and never mark data arguments as `:` or `0` (which would force unintended caller-module term wrapping).
122+
123+
```prolog
124+
:- module(my_higher_order, [
125+
custom_map/3,
126+
delimited//3
127+
]).
128+
129+
:- meta_predicate
130+
custom_map(2, +, -),
131+
delimited(//, //, //, ?, ?).
132+
```
133+
111134
### Use Term & Goal Expansion to Avoid Code Duplication
112135

113136
Leverage Prolog's compile-time expansion hooks (`user:term_expansion/2` and `user:goal_expansion/2`) to eliminate repetitive code structures, redundant clause boilerplate, or macro-like patterns instead of duplicating logic across multiple rules.

‎.agents/skills/prolog-code-review/SKILL.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Use this skill when reviewing Prolog pull requests, auditing code diffs, or eval
1616
| **Clean Data Representation** | - Can every data element kind be distinguished solely by its **principal functor** (e.g., `leaf(L)` vs `node(L, R)`)?<br>- Are defaulty representations avoided so argument indexing works automatically?<br>- Are external defaulty/unstructured inputs converted into clean trees early? |
1717
| **Determinism & Performance** | - Do deterministic predicates leave open choice points?<br>- Is the primary input placed in the first argument position for first-argument indexing?<br>- Is `zcompare/3` used for reified integer comparisons?<br>- Are recursive calls in tail position (TCO) with accumulators? |
1818
| **Variable Naming & Syntax** | - Are public API parameter names domain-descriptive (`Tree`, `TokenStream`) while standard short names (`X`, `Xs`, `N`) are kept in tight local contexts?<br>- Are DCG state pairs consistently named (`L0..L` / `S0..S`)?<br>- Are neck operators `:-` free of dropped characters (`:` instead of `:-`)?<br>- Are line comments formatted with `%` rather than `#` or `//`?<br>- Are DCG rules declared with `-->` rather than `->`?<br>- Are comparison operators Prolog-standard (`=\=`, `\=`, `=<`, `>=`) rather than C/Python symbols (`!=`, `<=`, `=>`)?<br>- Do module export lists (`:- module/2`), import lists (`:- use_module/2`), and doc comments use ISO `Name//Arity` indicator notation for DCG non-terminals? |
19+
| **Meta-Predicate Declarations** | - Do all exported and module-level predicates taking callable arguments (goals `0`, closures `1`..`N`, DCG non-terminals `//` or `2`, dynamic goals `:`) have explicit `:- meta_predicate` declarations?<br>- Are closure arity extensions accurate (e.g. `2` for `maplist/3`, `2` for `tfilter/3`, `3` for `foldl/4`)?<br>- Are non-callable data arguments marked with `+`, `-`, `?`, or `*` rather than `:` or `0` to prevent unintended caller module qualification? |
1920
| **Engine Portability** | - Are engine-specific types (SWI dicts, SWI strings) avoided in ISO / multi-engine code?<br>- Are explicit module imports declared (e.g. `:- use_module(library(dcgs)).`, `library(si)`, `library(clpz)`)? |
2021
| **Homoiconicity & Prolog Tooling** | - If this tool/program processes or generates Prolog source, is it itself implemented in Prolog?<br>- Does the implementation follow the **ISO core + flat shim** pattern: engine-agnostic logic in `core.pl`, engine-specific differences isolated to `scryer_shim.pl` / `swi_shim.pl` / etc.?<br>- If skill or capability metadata is declared, is it represented as `skill(Name, Caps)` Prolog facts rather than external YAML/JSON config?<br>- Is skill discovery expressed as Prolog queries (`skill(Name, Caps), member(Capability, Caps)`) rather than string-matching lookups? |
2122
| **Safety & Security** | - Is user input sanitized before `consult/1` or `read_term/2`?<br>- Are execution timeouts enforced via `prolog-safe`? |

‎.agents/skills/prolog-conventions/SKILL.md‎

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,31 @@ While the module loading directive (e.g. `:- use_module(library(clpz)).` in Scry
7474
call(Sep, X),
7575
separated_by(Xs, Sep).
7676
```
77-
9. **Explicit Library Declarations**: Always explicitly import required library modules (e.g. `:- use_module(library(reif)).`, `:- use_module(library(dcgs)).`, `:- use_module(library(charsio)).`, `:- use_module(library(lambda)).`, `:- use_module(library(clpz)).`). Do not assume SWI-style autoloading when targeting ISO or embedded engines.
78-
10. **Control Structures & CLP(Z) Constraints**: Use standard ISO control structures `(,)/2`, `(;)/2`. Prefer CLP(Z) constraints (`#=`, `#>`, `all_distinct/1`) and reified arithmetic (`zcompare/3`, `'#='(X, Y, Truth)`, `clpz_t/2`) over low-level evaluation (`is/2`, `>/2`). Always post domain declarations (`ins`, `in`) before posting complex relations to enable early constraint propagation. Link model flags via `#<==>` (e.g. `X #> 10 #<==> B #= 1`) and pass partial closures `(#<)(0)` to `tfilter/3`.
79-
11. **Coroutining & Goal Suspension**: Use `freeze/2` for single-variable activation guards (`nonvar/1`) and `when/2` for multi-variable or disjunctive activation conditions (`(nonvar(A) ; nonvar(B))`). Prefer CLP(Z)/`dif/2` over manual coroutining where domain-specific constraints apply.
80-
12. **Clean Data Representations**: Prefer clean data structures where element kinds are distinguished by principal functor (`leaf(L)` vs `node(L, R)`). Avoid defaulty representations that force runtime type tests (`var/1`) or procedural default branches. Convert raw input data into clean trees early.
81-
13. **Macro & Compile-Time Expansion**: Use Prolog's macro mechanism (`user:term_expansion/2` and `user:goal_expansion/2`) to transform clauses or rewrite inline goals at compile time to eliminate boilerplate and redundant rules. Prefer static compile-time expansion over dynamic database modification (`asserta`/`assertz`).
82-
14. **Avoid Non-Standard Extensions**: Do not rely on engine-specific types (e.g. SWI dicts or SWI string types) when writing standard Prolog code.
83-
15. **Library Steering vs Reading Source**: Rely on dialect-specific Standard Library Cheat Sheets for module header declarations and predicate exports. AI assistants MUST NOT read raw standard library implementation source files, relying instead on concise cheat sheets and pre-trained semantics to save context tokens.
84-
16. **Safety**: Execute code using `prolog-safe`.
85-
86-
17. **Prolog Tooling in Prolog (ISO Core + Engine Shims)**: Programs that parse, rewrite, transform, analyze, or generate Prolog source code SHOULD themselves be implemented in Prolog, exploiting the language's homoiconicity (code = terms = data). Structure such tools using an ISO-common core with flat, engine-specific shim files:
77+
9. **Meta-Predicate Declarations (`meta_predicate`)**: When defining predicates in a module that accept callable arguments (goals `0`, closures `1`..`N`, DCG rules `//` or `2`, or module-sensitive terms `:`), ALWAYS insert a `:- meta_predicate` declaration directly after the `:- module/2` header and imports. This ensures the module system applies caller-module name expansion to meta-arguments across module boundaries:
78+
```prolog
79+
:- module(my_combinators, [
80+
my_maplist/3,
81+
my_tfilter/3,
82+
bracketed//3
83+
]).
84+
85+
:- meta_predicate
86+
my_maplist(2, +, -),
87+
my_tfilter(2, +, -),
88+
bracketed(//, //, //, ?, ?).
89+
```
90+
- Use exact closure arities: `0` for goals (`call(G)`), `1`..`9` for closures expecting additional arguments (`call(C, X)` -> `1`, `call(C, X, Y)` -> `2`), `//` (or `2`) for DCG rules.
91+
- Use `+`, `-`, `?`, `*` for non-meta data terms. NEVER declare `meta_predicate` on first-order data predicates or mark data arguments as `:`/`0` (which would trigger unwanted module qualification wrapping).
92+
10. **Explicit Library Declarations**: Always explicitly import required library modules (e.g. `:- use_module(library(reif)).`, `:- use_module(library(dcgs)).`, `:- use_module(library(charsio)).`, `:- use_module(library(lambda)).`, `:- use_module(library(clpz)).`). Do not assume SWI-style autoloading when targeting ISO or embedded engines.
93+
11. **Control Structures & CLP(Z) Constraints**: Use standard ISO control structures `(,)/2`, `(;)/2`. Prefer CLP(Z) constraints (`#=`, `#>`, `all_distinct/1`) and reified arithmetic (`zcompare/3`, `'#='(X, Y, Truth)`, `clpz_t/2`) over low-level evaluation (`is/2`, `>/2`). Always post domain declarations (`ins`, `in`) before posting complex relations to enable early constraint propagation. Link model flags via `#<==>` (e.g. `X #> 10 #<==> B #= 1`) and pass partial closures `(#<)(0)` to `tfilter/3`.
94+
12. **Coroutining & Goal Suspension**: Use `freeze/2` for single-variable activation guards (`nonvar/1`) and `when/2` for multi-variable or disjunctive activation conditions (`(nonvar(A) ; nonvar(B))`). Prefer CLP(Z)/`dif/2` over manual coroutining where domain-specific constraints apply.
95+
13. **Clean Data Representations**: Prefer clean data structures where element kinds are distinguished by principal functor (`leaf(L)` vs `node(L, R)`). Avoid defaulty representations that force runtime type tests (`var/1`) or procedural default branches. Convert raw input data into clean trees early.
96+
14. **Macro & Compile-Time Expansion**: Use Prolog's macro mechanism (`user:term_expansion/2` and `user:goal_expansion/2`) to transform clauses or rewrite inline goals at compile time to eliminate boilerplate and redundant rules. Prefer static compile-time expansion over dynamic database modification (`asserta`/`assertz`).
97+
15. **Avoid Non-Standard Extensions**: Do not rely on engine-specific types (e.g. SWI dicts or SWI string types) when writing standard Prolog code.
98+
16. **Library Steering vs Reading Source**: Rely on dialect-specific Standard Library Cheat Sheets for module header declarations and predicate exports. AI assistants MUST NOT read raw standard library implementation source files, relying instead on concise cheat sheets and pre-trained semantics to save context tokens.
99+
17. **Safety**: Execute code using `prolog-safe`.
100+
101+
18. **Prolog Tooling in Prolog (ISO Core + Engine Shims)**: Programs that parse, rewrite, transform, analyze, or generate Prolog source code SHOULD themselves be implemented in Prolog, exploiting the language's homoiconicity (code = terms = data). Structure such tools using an ISO-common core with flat, engine-specific shim files:
87102
- **ISO core** (`core.pl`): All term reading (`read_term/2`), DCG-based traversal and transformation, `copy_term/2`, `functor/3`, `=..`, and CLP(Z) constraints. This layer MUST NOT use engine-specific predicates or library paths.
88103
- **Flat shim files** (`scryer_shim.pl`, `swi_shim.pl`, `trealla_shim.pl`, etc.): Each shim defines only what differs per engine — module load paths, flag names, engine-specific built-ins — and exports a uniform interface consumed by the core.
89104
- **Entry point** (`run.pl`): Selects and loads the appropriate shim (e.g. via `PROLOG_ENGINE` flag or conditional compilation), then loads `core.pl`.

‎.agents/skills/prolog-dcg-mastery/SKILL.md‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,18 @@ For complex programming languages or DSLs, split parsing into two pure DCG passe
101101

102102
---
103103

104-
## 6. Higher-Order DCGs (`call//N`)
104+
## 6. Higher-Order DCGs (`call//N`) & Meta-Predicates
105105

106-
Avoid duplicating DCG rules just to vary an element non-terminal or predicate. Use `call//N` to parameterize grammar rules:
106+
Avoid duplicating DCG rules just to vary an element non-terminal or predicate. Use `call//N` to parameterize grammar rules, and declare `:- meta_predicate` with `//` or `2` so closures resolve in the caller module context:
107107

108108
```prolog
109+
:- module(seq_combinators, [
110+
seq_of//2
111+
]).
112+
113+
:- meta_predicate
114+
seq_of(?, //, ?, ?).
115+
109116
% Generic DCG rule to match a list of elements using a parameter non-terminal nonterm//1
110117
seq_of([], _) --> [].
111118
seq_of([X|Xs], NonTerm) -->

‎CHANGELOG.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
## [0.0.1.dev18] - 2026-08-31
2+
3+
### Summary of Changes
4+
- Added Meta-Predicate Declarations (`:- meta_predicate`) guidelines and standards across `prolog-conventions`, `prolog-dcg-mastery`, `prolog-code-review`, `AGENTS.md`, and `prolog_guidelines.md`.
5+
- Added explicit rules for caller-module expansion, closure arity specifiers (`0`, `1`..`N`, `//`), and non-callable data term markings (`+`, `-`, `?`, `*`).
6+
- Updated Code Review checklist to audit module encapsulation and meta-predicate declarations.
7+
- Synchronized version `0.0.1.dev18` across manifests and documentation.
8+
9+
### Added / Modified
10+
- `.agents/skills/prolog-conventions/SKILL.md`: Added Rule 9 on Meta-Predicate Declarations.
11+
- `.agents/skills/prolog-code-review/SKILL.md`: Added Meta-Predicate Declarations verification row to code review checklist.
12+
- `.agents/skills/prolog-dcg-mastery/SKILL.md`: Added meta-predicate declarations example for higher-order DCG non-terminals.
13+
- `.agents/AGENTS.md`: Added meta-predicate declaration standard to Universal Prolog Style & Purity Guidelines.
14+
- `.agents/references/prolog_guidelines.md`: Added detailed meta-predicate reference section.
15+
16+
### Breaking Changes
17+
- None.
18+
19+
120
## [0.0.1.dev17] - 2026-08-29
221

322
### Summary of Changes

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[![Schema.org Metadata](https://img.shields.io/badge/schema.org-JSON--LD-brightgreen.svg)](schema.org.jsonld)
88
[![Share on LinkedIn](https://img.shields.io/badge/Share_on-LinkedIn-0A66C2?logo=linkedin&logoColor=white)](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fgithub.com%2Fdougransom%2Fprolog-agent-toolkit)
99

10-
**Version**: `0.0.1.dev17`
10+
**Version**: `0.0.1.dev18`
1111
**Category**: AI Assistant Developer Tools / Prolog Language Tooling
1212
**Metadata**: [schema.org.jsonld](schema.org.jsonld)
1313

‎docs/capability_manifest.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "Prolog Agent Toolkit Capability Manifest",
3-
"version": "0.0.1.dev14",
3+
"version": "0.0.1.dev18",
44
"vendor_neutral": true,
55
"description": "Reusable AI agent skills, coding standards, and safety execution toolkit for Prolog",
66
"capabilities": {

‎docs/repository_ontology.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$schema": "https://json-schema.org/draft/2020-12/schema",
33
"name": "Prolog Agent Toolkit Repository Ontology",
44
"description": "Machine-readable graph mapping components, file dependencies, and structural relations",
5-
"version": "0.0.1.dev14",
5+
"version": "0.0.1.dev18",
66
"nodes": [
77
{
88
"id": "pyproject.toml",

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "prolog-agent-toolkit"
7-
version = "0.0.1.dev17"
7+
version = "0.0.1.dev18"
88
description = "Reusable AI agent skills, coding standards, and safety runner toolkit for multi-engine Prolog"
99
readme = "README.md"
1010
requires-python = ">=3.9"

0 commit comments

Comments
 (0)