feat(vocab): LIVE vocab-currency GovernedLoop — LSA↔LDA currency, governed (task #13) - #255
Conversation
…pus) currency (task #13) Makes the vocabulary-currency loop live and GOVERNED by the merged GovernedLoop contract. The approved glossary is the fixed set (LSA), the corpus token distribution is the open set (LDA), and uncovered probability mass is the currency signal (the LSI drive — new fields that became vocab but aren't connected). Remediation connects the highest-mass uncovered term, strictly decreasing divergence (monotone-decrease is real). The runner reads bound + tolerance + onNonConvergence + admission FROM the contract and obeys them. Fail-closed teeth (asserted by validate-vocab-currency-loop, wired into make validate): - convergent corpus reaches currency (ok); - a domain the vocab can't name within the bound ESCALATES-human, never silently passes, never spins past maxIterations; - a loop with no superconscious admission is REFUSED (loops don't self-authorize). Emits candidateNewVocab for routing into ontogenesis/prophet-ontology. Dependency-free.
The flag gated the per-iteration trace, not the candidate list (candidateNewVocab is always emitted), so the name misdescribed its effect. Renamed to --trace.
There was a problem hiding this comment.
🟡 Not ready to approve
The loop runner can crash or behave inconsistently with the contract because it doesn’t handle convergence.tolerance: null (schema-allowed) and doesn’t enforce convergence.measure compatibility.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
Adds a “live” vocab-currency loop runner and CI harness that instantiate the GovernedLoop contract for measuring glossary↔corpus divergence (uncovered token mass) and enforcing fail-closed governance behavior, then wires it into make validate with fixtures and brief spec/docs.
Changes:
- Added
tools/vocab_currency_loop.pyrunner that reads loop bounds/tolerance/handler/admission from aGovernedLoopdocument and produces a currency/escalation result (+ candidate term list). - Added
tools/validate_vocab_currency_loop.pyharness plusfixtures/vocab-currency/*to assert convergent, divergent (fail-closed), and unadmitted behavior. - Documented the loop (
specs/vocab-currency-loop.md) and surfaced it inCHANGELOG.md; wired avalidate-vocab-currency-looptarget intoMakefile.
File summaries
| File | Description |
|---|---|
| tools/vocab_currency_loop.py | Implements the governed vocab-currency loop runner (tokenization, divergence, bounded remediation, fail-closed result). |
| tools/validate_vocab_currency_loop.py | Adds a CI/make harness asserting converge/escalate/refuse behaviors for the runner. |
| specs/vocab-currency-loop.md | Normative/spec note describing the loop model and governance properties. |
| Makefile | Adds validate-vocab-currency-loop target and includes it under validate. |
| fixtures/vocab-currency/glossary.json | Minimal glossary fixture (approved vs draft term) used as the “fixed set”. |
| fixtures/vocab-currency/corpus.json | Convergent corpus fixture expected to reach tolerance within the bound. |
| fixtures/vocab-currency/corpus_divergent.json | Divergent corpus fixture expected to fail-closed (escalate) within the bound. |
| CHANGELOG.md | Adds an Unreleased entry describing the new loop/tooling and validation target. |
Review details
- Files reviewed: 8/8 changed files
- Comments generated: 2
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
| max_iter = loop["bound"]["maxIterations"] | ||
| tolerance = loop["convergence"].get("tolerance", 0.0) | ||
| on_nonconv = loop["onNonConvergence"] | ||
|
|
| def run(corpus_name: str, loop_override: dict | None = None) -> dict: | ||
| loop = loop_override or vcl.load(LOOP) | ||
| return vcl.run_loop(loop, vcl.load(FIX / "glossary.json"), vcl.load(FIX / corpus_name)) |
…olerance + conformance-first - run_loop now REFUSES a contract whose convergence.measure this runner doesn't implement (only monotone-decrease/error-below-tolerance; a 'fixpoint' contract is refused rather than run with mismatched semantics — don't honor a guarantee you don't provide). - convergence.tolerance may be null per schema; treat null as 0.0 (must fully cover) instead of crashing on 'D <= None'. - the CI harness now schema-validates the shipped GovernedLoop contract FIRST (like the repo's other validators), so contract drift fails with a clear conformance error not a KeyError. - added two teeth: contract:conforms and unsupported-measure:refused. All 5 pass.
The vocab-currency loop, made live and governed
Instantiates the merged
GovernedLoopcontract (#253) as a running loop. Vocabulary is the governance substrate — if the approved glossary doesn't name what the estate does, we can't reason about governance. Currency can't be a one-shot DAG (the estate moves), so it's a loop; and a loop is admissible only when governed, so this runner is governed by the contract.GlossaryTerms (a draft term doesn't regulate state → doesn't count).Q— what the estate actually discusses.Σ Q(t)(the LSI drive: new fields that became vocab but aren't connected).GlossaryTerm) →Ddrops by exactlyQ(t), strictly monotone, somonotone-decreaseconvergence is real.The runner reads
bound.maxIterations,convergence.tolerance,onNonConvergence, andadmissionfrom the contract and obeys them — the contract governs the runtime.Fail-closed teeth (
make validate-vocab-currency-loop, inmake validate)maxIterationsadmission.superconsciousRef→ refused (loops don't self-authorize)Emits
candidateNewVocab(ranked unnamed terms) for routing into ontogenesis / the prophet-ontology as draft terms for the 3-method alignment pass. Dependency-free (stdlib + jsonschema).Ties: GovernedLoop contract (#253), vocabulary-as-governance-substrate, loops-vs-graphs doctrine.