docs/tickets: open #000032 (combinatorics@v1 π*) + #000033 (pillar VII)

Two design-only tickets opened together because they're tightly
coupled — pillar VII records bind to combinatorics@v1 via
pi_star_ref, and #000032 lands first to avoid rebind churn on
that field.

#000032 — combinatorics@v1 π*
=============================
A new π* kernel that canonicalizes pure-integer counting
expressions (binomial, factorial, permutations, partitions,
Catalan, Bell, Stirling) and FAILS CLOSED on any input whose
result is not a non-negative integer. Tighter domain than
algebra-symbolic@v1, which already accepts the same input
surface but happily returns symbolic / negative / rational
outputs.

Distinguishing feature: algebra-symbolic@v1 returns
binomial(n,k) → "binomial(n,k)" (symbolic), binomial(-3,2) → 6
(generalized). combinatorics@v1 rejects both. Operators choose
the kernel by what they want rejected.

Output format: integer string (b"10"). Compose with
arithmetic@v1 to get bytes-identical agreement (b"10/1") for
the multi-modality witness flow.

Estimated size: ~120 LOC module + ~80 LOC tests + ~22 fixtures.
Single-commit feasible.

#000033 — Claim-pack pillar VII (combinatorics)
================================================
Extend the claim-pack source (#000029) with a new combinatorics
pillar slotting into the documented gap (existing v2 bundles use
I, II, III, IV, V, VI, IX — VII and VIII reserved for
extension). Counting axioms (Pascal's rule, addition principle,
multiplication principle, pigeonhole, factorial / binomial
definitions) + classical theorems (binomial theorem,
inclusion-exclusion in counting form, hockey-stick, Vandermonde,
Catalan closed form, stars-and-bars).

Bundle provenance is the open question — three options
documented:
  A. Commission a Grok-4 v3 bundle for parity with the existing
     pack.
  B. Hand-curate from textbooks (Stanley, Brualdi, Wilf, Knuth).
  C. Hybrid — LLM draft + human curation.

Hard constraint: explicit authorship metadata. No silent
invention. Bundle landing is a config + data exercise; no
source-code changes to arborist/sources/claim_pack.py needed
since the source already iterates arbitrary pillar names.

Sequencing: #000032 first (kernel), #000033 next (records bind
to it from day one), #000031 stays parallel-track (textbook
ingest for warrant promotion).

Both tickets stay open · awaiting go/no-go pending fox's
implementation green-light.
This commit is contained in:
russell@unturf.com 2026-05-09 12:59:29 -04:00
parent 5257f9a8f3
commit d34ecb27c1
No known key found for this signature in database
3 changed files with 711 additions and 1 deletions

View file

@ -61,6 +61,8 @@ Newest first. Update on every open/close.
| ID | Title | Status | Opened | Directive |
|----------|------------------------------------------------|-----------------------|------------|-----------|
| #000033 | Claim-pack pillar VII (combinatorics) | open · awaiting go/no-go | 2026-05-09 | — |
| #000032 | combinatorics@v1 π* (integer counting kernel) | open · awaiting go/no-go | 2026-05-09 | — |
| #000031 | Surface-ingest cited textbooks for claim-pack warrant promotion | open · awaiting go/no-go | 2026-05-09 | — |
| #000030 | Math π* expansion: SymPy substrate (algebra · calculus · linalg) | closed · Phases 1+2+1b+3 landed 2026-05-09 (4-7 future work) | 2026-05-09 | — |
| #000029 | Claim-pack source (axiom/theorem JSON bundles) | closed · landed 2026-05-09 | 2026-05-09 | — |
@ -95,4 +97,4 @@ Newest first. Update on every open/close.
## Next ID
`000032`
`000034`

View file

@ -0,0 +1,349 @@
# Ticket #000032 — combinatorics@v1 π*
**Status:** open · awaiting go/no-go
**Opened:** 2026-05-09
**Scope:** A new π* kernel that canonicalizes pure-integer
counting expressions — binomials, factorials, permutations,
partitions, Catalan, Bell, Stirling numbers — and **fails closed
on any input whose result is not a non-negative integer**. Tighter
domain than `algebra-symbolic@v1` (which already accepts the same
input surface but happily returns symbolic / negative / rational
results).
**Audience:** maintainers of arborist's π* layer + downstream
consumers (canonical-projection witness, math/logic preflight,
benchmark batteries, claim-pack pillar VII if #000033 lands).
**Hard constraint:** **fail-closed integer discipline.** Any input
whose canonical SymPy reduction is not a `sp.Integer ≥ 0` raises
`PiStarError`. This is the distinguishing feature versus
`algebra-symbolic@v1`. Operators choose the kernel by what they
want rejected, not by what they want accepted.
---
## 1. Problem statement
Today, combinatorial primitives (`binomial(5, 2)`, `factorial(7)`,
`catalan(5)`, etc.) already canonicalize through
`algebra-symbolic@v1` because SymPy understands them as
expressions. Confirmed in #000030 Phase 1+2 commit:
```
binomial(5,2) → Integer(10)
factorial(7) → Integer(5040)
3*binomial(5,2) + factorial(4) → Integer(54)
binomial(n,k) → binomial(Symbol('n'), Symbol('k')) ← symbolic
binomial(-3, 2) → Integer(6) ← negative-arg accepted
```
This works — but it accepts inputs that combinatorial-counting
semantics should reject:
1. **Symbolic results** (`binomial(n,k)`) — counting only makes
sense once n,k are bound to concrete non-negative integers.
`algebra-symbolic@v1` returns the symbolic form unchanged,
which silently moves "the question is unanswerable" into
"the answer is this opaque expression." That's a false
confidence the witness flow can't catch without a separate
integer assertion.
2. **Generalized binomials** (`binomial(-3, 2) = 6`,
`binomial(0.5, 3) = 0.0625`) — SymPy's combinatorial
functions extend to negative integers, rationals, and complex
numbers via the Gamma function. The CLASSICAL counting
interpretation rejects all of these. A counting kernel
should fail closed.
3. **Composability with `arithmetic@v1`.** The output bytes of
`algebra-symbolic@v1` are `srepr(Integer(10))`. The output
bytes of `arithmetic@v1` are `b"10/1"`. Two callers asking
"how many ways to choose 2 from 5?" via different routes get
different canonical bytes for the same answer. A
combinatorics kernel that emits `b"10"` (or `arithmetic@v1`-
compatible `b"10/1"`) closes that discrepancy.
The witness flow (#000028) becomes more useful when modalities
agree on the SHAPE of the answer. STRICT-WITNESSED for "how many
ways to choose 2 from 5" should not depend on which kernel the
preflight happened to dispatch to.
## 2. Design choices
### 2.1 Output format
**A. Integer string (RECOMMENDED).** ``b"10"``, ``b"5040"``.
Compact, human-readable, and `arithmetic@v1`'s
``"<num>/<den>"`` recipe accepts it as ``10/1`` after one
re-canonicalization. Cross-modality agreement with
`arithmetic@v1` is one canonicalization step away — the
multi-modality witness can pin them as the same equivalence
class via composition.
**B. SymPy srepr integer.** ``b"Integer(10)"``. Matches the
algebra-symbolic@v1 fast-path output. Less readable; requires
SymPy to re-parse for any downstream comparison. Loses the
"witness can pin equivalence with arithmetic@v1" argument.
**C. Rational form.** ``b"10/1"`` via the existing
`arithmetic@v1` recipe. Bytes-identical to what
`arithmetic@v1` would output. Cleanest cross-kernel
agreement. Costs a denominator on every output (visual
clutter for pure counts).
**A.** Compact, distinguishes counting outputs from rational
arithmetic at the byte level (`b"10"` vs `b"10/1"`),
canonicalizes round-trip-cleanly through `arithmetic@v1` if
operators want bytes-identical agreement.
### 2.2 Allowed input surface
Same parser as `algebra-symbolic@v1` (SymPy `sympify`); the
domain narrowing happens at the OUTPUT stage. Inputs that the
parser accepts but the kernel rejects:
- Result is symbolic (any free symbols remain): reject.
- Result is non-integer: reject.
- Result is negative integer: reject (counting-domain rule;
generalized binomial doesn't qualify).
Inputs the parser already rejects (PiStarError from sympify,
syntax error, relational/boolean): reject same as
`algebra-symbolic@v1`.
### 2.3 Composition
`combinatorics@v1` outputs bytes that look like a non-negative
integer. The natural composition target is `arithmetic@v1`:
```python
from arborist.pi_star import compose
# combinatorics@v1 output "10" → arithmetic@v1 reads as 10 → "10/1"
chain = compose("combinatorics@v1", "arithmetic@v1")
chain.canonicalize(b"binomial(5,2)") == b"10/1"
```
Auto-registers as `combinatorics-then-arithmetic@v1` per the
existing composition algebra. The witness flow can use this
composition to pin equivalence-class agreement between
combinatorial and rational answers.
### 2.4 Preflight routing
Algebra route already accepts inputs like `binomial(5,2)` and
returns `Integer(10)`. Adding a combinatorics route ahead of
algebra would require a sniff that distinguishes counting
expressions (`binomial`, `factorial`, …) from general algebra.
Two options:
**A. Don't wire to preflight.** Let `algebra-symbolic@v1` keep
catching combinatorial inputs at the preflight layer. Operators
who want the tighter integer discipline call
`combinatorics@v1` directly (or via composition). This preserves
the existing preflight order; no new sniff complexity.
**B. Add a combinatorics sniff.** Detect known combinatorial
function names (`binomial`, `factorial`, `catalan`, `bell`,
`partition`, `stirling`) at the start of the input and route
accordingly. Adds a new regex + branch.
**A.** Keep preflight simple. The kernel exists to enforce
discipline at call sites that want it; the preflight layer
already works for the question-shape case via algebra.
### 2.5 Allowed function set
SymPy combinatorial primitives that produce non-negative integer
outputs on integer inputs:
| Name (SymPy) | Input | Output |
|---------------------------------------------------|--------------------|--------|
| ``sp.binomial(n, k)`` | n, k integers ≥ 0 | C(n, k), 0 if k > n |
| ``sp.factorial(n)`` | n integer ≥ 0 | n! |
| ``sp.ff(x, k)`` (falling factorial) | x, k integers ≥ 0 | x·(x-1)…(x-k+1) |
| ``sp.rf(x, k)`` (rising factorial / Pochhammer) | x, k integers ≥ 0 | x·(x+1)…(x+k-1) |
| ``sp.catalan(n)`` | n integer ≥ 0 | n-th Catalan |
| ``sp.bell(n)`` | n integer ≥ 0 | n-th Bell |
| ``sp.functions.combinatorial.numbers.partition(n)`` | n integer ≥ 0 | p(n) |
| ``sp.functions.combinatorial.numbers.stirling(n, k)`` | n, k integers ≥ 0 | S2(n, k) |
These are all addressable by name through SymPy's standard
parser; users write `binomial(5,2)`, `partition(7)` etc. directly.
Operators with arithmetic compositions (e.g.
`3*binomial(5,2) + factorial(4)`) get a single integer output,
54 in this case.
## 3. Recommendation
Implement Phase 1 + Phase 2 together as one commit:
- **Phase 1**`arborist/pi_star/combinatorics.py` with the
`CombinatoricsV1` class, integer-only output discipline, and
registration. ~120 LOC.
- **Phase 2** — Tests covering integer-output cases (collapse),
symbolic rejection, negative rejection, generalized-binomial
rejection, composition with `arithmetic@v1`. Bench fixtures
pair (syntax + semantics). ~80 LOC tests + ~12 fixtures.
## 4. Implementation sketch
### 4.1 New file: `arborist/pi_star/combinatorics.py`
```python
try:
import sympy as sp
except ImportError:
sp = None
@dataclass
class CombinatoricsV1:
name: str = "combinatorics"
version: str = "v1"
domain: str = "combinatorics"
def canonicalize(self, raw: bytes) -> bytes:
if sp is None:
raise PiStarError("requires sympy; pip install 'arborist[math]'")
# ... bytes/UTF-8/empty checks (mirror algebra_symbolic.py) ...
try:
expr = sp.sympify(text)
except (sp.SympifyError, SyntaxError, TypeError) as exc:
raise PiStarError(f"cannot parse {text!r}: {exc}") from exc
if not isinstance(expr, sp.Expr):
raise PiStarError(f"rejects non-expression {text!r}")
# Reduce — sp.simplify on combinatorial primitives evaluates
# them to integer literals (or leaves them symbolic).
try:
reduced = sp.simplify(expr)
except (TypeError, ValueError) as exc:
raise PiStarError(f"simplify failed: {exc}") from exc
# Domain check: must be a non-negative concrete integer.
if not isinstance(reduced, sp.Integer):
raise PiStarError(
f"combinatorics@v1 result is not a concrete integer: "
f"{reduced!r}"
)
if reduced < 0:
raise PiStarError(
f"combinatorics@v1 result is negative: {int(reduced)}"
)
return str(int(reduced)).encode("utf-8")
if sp is not None:
register(CombinatoricsV1())
```
### 4.2 Tests (`tests/test_pi_star_combinatorics.py`)
```python
sympy = pytest.importorskip("sympy")
def test_basic_counts(ps):
assert ps.canonicalize(b"binomial(5,2)") == b"10"
assert ps.canonicalize(b"factorial(7)") == b"5040"
assert ps.canonicalize(b"catalan(5)") == b"42"
assert ps.canonicalize(b"bell(5)") == b"52"
assert ps.canonicalize(b"partition(7)") == b"15"
def test_arithmetic_composition_inside_input(ps):
# Mixing counting + arithmetic still must reduce to integer.
assert ps.canonicalize(b"3*binomial(5,2) + factorial(4)") == b"54"
def test_symbolic_input_rejected(ps):
with pytest.raises(PiStarError, match="not a concrete integer"):
ps.canonicalize(b"binomial(n, k)")
def test_negative_result_rejected(ps):
# Hand-crafted: 5 - factorial(4) = -19 → counting domain rejects.
with pytest.raises(PiStarError, match="negative"):
ps.canonicalize(b"5 - factorial(4)")
def test_non_integer_result_rejected(ps):
# Generalized binomial(0.5, 3) = 0.0625 — SymPy supports it,
# combinatorics@v1 rejects.
with pytest.raises(PiStarError, match="not a concrete integer"):
ps.canonicalize(b"binomial(Rational(1,2), 3)")
def test_composes_with_arithmetic(ps):
from arborist.pi_star import compose
chain = compose("combinatorics@v1", "arithmetic@v1")
assert chain.canonicalize(b"binomial(5, 2)") == b"10/1"
```
### 4.3 Bench fixtures
`bench/fixtures/5s/syntax-combinatorics-v1.jsonl`
10 inputs that produce non-negative integers (parse-pass).
`bench/fixtures/5s/semantics-combinatorics-v1.jsonl`
12 equivalence-class fixtures:
- `binomial(5, 2)``10`
- `binomial(5, 3)``binomial(5, 2)` (symmetry)
- `factorial(0)``1`
- `binomial(7, 0)``binomial(7, 7)``1`
- distinct: `factorial(5)``factorial(6)`, etc.
### 4.4 Carrier whitelist + Makefile
`bench/batteries/base.py PHASE_1_CARRIERS` gains
`"combinatorics"`. `Makefile` gains `bench-5s-combinatorics`.
## 5. Hard constraints (re-stated)
1. **Fail-closed integer discipline.** Any input whose reduction
is not a non-negative `sp.Integer` raises `PiStarError`. No
silently-symbolic outputs. No negative-counting outputs. No
rational/float outputs.
2. **Optional dependency.** Same pattern as `algebra-symbolic@v1`:
`try/except` import, register only when sympy is present, tests
gate on `pytest.importorskip("sympy")`.
3. **No cache_key invariant changes.** Schema, chunker,
canonicalization versions stay pinned. New π* registers a new
key (`combinatorics@v1`); existing cache rows unaffected.
4. **No preflight wiring.** The kernel is direct-call; the
preflight algebra route already catches counting-shaped inputs
without a sniff change.
## 6. Risks / things to watch
- **`sp.simplify` cost.** Same risk as
`algebra-symbolic-simplified@v1`: pathological inputs can grow
exponentially. Combinatorial primitives are usually fast (≤ 10
ms even for `partition(1000)`), but composition with
`algebra-symbolic` shapes can hit the slow path. No in-π*
timeout in v1 (matches Phase 1b); operators size budget at
call sites.
- **`stirling(n, k)` ambiguity.** SymPy distinguishes Stirling
numbers of the first vs second kind via a kwarg
(`stirling(n, k, kind=1)`). The default is second kind. Document
in module docstring; fixtures pin the kind explicitly.
- **`partition` namespace.** `sp.partition` exists at
`sp.functions.combinatorial.numbers.partition` but NOT on the
top-level `sp.` namespace as a standalone callable in some
SymPy versions. Verify `sympify("partition(7)")` resolves
consistently across SymPy ≥ 1.13; fall back to the longer
`sp.functions...` path inside the parser's `local_dict` if
needed.
- **Catalan-number test fragility.** Some SymPy versions return
`catalan(5) → 42` directly; older versions might return an
unevaluated `catalan(5)` Function call. Pin the version
expectation in `[math]` extra (`sympy>=1.13`).
## 7. Forward links
- **#000030** — Math π* expansion (SymPy substrate). This ticket
is its sibling, narrower-domain.
- **#000033** — Claim-pack pillar VII (combinatorics). If both
land, the pillar's records cite this kernel as its formal
projection (analogous to how Phase III arithmetic theorems
cite `arithmetic@v1`).
- **#000028** — Multi-modality witness. Combinatorial questions
become STRICT-WITNESSED-eligible once the kernel + the algebra
preflight produce equivalent canonical forms via composition.
## 8. Status
Open · awaiting go/no-go.
Estimated size: ~120 LOC module + ~80 LOC tests + ~22 fixtures +
~5 LOC carrier-whitelist + ~5 LOC Makefile. Single-commit feasible
alongside #000033 if both land together; otherwise standalone.

View file

@ -0,0 +1,359 @@
# Ticket #000033 — Claim-pack pillar VII (combinatorics)
**Status:** open · awaiting go/no-go
**Opened:** 2026-05-09
**Scope:** Extend the `claim_pack` source (#000029) with a new
combinatorics pillar (proposed numbering: VII, slotting between
classical physics VI and λ-Calculus IX). The pillar carries
counting-domain axioms (binomial coefficients, factorial,
Pascal's rule, addition/multiplication principles) and theorems
(inclusion-exclusion, pigeonhole, binomial theorem, generating
functions). Each record follows the existing v2-style dual-
threaded shape (Δ symbolic + ∇ verbose) and cites a stable
combinatorics text. Companion to #000032 (combinatorics@v1 π*).
**Audience:** maintainers of arborist's claim-pack source +
anyone running QA on combinatorial questions ("how many ways…",
"prove the binomial theorem", "what is the inclusion-exclusion
principle").
**Hard constraint:** **bundle provenance is explicit.** The
existing v2 bundles are Grok-4-generated artifacts with
documented authorship metadata. A combinatorics pillar must come
from a comparable provenance: either a NEW LLM-generated bundle
(with the LLM model + run timestamp + seed all recorded) OR a
hand-curated bundle (with curator name + sources + curation date
recorded). **No silent invention.** Same audit discipline that
`#000029` documented for the existing axioms.
---
## 1. Problem statement
Today the claim-pack source (`#000029`) ingests two companion
JSONs covering 7 pillars. Pillar VII is missing — the existing
bundles use a Roman-numeral progression I → II → III → IV → V →
VI → IX, deliberately leaving VII (and VIII) un-numbered for
future extension. The combinatorics gap is real:
- **No counting axioms.** Pascal's rule (`C(n,k) = C(n-1,k-1) +
C(n-1,k)`), addition principle, multiplication principle, the
pigeonhole foundational claim — none are present.
- **One combinatorics-flavored theorem in pillar V**
Inclusion-Exclusion Principle (cited to Kolmogorov 1933).
Treated as a probability theorem, not a counting theorem.
That's correct framing for the probability pillar, but it
leaves the counting half of the I-E principle (set theory of
finite unions) without a home.
- **Combinatorics is a claim-pack-friendly domain.** Counting
identities have classical proofs, are formally stated as
closed expressions, and have a deep textbook tradition
(Riordan 1958, Comtet 1974, Stanley 1986, Aigner 2007, Wilf
generatingfunctionology 1990, Brualdi 2009). Plenty of
authoritative source citations.
A claim-pack pillar VII for combinatorics gives:
1. **Retrieval coverage** for combinatorial questions when an
operator runs claim-pack-augmented queries.
2. **Cross-pillar edges** — Pascal's rule connects to pillar III
(arithmetic) via successor + addition; the binomial theorem
connects to pillar I (logic) via finite induction.
3. **A natural target for `combinatorics@v1` π* (#000032).**
Each pillar VII record can carry a `pi_star_ref` pointing at
the kernel; the witness flow (#000028) becomes computable on
counting questions.
## 2. Design choices
### 2.1 Bundle provenance — where does the JSON come from
The existing v2 bundles cite themselves as:
```json
"identity": "Grok 4, operating as the GOD AI 'Prometheus' Maths Engine"
"deterministic_seed": 42
"updated": "2025-07-11T12:00:00Z"
```
We have three honest options for pillar VII provenance:
**A. Commission a Grok-4 v3 bundle (RECOMMENDED FOR PARITY).**
Run a prompt against Grok 4 (or whatever the current generation
is in 2026-05) requesting an additional pillar VII to extend the
existing v2 bundles. Same prompt template, same seed
discipline. Pro: identical authorship provenance to the rest of
the pack; no shape divergence. Con: requires access to Grok 4,
or substitute model with documented divergence note.
**B. Hand-curate from established textbooks** (Stanley *Enumerative
Combinatorics*, Brualdi *Introductory Combinatorics*, Wilf
*generatingfunctionology*). Pro: canonical sources, audit-grade
citations, fox owns the process end-to-end. Con: substantially
more time investment per record (~30-60 min/axiom for
high-quality dual-threaded text); pillar VII would feel less
"of-a-piece" with the LLM-generated rest.
**C. Hybrid — LLM draft, human curation.** Use a Grok-4 / Hermes
draft as the seed, then curate by hand against textbook
citations. Pro: balances speed with citation rigor. Con: the
authorship metadata becomes ambiguous ("LLM with human
edits" is a fuzzy provenance label).
→ Default to **A** if Grok-4 access is straightforward; otherwise
**C** with explicit "human-curated from LLM draft, validated
against [list of textbook citations]" provenance metadata. **B**
is the fallback if both LLM access and curation budget are
unavailable.
### 2.2 Pillar numbering
The existing pack uses I, II, III, IV, V, VI, IX. There's a
2-pillar gap (VII, VIII) where this ticket and a future one
could land. Two questions:
- **Should this pillar be VII or some other number?** The Roman-
numeral progression in the v2 bundles is documented as
reserving VII / VIII for "future pillars" without specifying
what — we get to choose. **VII** (combinatorics) is natural,
positioning it between physics (VI) and λ-Calculus (IX). VIII
stays open for whatever lands next (number theory? graph
theory? topology?).
- **Should re-numbering be considered?** No — the v2 bundles are
shipped artifacts in fox's `~/Downloads`; renumbering would
break references at runtime. New pillars get new numbers, no
mutation of existing ones.
### 2.3 Axiom set (proposal)
Foundational counting axioms — minimal set that supports the
classical theorems in §2.4:
| # | Axiom | Δ form | Source |
|---|-------|--------|--------|
| 1 | Addition Principle | If A, B disjoint finite, A B = A + B | Brualdi §1 / Stanley I.1 |
| 2 | Multiplication Principle | A × B = A · B | Brualdi §1 / Stanley I.1 |
| 3 | Pigeonhole | If n+1 objects in n boxes, some box has ≥ 2 | Dirichlet 1834 / Brualdi §3 |
| 4 | Definition of Factorial | 0! = 1 ; n! = n · (n-1)! | Standard / Stanley §1.1 |
| 5 | Definition of Binomial | C(n, k) = n! / (k! (n-k)!) | Standard / Knuth TAOCP §1.2 |
| 6 | Pascal's Rule (axiom shape) | C(n,k) = C(n-1,k-1) + C(n-1,k) | Pascal 1654 / Brualdi §5 |
| 7 | Symmetry of Binomial | C(n,k) = C(n,n-k) | Standard |
Six to seven axioms keeps pillar size comparable to the existing
pillars (V has 3 axioms + Kolmogorov's 3rd as fundamental;
III has 9 Peano-style; IV has 17 Hilbert-style).
### 2.4 Theorem set (proposal)
Classical results that the axioms support:
| # | Theorem | Δ form | Source |
|---|---------|--------|--------|
| 1 | Binomial Theorem | (a+b)^n = Σ C(n,k) a^(n-k) b^k | Newton 1665 / Stanley §1.5 |
| 2 | Inclusion-Exclusion (counting form) | A_i = Σ A_i - Σ A_i ∩ A_j + … | Da Silva / Sylvester / Brualdi §6 |
| 3 | Pigeonhole — strong form | n objects in k boxes ⇒ some box has ⌈n/k⌉ | Brualdi §3 |
| 4 | Vandermonde's Identity | C(m+n, k) = Σ C(m,i) C(n,k-i) | Vandermonde 1772 |
| 5 | Hockey-Stick Identity | Σ C(i, k) for i=k..n = C(n+1, k+1) | Standard / Knuth |
| 6 | Catalan numbers — closed form | C_n = C(2n, n) / (n+1) | Catalan 1838 |
| 7 | Stars-and-Bars | Number of weak compositions of n into k parts = C(n+k-1, k-1) | Standard |
Seven theorems lines up with what the existing pillars carry
(I has 4, II has 2, III has 4, IV has 2, V has 2, VI has 2,
IX has 7).
### 2.5 Cross-pillar edges
`provenance.references` of pillar VII would point at:
- Pillar III (arithmetic): Pascal's rule recurrence uses
successor + addition.
- Pillar I (logic): Inclusion-exclusion proof uses De Morgan's
laws + finite induction.
- Pillar II (set theory): finite union/intersection axioms support
the addition principle.
- Pillar V (probability): I-E principle in counting form is the
classical case of the probability-theory I-E.
Pillar VII's outbound edges would be ~4 references at the
provenance level, matching the density of existing pillars'
references.
### 2.6 π* binding
Each axiom + theorem record carries a `pi_star_ref` field
identifying the formal projection it canonicalizes to:
- Identity-shaped records (e.g., `binomial(n,k) = n! / (k! (n-k)!)`):
`pi_star_ref: "algebra-symbolic@v1"` (the identity holds in
the polynomial-canonical equivalence class).
- Concrete-count examples (e.g., `binomial(5, 2) = 10`): →
`pi_star_ref: "combinatorics@v1"` if `#000032` lands;
otherwise `algebra-symbolic@v1`.
Pillar VII landing AFTER `#000032` lets the pillar use the
tighter kernel from the start. Pillar VII landing FIRST means
the records start with `algebra-symbolic@v1` and rebind to
`combinatorics@v1` post-#000032; that's a re-canonicalize step
which would invalidate any cache rows pinned to the old hash.
**Land #000032 first** to avoid the rebind churn.
## 3. Recommendation
Sequence:
1. **#000032 first** — combinatorics@v1 π* kernel. Cleanest
integer-output discipline lands without any pillar VII
coupling.
2. **#000033 next** — author the pillar VII JSON (option A:
Grok-4 v3 bundle if accessible; option C: hybrid; option B:
hand-curate as fallback). Produce
`pillar-vii-combinatorics-v1.json` (axioms) and
`pillar-vii-combinatorics-theorems-v1.json` (theorems) under
`~/.arborist/claim-packs/` (or wherever fox prefers; not
committed to repo unless small).
3. **Ingest** via the existing `ClaimPackSource` — it already
accepts arbitrary pillar names; no source-code changes
needed.
If Grok-4 access is the binding constraint, fall back to
**option B** (hand-curate) or **option C** (hybrid). The pillar
content matters more than the authorship label; we just have
to record which path we took.
## 4. Implementation sketch
### 4.1 Bundle authoring
Whichever provenance path we pick, the output is two JSON files
that mirror the existing v2 shape:
```jsonc
// pillar-vii-combinatorics-v1.json
{
"metadata": {
"version": "1.0.0",
"pillar_id": "VII",
"authorship": "...", // "Grok-4 ..." | "hand-curated by ..." | "hybrid: LLM-draft + human-curation"
"sources": [...], // list of textbook citations validated against
"deterministic_seed": ...,
"created": "2026-05-...",
"ingest_target": "claim_pack@v1"
},
"pillars": {
"VII": {
"title": "Combinatorics axioms (counting principles)",
"description": "...",
"provenance": {
"delta": "...",
"references": [
"axiomsg4.json:pillar.III.peano.successor",
"axiomsg4.json:pillar.II.zf.union",
"theoremg4.json:pillar.I.logic.deMorgan"
]
},
"axioms": [
{ "name": "Addition Principle", "runicLabel": "...",
"delta": "|A B| = |A| + |B| (when A ∩ B = ∅)",
"nablaVerbose": "If two finite sets share no elements, ...",
... }
// 6 more axioms
]
}
}
}
```
### 4.2 No source-code changes needed
`arborist/sources/claim_pack.py` (#000029) already iterates any
pillar found in the bundle. New pillars register as documents
automatically. Adding pillar VII = adding two JSON files to the
ingest path; everything else flows through existing
infrastructure.
### 4.3 Tests / validation
The existing `tests/test_claim_pack.py` covers the source's
parsing + edge-emission behavior. Pillar VII inherits all of
that; no new test machinery needed at the source layer.
What IS new: a small **manifest-content** test that asserts the
new JSON files parse cleanly via the lenient parser, the axiom
+ theorem counts match expectation, and the pillar has the
documented cross-pillar references.
### 4.4 Bench fixtures
Once pillar VII ingests, the bench-emergent battery (#000006)
gains a target for combinatorial questions. No new fixtures in
this ticket; downstream bench tickets pick that up.
## 5. Hard constraints (re-stated)
1. **Bundle provenance is explicit.** Either
"Grok-4 v3 generation, model-id, seed, timestamp" OR
"hand-curated by [name], sources [list], date [YYYY-MM-DD]"
OR "hybrid: LLM-draft + human curation, sources [list]".
No silent authorship.
2. **No re-numbering of existing pillars.** Pillar VII slots
into the documented gap; existing references stay valid.
3. **No retroactive changes to claim-pack records already in
shards.** New pillar = new documents = additive only. Cache
key invariants untouched.
4. **#000032 lands first.** Avoids rebind churn on
`pi_star_ref` fields; pillar VII records ship with the
tighter kernel reference from day one.
## 6. Risks / things to watch
- **Authorship-metadata consistency.** The v2 bundles' metadata
shape becomes load-bearing once we extend it. If we change
`authorship` from a string to a structured object, every
downstream consumer that reads the field has to know about
both shapes. Recommend: add `authorship` as a structured
field on the new bundle's metadata, document the schema, and
treat the v2 string field as a legacy alias.
- **Citation density.** Combinatorics has many overlapping
classical sources (Knuth TAOCP, Brualdi, Stanley, Wilf, Comtet,
Riordan). Pick ONE primary citation per record; multi-source
citations dilute the warrant resolution layer (#000031).
- **Symbol notation drift.** "C(n, k)" vs "binomial(n, k)" vs
"n choose k" notation matters at retrieval time. The Δ field
pins ONE notation. Pick `\binom{n}{k}` LaTeX consistent with
the existing pillar III arithmetic notation; the ∇ field
re-expresses in prose.
- **Pillar VIII placeholder.** Leaving VIII open for a future
pillar (e.g., number theory, graph theory) is fine; do NOT
pre-allocate or stub.
- **LLM availability.** Option A depends on Grok-4 (or successor)
access. If that's not available, fall back without re-opening
the ticket; document the substitution in the bundle's
authorship field.
## 7. Forward links
- **#000029** — claim-pack source. This ticket extends it.
- **#000032** — combinatorics@v1 π*. Kernel that pillar VII
records bind to via `pi_star_ref`. Lands FIRST.
- **#000031** — surface-ingest cited textbooks. If pillar VII
cites textbooks (Brualdi, Stanley, Knuth, etc.), those become
candidates for the textbook-ingest pipeline. Mostly
proprietary — yellow-light per #000031's license discipline.
- **#000028** — multi-modality witness. Pillar VII records that
bind to `combinatorics@v1` become STRICT-WITNESSED-eligible
on counting questions.
## 8. Status
Open · awaiting go/no-go.
Estimated size:
- Authoring effort: 4-12 hours depending on provenance path
(option A fastest if Grok-4 access available; option B
longest at hand-curation tempo; option C in between).
- Code: ~30 LOC manifest-content test. No source-code changes
in `arborist/sources/claim_pack.py`.
- Data: 2 JSON files (~100-200 KB total based on v2 sizing).
Stored under `~/.arborist/claim-packs/` or committed to repo
under `bench/fixtures/claim-packs/` if size is small.
- Bench: 0 LOC in this ticket; downstream bench tickets pick
up combinatorial fixtures separately.