Skip to content

feat(vocab): emit conformant draft GlossaryTerms from the currency loop (task #13) - #256

Merged
mdheller merged 2 commits into
mainfrom
feat/vocab-loop-draft-emission
Aug 2, 2026
Merged

feat(vocab): emit conformant draft GlossaryTerms from the currency loop (task #13)#256
mdheller merged 2 commits into
mainfrom
feat/vocab-loop-draft-emission

Conversation

@mdheller

@mdheller mdheller commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Close the currency → proposal lifecycle

Builds on the merged vocab-currency loop (#255). The loop detected divergence and named the unnamed terms; now it emits them as artifacts ontogenesis can ingest.

Each remediation step emits a conformant status:draft GlossaryTerm in result.proposedTerms for the token it connects. The loop proposes onlypartOfSpeech, alignment, and approval are the downstream 3-method pass; status stays draft, so the loop never self-approves.

Teeth (make validate-vocab-currency-loop, now 6)

  • new: every proposed term must conform to GlossaryTerm.json and be status:draft — the loop may not push malformed or self-approved vocab into the glossary.
  • plus the existing 5 (contract conforms, converges, escalates fail-closed, refuses unadmitted, refuses unsupported measure).

Sample emitted artifact:

{ "id": "urn:srcos:glossary:quarantine", "type": "GlossaryTerm", "specVersion": "2.0.0",
  "name": "quarantine", "definition": "Proposed by vocab-currency loop …", "status": "draft" }

This is the ontogenesis on-ramp: currency detection (#255) → conformant draft proposals (here) → 3-method alignment (downstream). Dependency-free.

…op (task #13)

Closes the currency→proposal lifecycle. Each remediation step now emits a status:draft
GlossaryTerm artifact (result.proposedTerms) for the token it connects — directly ingestible
by ontogenesis for the 3-method alignment pass. The loop PROPOSES only: partOfSpeech, alignment,
and approval are downstream; status stays draft (the loop never self-approves). The CI harness
refuses any proposed term that doesn't conform to GlossaryTerm.json or that isn't status:draft,
so the loop can't push malformed or self-approved vocab into the glossary. 6 teeth.
Copilot AI review requested due to automatic review settings August 2, 2026 22:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the LIVE vocab-currency GovernedLoop to emit remediation artifacts as conformant GlossaryTerm draft proposals (result.proposedTerms), closing the currency → proposal lifecycle so downstream ontogenesis can ingest the loop’s outputs without the loop self-approving terms.

Changes:

  • Add proposed_term(...) generation and include emitted draft GlossaryTerm artifacts in result.proposedTerms (and per-connected token metadata).
  • Harden CI validation to require every emitted proposal conforms to schemas/GlossaryTerm.json and has status: "draft".
  • Document the emitted remediation artifacts in the vocab-currency loop spec and changelog.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
tools/vocab_currency_loop.py Emits conformant draft GlossaryTerm proposal artifacts during each remediation step and surfaces them as result.proposedTerms.
tools/validate_vocab_currency_loop.py Adds a validator check to ensure emitted proposed terms conform to GlossaryTerm.json and remain status:draft.
specs/vocab-currency-loop.md Documents the new remediation artifact emission contract (result.proposedTerms).
CHANGELOG.md Records the new draft-term emission behavior and the added CI “tooth” enforcing schema conformance + draft status.

Comment on lines +58 to +69
gt = jsonschema.Draft202012Validator(vcl.load(GLOSSARY_SCHEMA))
proposals = r.get("proposedTerms", []) + run("corpus_divergent.json").get("proposedTerms", [])
bad = [(t.get("id"), e.message) for t in proposals for e in gt.iter_errors(t)]
self_approved = [t["id"] for t in proposals if t.get("status") != "draft"]
if bad:
FAILURES.append(f"proposed term(s) do not conform to GlossaryTerm.json: {bad[:3]}")
elif self_approved:
FAILURES.append(f"proposed term(s) not status:draft — the loop must not self-approve: {self_approved[:3]}")
elif not proposals:
FAILURES.append("expected the loop to emit proposed draft terms, got none")
else:
CHECKS["proposed-terms:conform-and-draft"] = True
…osal reports, not crashes (Copilot #256)

A proposal missing 'id' is exactly what the conformance check should surface; using t['id']
(computed before the 'if bad' branch) would KeyError-crash first. Use t.get('id').
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.

2 participants