Skip to content

test(parity): assert Node and Python mappers emit equivalent project-map (closes #98)#113

Merged
wesleysimplicio merged 2 commits into
mainfrom
claude/issue-98-parity-test
Jun 2, 2026
Merged

test(parity): assert Node and Python mappers emit equivalent project-map (closes #98)#113
wesleysimplicio merged 2 commits into
mainfrom
claude/issue-98-parity-test

Conversation

@wesleysimplicio
Copy link
Copy Markdown
Owner

Resumo

Fecha #98. Adiciona teste de paridade Node ↔ Python para os artefatos do mapper.

Mudanças

  • tests/fixtures/parity-host/ — fixture determinística (package.json + express dep, 2 sources, 1 test).
  • tests/python/test_parity.py — copia o fixture para 2 temp dirs, roda node bin/cli.js map em um e write_mapping_artifacts no outro, compara:
    • schema + version
    • files[] set (paths)
    • entry_points
    • test_files
    • architecture.signals
    • roles por path
    • helper _normalize remove generated_at e product.root (volatile).
    • @skipUnless(node-on-PATH) para dev local Python-only.
  • .gitignore — whitelist tests/fixtures/.
  • .github/workflows/python-ci.yml — instala Node 22 no matrix pytest pra rodar o teste em CI.

Acceptance

  • Mudança heurística em só uma implementação faz pelo menos 1 das 7 paridade assertions falhar.
  • Cobre schema + files + entry_points + roles + architecture.signals.
  • Volatile fields (generated_at, product.root) excluídos.

Validação local

Item Resultado
python -m unittest tests.python.test_parity ✅ 7 pass
Suite Python completa ✅ 38 pass · 1 falha pré-existente do container (git signing fixture, idêntica ao baseline em main)

Refs #98.

https://claude.ai/code/session_01JdmemqddwFnvbceWyuDE8m


Generated by Claude Code

claude added 2 commits June 2, 2026 13:36
Closes #98.

The repo carries two independent implementations of the same mapping logic —
`bin/mapper-artifacts.js` + `bin/map.js` on the Node side and
`simplicio_mapper.mapper` + `simplicio_mapper.cli` on the Python side —
that both emit the `simplicio.*/v1` schemas defined in
`SIMPLICIO_INTEGRATION.md`. Until now nothing verified the two stay in
lockstep, so any heuristic change to one (roles, importance, symbol/import
regexes, layer detection) could silently diverge.

Adds:

- `tests/fixtures/parity-host/` — a small deterministic Node fixture with
  `package.json`, two source files (entrypoint + helper module), one test
  file, and an `express` dependency so the architecture-signal detector has
  something to find.
- `tests/python/test_parity.py` — runs `node bin/cli.js map` and the Python
  `write_mapping_artifacts` against the same fixture (copied into two temp
  trees so they do not clobber each other) and asserts the resulting
  `project-map.json` agrees on schema, the file inventory set, entry
  points, test files, architecture signals, and the per-path roles map. A
  helper strips the intentionally volatile `generated_at` and `product.root`
  fields before comparison. The whole class is `@skipUnless(node-on-PATH)`
  so local Python-only contributors still get a clean run.
- `.gitignore` whitelist for `tests/fixtures/` so the fixture can ship.
- `.github/workflows/python-ci.yml` now installs Node 22 in the pytest
  matrix so the parity assertions run in CI.

Any heuristic change applied to only one implementation will fail at least
one of the seven parity assertions.

https://claude.ai/code/session_01JdmemqddwFnvbceWyuDE8m
The fixture file was named `tests/server.test.js` to make role detection
classify it as a test file, but `node --test` discovers `**/*.test.js`
recursively across the repo, so it tried to load the fixture from outside
its sandbox — failing because the fixture's `express` dependency is not
installed in the main CI suite.

Rename it to `tests/server-fixture.js`. Path-based role detection
(`tests/`) still classifies it as a test file, so the parity assertion on
`test_files` continues to hold.

https://claude.ai/code/session_01JdmemqddwFnvbceWyuDE8m
@wesleysimplicio wesleysimplicio marked this pull request as ready for review June 2, 2026 13:42
Copilot AI review requested due to automatic review settings June 2, 2026 13:42
@wesleysimplicio wesleysimplicio merged commit dcdb027 into main Jun 2, 2026
36 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adiciona um teste de paridade para garantir que os mappers em Node e Python emitam resultados equivalentes ao mapear um fixture determinístico, evitando divergências silenciosas entre as duas implementações.

Changes:

  • Adiciona fixture determinístico tests/fixtures/parity-host/ para servir de input comum aos dois runtimes.
  • Cria tests/python/test_parity.py que executa o mapper em Node e em Python e compara campos-chave do project-map.json.
  • Ajusta .gitignore para versionar tests/fixtures/ e atualiza o workflow python-ci.yml para instalar Node (necessário para o teste de paridade).

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/python/test_parity.py Adiciona teste de paridade Node ↔ Python (atualmente focado em project-map.json).
tests/fixtures/parity-host/tests/server-fixture.js Fixture: arquivo de teste JS para acionar detecção de “test files/roles”.
tests/fixtures/parity-host/src/index.js Fixture: entrypoint simples com express para sinais/roles.
tests/fixtures/parity-host/src/greet.js Fixture: módulo auxiliar para símbolos/imports.
tests/fixtures/parity-host/package.json Fixture: manifest com dependency express para arquitetura/sinais.
.gitignore Passa a versionar tests/fixtures/.
.github/workflows/python-ci.yml Instala Node 22 no job de pytest para rodar o teste de paridade.

Comment on lines +3 to +7
Both `bin/mapper-artifacts.js` (invoked via `node bin/cli.js map`) and the
Python `simplicio_mapper.cli` emit `simplicio.*/v1` artifacts. Running them
against the same fixture must produce equivalent shape — schema, file set,
entry points, roles, architecture signals, symbol names, call-graph edge
counts — modulo intentionally volatile fields like `generated_at` and the
Comment on lines +55 to +68
def _node_map(self) -> dict:
result = subprocess.run(
["node", str(ROOT / "bin" / "cli.js"), "map", "--root", str(self.node_root)],
capture_output=True,
text=True,
check=False,
timeout=60,
)
self.assertEqual(result.returncode, 0, msg=result.stderr)
return json.loads((self.node_root / ".simplicio" / "project-map.json").read_text())

def _python_map(self) -> dict:
write_mapping_artifacts(cwd=str(self.python_root), meta={"product_name": "parity-host"})
return json.loads((self.python_root / ".simplicio" / "project-map.json").read_text())
Comment on lines +113 to +116
# generated_at must be absent from both after normalize.
self.assertNotIn("generated_at", n)
self.assertNotIn("generated_at", p)

Comment on lines +64 to +68
return json.loads((self.node_root / ".simplicio" / "project-map.json").read_text())

def _python_map(self) -> dict:
write_mapping_artifacts(cwd=str(self.python_root), meta={"product_name": "parity-host"})
return json.loads((self.python_root / ".simplicio" / "project-map.json").read_text())
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.

3 participants