Predicate Packages: Bundling distinctions for transport
The name of the party must be written, and the name of his father, and his place of origin, so that he may be distinguished from all others of the same name.
This chapter formalizes the predicate package as Anchor A24: a 7-tuple comprising signature, intension, runtime spec, tests, invariants, provenance, and scope that constitutes the contract between an invented predicate and the substrate (A22). A24 specifies staged acceptance criteria (admission and promotion), three operations (admit, rebase, version), and agreement contracts that determine gluing semantics. The chapter draws on predicate invention (A17) and invariant preservation (A17b) from Chapters 15 and 16, and applies the proof-carrying paradigm to predicate governance. For the narrative introduction to predicate drift and the need for packaging discipline, see Vol I, Chapter 7 (The Witness Protocol).
Predicates Without Packages Drift
A user invents "puffy" during a search session. The predicate works: it identifies dresses with voluminous silhouettes. The user leaves. What happens to "puffy"?
Without structure, the predicate becomes a liability. The reference set that defined "max volume" updates when new items enter the catalog. The same formula now returns different scores. A colleague uses "puffy" assuming it means what they mean by puffiness, not what the original user meant. Someone promotes it to an org-wide filter without checking whether it satisfies invariants in contexts beyond the original session. Six months later, a compliance audit asks who authorized this predicate, when, and with what evidence. No one knows.
This is not drift as accident. It is drift as structural vulnerability. Without packages, predicate names become write-access to meaning. Whoever runs the evaluator at query time controls what the predicate "meant" retroactively.
The failure modes are predictable: definition without runtime spec (same name, different code paths, no explanation); tests without invariants (predicate passes today, violates constraints tomorrow); signature without tests (meaning drifts to whatever the evaluator computes); local validity without scope (silent assumption of global standing); definition without provenance (authority unauditable).
Chapter 15 defined predicate invention (A17) and produced the PredicateDossier artifact. Chapter 16 established invariant preservation (A17b). Chapters 20 and 21 built the substrate. The missing piece is the contract between predicates and substrate: what must a predicate carry to be accepted?
Anchor A24: Predicate Package
A predicate package is a 7-tuple:
Components:
- (signature): domain, codomain, arity, agreement contract
- (intension): evaluation method (rule, measurement, oracle, learned)
- (runtime spec): evaluator identity, dependencies pinned, required inputs, determinism class
- (tests): witness set (positive exemplars, negative exemplars, boundary cases, confounders)
- (invariants): hard invariants q must satisfy (internal + external)
- (provenance): origin (author, timestamp, authority level, derivation chain)
- (scope): admitting context, promotion path, current standing
Acceptance criteria (staged):
Admission (criteria 1-5, checked when package enters context U):
- Well-formed: is a valid type in the substrate's type system
- Grounded: can be evaluated using in context U
- Witnessed: satisfies the witness criterion for the agreement contract (see below)
- Admission-invariant: q does not violate in U
- Scoped: S declares U as admitting context; authority permits
Promotion (criteria 6-8, checked when scope widens U → V): 6. Promotion-invariant: q does not violate in V 7. Authority: scope-appropriate authority required; A21 budget applies 8. Overlap agreement: agreement contract satisfied on U ∩ V
Operations:
admit(q, U) → Admitted | Rejected(reason)rebase(q, U→V, π_widen) → q' | RebaseFailureversion(q, Δ) → q' | MigrationRequired
A predicate package is not documentation. Documentation is optional and unvalidated. The package is mandatory and validated by the substrate. A predicate without a valid package is rejected at admission. Governance costs money: the coherence budget (A21) prices admission, promotion, and versioning according to the standing you claim.
The package is the predicate's citizenship papers. It records what the predicate claims to do, how it does it, what evidence supports it, what constraints it promises to satisfy, who authorized it, and where it is valid. The substrate can verify these claims locally, without trusting the sender.
Invariants: package vs substrate. Package invariants are claims about q (what the predicate promises). Substrate invariants are constraints in U (what the context requires). Admission checks both.
Substrate representation. A predicate package is represented in the context graph (A22) as a structured claim bundle, not a sixth node type. The predicate itself is an opaque entity token. The package components are claims about that token, supported by witness nodes (test results, calibration witnesses, authority attestations), constrained by constraint nodes (external invariants), and scoped to the admitting context via scoped_to edges. This keeps A22's five node types intact. A24 is a schema for organizing claims about predicate-tokens, not an additional node type.
The Proof-Carrying Paradigm
The paradigm is borrowed from Necula's Proof-Carrying Code(Necula 1997)George C. Necula, "Proof-Carrying Code," in Proceedings of the 24th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (POPL 1997) (ACM, 1997), 106–119.View in bibliography: mobile code ships with a proof; the host verifies locally without trusting the sender. The question is not "is this code safe?" but "does this proof verify?" We ask the same of predicates: not "is this predicate good?" but "does this package validate?"
The substrate cannot trust the sender: arbitrary users can propose predicates. The substrate cannot consult a global oracle. It must validate locally. And validation must be cheap: O(package size), not O(catalog size). For promotion with overlap agreement, cost may scale with overlap size; this is priced by A21.
The "proof" in proof-carrying predicates is not a mathematical proof but a locally-checkable certificate of admission, not a universal truth claim. The verifier is explicit:
Verify(q, U) → Valid | Invalid(reason):
1. Type-check σ against substrate type system
2. Check ι is evaluable with ρ in U (dependencies available, inputs present)
3. Run ι under ρ on witness set τ; check witness criterion (by contract type)
4. Check q against I_hard in U (package invariants + substrate constraints)
5. Check authority chain in π permits admission to U
6. If promotion: check agreement contract on overlap items
Return Valid if all pass; else Invalid(first_failure)
The dominant term is evaluation on τ: O(|τ| · C_eval(ρ)), where C_eval is the per-exemplar cost of the pinned evaluator. The substrate bounds |τ| by standing: user-level predicates require fewer exemplars than org-level or global predicates. This is linear in package size, not catalog size. The substrate verifies without re-evaluating the predicate on arbitrary inputs.
The Witness Criterion (by Agreement Contract)
The witness criterion in acceptance criterion 3 depends on the agreement contract type:
| Contract | Witness Criterion |
|---|---|
decidable | All positives evaluate true; all negatives evaluate false |
calibrated | Mean separation ≥ ε between positive and negative scores after applying monotone transform from CalibrationWitness |
majority-attested | Attestation quorum satisfied on positives; fails threshold on negatives (or carries explicit dissent witness) |
probabilistic-bound | For all exemplar pairs, P(pos > neg) ≥ 1 − δ as certified by ErrorBoundWitness |
For decidable predicates (Bool codomains), the criterion is strict: the evaluator must correctly classify every exemplar. For calibrated predicates (Score codomains), the criterion allows tolerance: scores must be separable above margin ε after monotone calibration. For learned predicates, the criterion requires both calibration and error bound witnesses.
This makes "witnessed" concrete rather than handwavy. The substrate checks a well-defined condition, not a vague "sufficient exemplars."
The Seven Components
Signature (). The signature declares the predicate's type: what it takes as input, what it returns, and how values from different evaluations are reconciled. For "puffy," the domain is Dress, the codomain is Score (a real number in [0,1]), the arity is 1. The agreement contract specifies how to handle disagreement: for Score predicates, the contract is typically calibrated(ε), meaning two evaluations agree if they are within ε of each other after a monotone calibration transform.
The agreement contract is part of σ because it determines glue semantics. When the substrate attempts glue(cover, target) (A22), it retrieves the agreement contract and runs the appropriate comparison. The contract determines the gluing procedure.
| Agreement Contract | Comparison | Evidence Required |
|---|---|---|
decidable | exact equality | none |
calibrated | monotone within ε | CalibrationWitness |
majority-attested | voting threshold | AttestationSet |
probabilistic-bound | confidence interval δ | ErrorBoundWitness |
Intension (). The intension is the evaluation method: how you compute the predicate's value for a given input. Four types are supported:
Rule-based: A logical formula in terms of existing predicates. If voluminous and structured already exist, puffy might be defined as voluminous(d) ∧ ¬structured(d). The formula is auditable; you can check whether the rule was applied correctly.
Measurement-based: A deterministic procedure. For "puffy," this might be volume_ratio(d) / max_volume_in_reference_set. The reference set is pinned at creation time; otherwise the measurement drifts as the catalog changes.
Oracle-based: Human judgment. A stylist assigns a puffiness score. The oracle must be declared, not hidden. The system records that this predicate's values come from human judgment, not computation.
Learned: A classifier or regressor trained on exemplars. The model must carry provenance (training data, architecture, version), calibration witness, error bound, and known failure modes. It is not a black box; it is a function with declared uncertainty.
Runtime spec (). The runtime spec prevents "same predicate name, different code path." It contains:
RuntimeSpec {
evaluator_id: hash of evaluation code or model weights,
dependencies: [(predicate_name, version, hash), ...],
required_inputs: [feature_name, ...],
determinism: Deterministic | Stochastic(seed_policy) | External(oracle_id)
}
Given the same inputs and the same , the evaluator must produce the same outputs (modulo declared stochasticity). This is reproducibility by construction.
Tests (). The witness set grounds the predicate's meaning. For "puffy": five dresses labeled high-puffy (score > 0.7), five labeled low-puffy (score < 0.3), each with provenance. The test set also includes boundary cases (items where the label is disputed) and confounders (items that might fool a naive evaluator, like a voluminous coat that is not a dress).
The witness criterion depends on agreement contract type (see above). The substrate checks a well-defined condition, not a vague sufficiency standard.
Invariants (). The package carries two kinds of invariants:
Internal invariants: constraints the predicate promises to satisfy. For "puffy": puffy(d) ∈ [0,1] for all d; puffy is monotone with respect to volume_ratio.
External invariants: constraints the substrate requires. Predicates must be conservative with respect to existing vocabulary (A17b). Learned predicates must carry calibration witnesses.
Admission checks both kinds in the admitting context. Package invariants are claims about q; substrate invariants are constraints in U.
Provenance (). Who invented this predicate? When? Under what authority? With what derivation?
Provenance {
author: "user_session_42",
timestamp: "2024-01-15T10:30:00Z",
authority: user | org | system | regulator,
derivation: "measurement_from_volume" | "rule_composition" | "model_training" | ...
}
Authority levels constrain what you can claim. A user-level predicate cannot assert system authority. Promotion to higher authority requires additional approval.
Scope (). Where is this predicate valid? A predicate starts local. It is admitted to a specific context, not to the entire substrate.
Scope {
admitting_context: user_session_42_view,
promotion_path: [user → org → global],
current_standing: local
}
Globality is a promotion outcome, not a creation-time attribute. The predicate must earn broader scope by passing promotion criteria.
Intension Types and Their Obligations
Different intension types have different validation requirements and different constraints on scope widening (rebase).
| Intension | Tests Required | Calibration | Reproducibility | Rebase Difficulty |
|---|---|---|---|---|
| Rule | positive/negative | N/A | yes (given deps) | easy |
| Measurement | positive/negative | N/A | yes (given ref set) | medium |
| Oracle | positive/negative | optional | no | hard |
| Learned | calibration set | required | conditional | hard |
Rule-based predicates are easiest to rebase: if the dependencies rebase, the rule rebases. Measurement-based predicates require the reference set to be valid in the target context. Oracle-based predicates are hard: the oracle may not be available or authoritative in a different context. Learned predicates are hardest: the model may not generalize outside its training distribution.
This is where T9 (schema evolution) bites. Learned predicates are especially prone to drift because the model changes. When you retrain, you get a new evaluator_id. The package makes this visible; without it, the drift is silent.
T6: Puffy Dress (Full Package)
PredicatePackage(puffy) = {
signature: Dress → Score, calibrated agreement
intension: volume_ratio / max_volume_in_reference_set
runtime: deterministic evaluator, pinned dependencies
tests: positive, negative, boundary, confounder exemplars
invariants: score ∈ [0,1], monotone w.r.t. volume, conservative extension
provenance: author, timestamp, authority level, derivation method
scope: admitting context, promotion path [user → org → global]
}
The seven components each do distinct work. The signature declares what the predicate accepts and returns. The intension records how it computes. The runtime pins the evaluator so that the same inputs always produce the same outputs. The tests provide the empirical evidence that the predicate separates what it claims to separate — positive exemplars scoring high, negative exemplars scoring low, with enough separation to satisfy the agreement contract. The invariants are the promises the predicate makes to the substrate. The provenance records who created it and under what authority. The scope declares where the predicate is admitted and what path it must follow to earn broader standing.
Admission checks five conditions: well-formed (valid type), grounded (computable in the admitting context), witnessed (exemplars demonstrate adequate separation), admission-invariant (no existing constraint violated), and scoped (authority sufficient for the declared scope). If all five pass, the predicate enters the substrate as a first-class citizen.
The predicate now exists as a first-class citizen. It can be queried, versioned, and (with additional authorization) promoted to broader scopes. It cannot be silently redefined, because any change requires a new version with new witnesses.
T9: Schema Evolution
The reference set changes. New items enter the catalog. The max volume in the new catalog is larger than before.
Version 1: puffy_v1 uses reference_set catalog_v3_2024Q1. Max volume: 1200 cubic units.
Version 2: puffy_v2 uses reference_set catalog_v4_2024Q4. Max volume: 1500 cubic units.
A dress with volume 900 cubic units:
- Under
puffy_v1: score = 900/1200 = 0.75 - Under
puffy_v2: score = 900/1500 = 0.60
Same formula. Same dress. Different scores. Same name would mean different things.
Without packages, this drift is invisible. The scores silently change. Downstream invariants that depended on "puffy > 0.7" silently break.
With packages, the drift is explicit. puffy_v2 is a new package with a different reference_set and a different evaluator_id. The system computes a compatibility witness:
Is puffy_v2 ⪯ puffy_v1? That is: does puffy_v2(d) ≤ puffy_v1(d) for all d in the overlap? Yes. The new version systematically assigns lower scores because the denominator is larger. This monotone refinement holds under this specific normalization scheme; in general, compatibility is empirical and witnessed on the overlap set.
The version(q, Δ) operation emits a migration artifact:
MigrationWitness(puffy_v1 → puffy_v2) = {
compatibility: refinement (v2 ⪯ v1),
change: { reference_set: "catalog_v3_2024Q1" → "catalog_v4_2024Q4" },
affected_invariants: ["puffy > 0.7" thresholds shift downward],
consumer_action_required: true,
options: [
"accept_refinement: downstream thresholds auto-adjust",
"pin_version: continue using v1 with frozen reference_set",
"fork: maintain both versions with explicit scope separation"
]
}
The substrate does not choose. It surfaces the options with their costs (A21). The consumer chooses. But the choice is recorded, witnessed, and auditable. Silent drift is replaced by governed evolution.
Lightweight Admission: The Tag That Becomes a Citizen
The seven-tuple package is the full specification. But users do not arrive with seven-tuples. They arrive with gestures: "tag this as cool," "mark these as similar," "call this puffy." The system must bridge the gap.
When a user tags an item, the system infers a provisional package. The inference is explicit, not magical: the system applies defaults, records what it assumed, and marks the result as requiring verification before promotion.
User action: Tags three dresses as "cool" during a session.
System inference:
PredicatePackage(cool) = {
signature: {
domain: Item,
codomain: Bool,
arity: 1,
agreement_contract: decidable // tagged or not
},
intension: Extension {
type: "explicit_membership",
members: [dress_A, dress_B, dress_C]
},
runtime: {
evaluator_id: "membership_check",
dependencies: [],
required_inputs: [item_id],
determinism: Deterministic
},
tests: {
positive: [dress_A, dress_B, dress_C], // the tagged items
negative: [], // none declared
boundary: [],
confounders: []
},
invariants: {
internal: [],
external: [conservative_extension] // default
},
provenance: {
author: "user_session_87",
timestamp: "2024-01-20T14:22:00Z",
authority: user,
derivation: "auto_inferred_from_tags"
},
scope: {
admitting_context: user_session_87_view,
promotion_path: [user → org → global],
current_standing: local // usable in session, pending verification for promotion
}
}
The auto-inferred package has gaps. No negative exemplars. No invariants beyond the default. No calibration. These gaps are not hidden; they are recorded in the package and reflected in the promotion requirements.
Promotion requires filling the gaps. To promote "cool" from local to org level, the system requires at least one negative exemplar. To promote from org to global, the system requires a defined intension (not just membership) and boundary cases. The package grows as the predicate's standing grows.
This is the Third Mode's answer to the cold-start problem. Users can gesture informally. The system interprets their gestures as provisional packages. Provisional packages are usable within their session but do not escape without earning their citizenship. The barrier to entry is low; the barrier to promotion is appropriate to the standing claimed.
The auto-inference is not inference about meaning. The system does not guess what "cool" means. It records what the user did (tagged these items) and packages that behavior as a local predicate. The meaning, if any, comes later—when the user or the organization fills in the intension, adds negative exemplars, and earns broader standing.
Rebase and Versioning
Admission is the first operation. A package proposes to enter a context. The substrate checks criteria 1-5 and returns Admitted or Rejected(reason).
Rebase is scope widening. A predicate admitted in context U wants standing in context V. The operation rebase(q, U→V, π_widen) checks promotion criteria:
- Does q satisfy hard invariants in V? (Promotion-invariant)
- Does the requester have scope-appropriate authority? (A21 budget applies)
- If U and V overlap, does the agreement contract hold on shared items? (Overlap agreement)
Rebase respects intension type. A learned predicate trained on fashion data cannot rebase to a medical context without retraining. The substrate enforces this: the promotion-invariant check asks whether the evaluator is valid in the target context.
Versioning is evolution over time. A predicate changes: new tests, new reference set, retrained model. The operation version(q, Δ) produces a new package.
If the change is non-breaking (the new version refines or extends the old), the system records the compatibility relation and propagates the update.
If the change is breaking (the new version is incompatible with the old), the system requires migration witnesses (A17b). Downstream consumers must acknowledge the breaking change, either by migrating to the new version or by forking to a pinned version.
Rebase vs version: disambiguation. Rebase keeps the evaluator fixed and widens scope. Version changes the evaluator (or its inputs) and may or may not be promotable.
puffyadmitted inuser_session_42_view→rebase(puffy, user→org, π_widen)widens scope with governance approval. Same evaluator, broader standing.puffy_v2created because reference_set changed →version(puffy, Δ)produces new package with new evaluator_id. Different meaning, migration required.
The cost of versioning scales with the standing you claim. A user-level predicate can be versioned cheaply. An org-wide predicate requires more witnesses. A global predicate requires full certification. This is A21's coherence budget in action: governance costs money.
Agreement Contracts and Gluing
When a predicate is evaluated in multiple contexts, the results must be reconcilable. The agreement contract specifies how.
For decidable predicates (Bool codomains), agreement means exact equality. Either the predicate holds or it does not.
For calibrated predicates (Score codomains), agreement means values are within ε of each other after calibration. If merchant A scores a dress at 0.8 and merchant B scores it at 0.75, they agree if calibration shows their scales are monotonically related and the difference is within tolerance.
For majority-attested predicates (oracle codomains), agreement means voting consensus. If three stylists label a dress and two say "puffy," the predicate agrees with the majority.
For probabilistic-bound predicates (learned codomains), agreement means confidence intervals overlap. If model A predicts 0.7 ± 0.1 and model B predicts 0.65 ± 0.1, they agree.
The agreement contract is not metadata. It is executable. When the substrate attempts glue(cover, target) (A22), it retrieves the agreement contract from each predicate's package and runs the appropriate comparison. A calibrated predicate triggers calibration witness lookup. A probabilistic-bound predicate triggers confidence interval computation. The contract determines the gluing procedure.
Mismatched contracts block gluing. If merchant A's "sustainable" uses decidable (Bool) and merchant B's uses calibrated (Score), the overlap check fails before values are compared. The types disagree. The substrate emits an obstruction witness naming the contract mismatch, not the value disagreement. This is correct: the predicates are not commensurable, and no amount of value reconciliation will fix it.
What Packages Prevent
Packages prevent three failure modes:
Drift. Meaning changes silently. The reference set updates, the model retrains, the oracle changes their mind. Without packages, no one notices. With packages, every change is a version event with witnesses.
Escape. Scope expands silently. A user-level predicate becomes org-wide because someone copied it. Without packages, standing is assumed. With packages, standing is earned through promotion criteria.
Forgery. Same name, different runtime. Two systems evaluate "puffy" with different code paths and get different results. Without packages, the divergence is invisible. With packages, the evaluator_id pins the runtime and makes forgery detectable.
Consequence
The predicate package is the unit of meaning in the Third Mode substrate. A predicate without a package is a drifting signifier. A predicate with a package is a first-class citizen with rights and obligations.
The package carries its own proof of admission. The substrate verifies locally, without trusting the sender. Predicates that pass admission can be queried, versioned, and promoted. Predicates that fail admission are rejected with a reason.
Local truth remains cheap: anyone can propose a predicate. Global coherence remains expensive: the package is the price of admission. The substrate collects the toll.
Chapter 23 asks what a query promises when it runs against this substrate. A query is also a contract: it declares what contexts it references, what predicates it uses, what witnesses it requires, and what uncertainty it tolerates. The predicate package is one half of the contract. The query contract is the other half.