Skip to content

feat(contracts): land New Hope + Slash Topics semantic-BI integration - #1129

Merged
mdheller merged 3 commits into
mainfrom
feat/land-newhope-slashtopics-integration
Jul 31, 2026
Merged

feat(contracts): land New Hope + Slash Topics semantic-BI integration#1129
mdheller merged 3 commits into
mainfrom
feat/land-newhope-slashtopics-integration

Conversation

@mdheller

Copy link
Copy Markdown
Member

What & why

Lands the New Hope × Slash Topics × Semantic BI integration into the platform and closes a real gap: slash-topics was referenced by the integration but never imported (new-hope, memory-mesh, semantic-serdes were). Sourced from the newhope-slash-topics-integration pack that previously lived only on a local machine (no remote).

Changes

  • Import slash-topics as a first-class pinned contractcontracts/imported/slash-topics/SOURCE_MANIFEST.yaml (pinned to 9037a91) + mirrored schema subset (SlashTopics pack v0.1, MembraneDecision v0.1/v0.2, Model Selection policy v0.1), parity with the existing imports.
  • Declare and enforce — added to IMPORT_MANIFEST.yaml and to validate_repo.py's required-manifest gate.
  • Integration specdocs/INTEGRATION_NewHope_SlashTopics_SemanticBI.md + contracts/imported/CANONICAL_SOURCES.yaml (single-source-of-truth registry).
  • Fixturesexamples/newhope-slash-topics/ (the 4 vertical-slice examples).
  • Self-contained CI gatetools/validate_newhope_slashtopics_integration.py (+ test) validates junk-freeness, import provenance/pins, schema invariants (MembraneDecision enum, encoder-disabled-by-default posture), and that fixtures validate against the mirrored schemas. Wired via .github/workflows/newhope-slashtopics-integration.yml.

Verification (local)

  • validate_newhope_slashtopics_integration.py → all 6 checks pass (rc=0)
  • pytest tools/tests/test_validate_newhope_slashtopics_integration.py → 2 passed
  • tools/validate_repo.py (umbrella) → OK: validate passed

Follow-on (not in this PR)

Standing up the runtime services for the event flow (Membrane → TopicProjection → Vectorization → Semantic BI lens). Adapters already exist (apps/knowledge-reason/service/new_hope_adapter.py, newHopeMembrane.ts, slashTopicsScope.ts); this PR lands the contracts they bind to.

Import slash-topics as a first-class pinned contract (parity with new-hope /
memory-mesh / semantic-serdes) and land the New Hope x Slash Topics integration
pack into the platform:

- contracts/imported/slash-topics/: SOURCE_MANIFEST (pinned 9037a91) + mirrored
  schema subset (SlashTopics pack, MembraneDecision v0.1/v0.2, Model Selection)
- IMPORT_MANIFEST + validate_repo.py: declare AND enforce the slash-topics import
- docs/INTEGRATION_NewHope_SlashTopics_SemanticBI.md + contracts/CANONICAL_SOURCES
- examples/newhope-slash-topics/: the 4 vertical-slice fixtures
- tools/validate_newhope_slashtopics_integration.py + test + CI workflow: a
  self-contained gate (schema invariants + fixtures validate against the mirror)

Closes the gap where slash-topics was referenced by the integration but never
imported. Validator, tests, and repo-wide validate_repo.py all green locally.
Copilot AI review requested due to automatic review settings July 30, 2026 19:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds the missing slash-topics imported contract and lands a self-contained CI validator to enforce the New Hope × Slash Topics × Semantic BI integration invariants.

Changes:

  • Adds slash-topics as a pinned imported contract (manifest + mirrored spec subset) and enforces its presence via repo validation.
  • Introduces a dedicated validator script + pytest coverage, and wires it into a new GitHub Actions workflow.
  • Adds integration docs and example fixtures to validate against mirrored schemas.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tools/validate_repo.py Enforces presence of the new slash-topics imported source manifest.
tools/validate_newhope_slashtopics_integration.py New integration validator (junk scan, provenance checks, invariants, fixture validation).
tools/tests/test_validate_newhope_slashtopics_integration.py Adds tests to ensure the integration validator passes and required assets exist.
examples/newhope-slash-topics/slash_topics_pack_min.example.json Adds minimal Slash Topics pack fixture.
examples/newhope-slash-topics/newhope_message_posted.example.json Adds New Hope carrier fixture for the vertical slice.
examples/newhope-slash-topics/membrane_decision_allow.example.json Adds MembraneDecision example fixture.
examples/newhope-slash-topics/embedding_receipt_lsi.example.json Adds embedding receipt fixture for the vertical slice.
docs/INTEGRATION_NewHope_SlashTopics_SemanticBI.md Documents the integration mapping, event flow, and safety posture.
contracts/imported/slash-topics/specs/SlashTopics_Schema_v0.1.json Mirrors Slash Topics pack schema subset into the repo.
contracts/imported/slash-topics/specs/Model_Selection_Policy_v0.1.json Mirrors model-selection policy artifact into the repo.
contracts/imported/slash-topics/specs/Membrane_Decision_v0.2.json Mirrors MembraneDecision v0.2 schema into the repo.
contracts/imported/slash-topics/specs/Membrane_Decision_v0.1.json Mirrors MembraneDecision v0.1 schema into the repo.
contracts/imported/slash-topics/SOURCE_MANIFEST.yaml Declares provenance/pin and mirrored objects for slash-topics.
contracts/imported/IMPORT_MANIFEST.yaml Registers slash-topics import entry and validation hooks.
contracts/imported/CANONICAL_SOURCES.yaml Adds canonical source registry defining ownership/mirroring rules.
.github/workflows/newhope-slashtopics-integration.yml Adds CI workflow to run the integration validator and its tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +68 to +75
manifest = yaml.safe_load(IMPORT_MANIFEST.read_text(encoding="utf-8"))
by_repo = {i.get("repo"): i for i in manifest.get("imports", [])}
for repo in ("SocioProphet/new-hope", "SocioProphet/slash-topics"):
entry = by_repo.get(repo)
if not entry:
fail(f"IMPORT_MANIFEST does not declare {repo}")
if not entry.get("pin"):
fail(f"IMPORT_MANIFEST entry for {repo} has no pin (provenance required)")
Comment on lines +112 to +114
Draft202012Validator(schema).validate(pack_example)
Draft202012Validator(md_schema).validate(md_example)
ok("Landed example fixtures validate against the mirrored Slash Topics schemas")
Comment on lines +109 to +113
pack_example = load_json(EXAMPLES / "slash_topics_pack_min.example.json")
md_example = load_json(EXAMPLES / "membrane_decision_allow.example.json")

Draft202012Validator(schema).validate(pack_example)
Draft202012Validator(md_schema).validate(md_example)
Comment on lines +48 to +49
- name: Install validator dependencies
run: pip install jsonschema pyyaml pytest
Comment on lines +37 to +39
def fail(msg: str) -> None:
print(f"[FAIL] {msg}", file=sys.stderr)
sys.exit(1)
…I deps (Copilot review #1129)

- assert_import_provenance: try/except on read/parse + validate YAML shape before use
- validate_examples: catch jsonschema ValidationError -> controlled [FAIL]; parse-check
  all 4 landed fixtures (schema-validate the 2 with mirrored slash-topics schemas)
- CI: pin jsonschema/PyYAML/pytest for reproducible runs
Copilot AI review requested due to automatic review settings July 30, 2026 23:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comments suppressed due to low confidence (3)

tools/validate_newhope_slashtopics_integration.py:35

  • The junk-artifact scan will not cover the docs/ directory because the docs entry in LANDED_PATHS is a file and the scan only runs for directories (if base.is_dir()). This means .DS_Store (or __MACOSX) under docs/ could slip through even though the docstring claims it checks all landed integration paths. Consider changing the docs entry to ROOT / \"docs\" (or ...md.parent) or extending the logic to scan base.parent when base is a file.
LANDED_PATHS = [SLASH, EXAMPLES, ROOT / "docs" / "INTEGRATION_NewHope_SlashTopics_SemanticBI.md"]

tools/validate_newhope_slashtopics_integration.py:62

  • The junk-artifact scan will not cover the docs/ directory because the docs entry in LANDED_PATHS is a file and the scan only runs for directories (if base.is_dir()). This means .DS_Store (or __MACOSX) under docs/ could slip through even though the docstring claims it checks all landed integration paths. Consider changing the docs entry to ROOT / \"docs\" (or ...md.parent) or extending the logic to scan base.parent when base is a file.
    for base in LANDED_PATHS:
        if base.is_dir():
            for p in base.rglob("*"):
                if p.name == ".DS_Store" or "__MACOSX" in p.parts:
                    junk.append(str(p.relative_to(ROOT)))

.github/workflows/newhope-slashtopics-integration.yml:49

  • The workflow pins Python packages but leaves python-version as 3.x, which can introduce breakage when GitHub Actions advances the default 3.x minor (and can undermine the stated reproducibility goal). Consider pinning a specific minor (e.g., 3.11/3.12) to make CI behavior stable over time.
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.x'

      - name: Install validator dependencies (pinned for reproducibility)
        run: pip install jsonschema==4.23.0 PyYAML==6.0.2 pytest==8.3.4

Comment thread contracts/imported/IMPORT_MANIFEST.yaml Outdated
Comment on lines +44 to +49
local_path: contracts/imported/slash-topics/
required_objects:
- SlashTopics_Schema_v0.1.json
- Membrane_Decision_v0.1.json
- Membrane_Decision_v0.2.json
- Model_Selection_Policy_v0.1.json
…rce them (Copilot #1129)

- IMPORT_MANIFEST required_objects now list the real specs/ paths (were bare
  basenames; would not resolve relative to local_path)
- validator now asserts each slash-topics required_object exists under local_path
  (declared AND enforced)
Copilot AI review requested due to automatic review settings July 31, 2026 00:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comments suppressed due to low confidence (5)

tools/validate_newhope_slashtopics_integration.py:77

  • If required_objects is present but not a list (e.g., a string), the loop will iterate unexpected values (characters) and the validator may fail in confusing ways; similarly, a non-string local_path can throw a TypeError during path joining. Add explicit type checks (e.g., local_path is a non-empty string; required_objects is a list of strings) and call fail(...) with a clear message when malformed.
    if not isinstance(manifest, dict) or not isinstance(manifest.get("imports"), list):
        fail("IMPORT_MANIFEST malformed: expected a mapping with an 'imports' list")
    by_repo = {i.get("repo"): i for i in manifest["imports"] if isinstance(i, dict)}

tools/validate_newhope_slashtopics_integration.py:89

  • If required_objects is present but not a list (e.g., a string), the loop will iterate unexpected values (characters) and the validator may fail in confusing ways; similarly, a non-string local_path can throw a TypeError during path joining. Add explicit type checks (e.g., local_path is a non-empty string; required_objects is a list of strings) and call fail(...) with a clear message when malformed.
    local_path = ROOT / st.get("local_path", "contracts/imported/slash-topics/")
    for obj in st.get("required_objects", []):

tools/validate_newhope_slashtopics_integration.py:35

  • The junk-file scan only recurses into directories; since the docs entry is a file path, junk under docs/ (e.g., docs/.DS_Store) will not be detected even though docs are part of the landed integration. Consider scanning ROOT / \"docs\" (or Path(...).parent) instead of the single markdown file so the check matches the stated intent.
LANDED_PATHS = [SLASH, EXAMPLES, ROOT / "docs" / "INTEGRATION_NewHope_SlashTopics_SemanticBI.md"]

tools/validate_newhope_slashtopics_integration.py:61

  • The junk-file scan only recurses into directories; since the docs entry is a file path, junk under docs/ (e.g., docs/.DS_Store) will not be detected even though docs are part of the landed integration. Consider scanning ROOT / \"docs\" (or Path(...).parent) instead of the single markdown file so the check matches the stated intent.
    for base in LANDED_PATHS:
        if base.is_dir():
            for p in base.rglob("*"):
                if p.name == ".DS_Store" or "__MACOSX" in p.parts:

contracts/imported/slash-topics/specs/Membrane_Decision_v0.1.json:3

  • Unlike Membrane_Decision_v0.2.json, the v0.1 schema is missing a $id. Adding a stable $id improves schema tooling/interoperability (especially if any downstream validator/resolver relies on schema identifiers) and keeps the mirrored schema set consistent.
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "properties": {

Comment on lines +86 to +92

def assert_schema_invariants() -> None:
schema = load_json(SPECS / "SlashTopics_Schema_v0.1.json")
md = load_json(SPECS / "Membrane_Decision_v0.1.json")
model = load_json(SPECS / "Model_Selection_Policy_v0.1.json")

required = set(schema.get("required", []))
Copilot AI review requested due to automatic review settings July 31, 2026 00:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comments suppressed due to low confidence (3)

tools/validate_newhope_slashtopics_integration.py:40

  • Repo validators appear to already have a fail() helper with consistent formatting and exit semantics (context excerpt shows raise SystemExit(2) and ERR: prefix). This script redefines fail() with different output format and exit code, which can make CI behavior and log parsing inconsistent across validators. Prefer reusing the shared helper (or matching its exit code + message format) so failures are uniform.
def fail(msg: str) -> None:
    print(f"[FAIL] {msg}", file=sys.stderr)
    sys.exit(1)

.github/workflows/newhope-slashtopics-integration.yml:49

  • The workflow pins library versions 'for reproducibility' but uses python-version: '3.x', which can change interpreter minor versions over time and break reproducibility (and possibly dependency resolution). Pin a specific Python version (e.g., 3.11/3.12) to align with the reproducibility goal, or relax dependency pins if you want broader interpreter compatibility. Also consider invoking pip as python -m pip ... to ensure the pip bound to the configured interpreter is used.
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.x'

      - name: Install validator dependencies (pinned for reproducibility)
        run: pip install jsonschema==4.23.0 PyYAML==6.0.2 pytest==8.3.4

tools/validate_newhope_slashtopics_integration.py:53

  • Error output includes an absolute filesystem path ({path}), while other failures sometimes use relative_to(ROOT). For CI logs and portability (and to avoid leaking runner filesystem structure), prefer normalizing paths to path.relative_to(ROOT) when possible, and fall back to the original string only if it cannot be relativized.
    except Exception as e:  # noqa: BLE001
        fail(f"Could not parse JSON: {path} ({e})")

Comment on lines +86 to +91
# Enforce slash-topics required_objects: each must resolve under its local_path.
st = by_repo["SocioProphet/slash-topics"]
local_path = ROOT / st.get("local_path", "contracts/imported/slash-topics/")
for obj in st.get("required_objects", []):
if not (local_path / obj).is_file():
fail(f"slash-topics required_object not mirrored: {(local_path / obj)}")
@mdheller
mdheller merged commit 78bf09e into main Jul 31, 2026
71 checks passed
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