Starts analysis
The API starts RepositoryAnalysisWorkflow by name and chooses a Temporal queue.
A frontend understands one language. Intermediate Representation (IR) is the shared vocabulary every frontend translates into. That lets CUPID reuse the same signals, graphs, and reports—and creates the foundation for finding contracts that break between languages.
Python AST, Tree-sitter, and a native compiler parser do not need to agree. Each frontend handles its own syntax, then lowers it into the same IR facts: functions, calls, imports, classes, locations, and capabilities.
Every language has different grammar and semantics.
Use the best parser for that language: Python ast, Tree-sitter, libclang, or a
future TypeScript/Go parser. C and C++ reuse a shared C-family walker where their structures match.
A Python call and a C++ call look different in source,
but both become a language-neutral CALL fact with a caller, callee, arguments, and location.
Signals judge local code. Graphs connect files and facts. Reports rank and explain the result. They consume IR, not language-specific syntax.
Autar is a useful example because each component can pass its own compiler and tests while the connection to the next component is already broken.
The API starts RepositoryAnalysisWorkflow by name and chooses a Temporal queue.
Python defines and registers the workflow, then schedules Iris activities and child workflows.
KB scan steps produce named outputs that qualifiers, scoring, profiles, and reports consume.
The Python Hermes client sends handwritten JSON to Go's /exec sandbox gateway.
Iris produces versioned JSON; a TypeScript transformer turns it into product-facing analysis.
The risk is not one bad file. It is a chain of separately handwritten contracts connecting languages, processes, and deployment units.
Each frontend emits facts independently. The graph linker joins them using stable contract keys such as a workflow name, task queue, HTTP method and path, JSON field, or KB output name.
TypeScript starts a Python workflow by string. The Python worker must define it, register it, and listen on the same task queue.
What CUPID could catch: a renamed workflow, missing worker registration, mismatched queue, or incompatible input that every language accepts on its own.
Python handwrites the request to Go's /exec route. Both sides depend on the same field names without one generated definition.
What CUPID could catch: Go changing exit to exit_code while its own tests still pass and Python fails only at runtime.
Iris produces versioned analysis JSON. A TypeScript transformer reads those fields and turns them into the result shown by the product.
What CUPID could catch: a field keeping the same name but changing shape, then silently becoming an empty analysis instead of a visible crash.
A scan step names an output. Later qualifiers, reports, and profiles refer to that name, so the YAML is an executable dataflow rather than passive configuration.
What CUPID could catch: a misspelled reference, use before definition, or same-entity overwrite that quietly turns a detection into an empty value.
Each frontend records what its language produces, consumes, defines, calls, and registers.
Contract keys connect facts that live in different files, languages, services, or configuration.
Risk rises with fan-in, criticality, missing schema/tests, and silent fallback; existing protection lowers it.
The report names the boundary, affected consumers, current safeguards, missing safeguard, and safest next action.
A useful architecture warning must account for safeguards that already exist. CUPID should explain the missing join, not pretend the whole boundary is unprotected.
Output versions, v1/v2/v3 transformers, transformer tests, and validation after the conversion.
The raw Python result is still read through dynamic TypeScript records, and transform failure can return an empty analysis. A broken contract may look like a successful scan with no findings, which damages product trust.
Go and Python each have useful local tests. Hermes also protects workspace paths, stream termination, and exit behavior.
There is no Hermes-specific OpenAPI, protobuf, generated client, or cross-language consumer/provider contract test. CUPID can identify the exact fields and callers affected before an integration fails.
Autar has a Python activity registry, explicit worker registration, task-queue routing, and TypeScript orchestrator tests.
No static check joins the TypeScript start call to the Python definition, worker registration, queue, and input/output shape as one chain. The value is complete-chain validation, not another warning about strings.
KB schema validation already checks structure, duplicate slugs, and dangling relationship targets.
It does not fully prove output define-before-use, same-entity uniqueness, or every output reference in the dataflow. CUPID can show which detections and reports silently disappear when an output breaks.
Compilers protect code inside one language. CUPID's architecture layer can protect workflow names, HTTP payloads, analysis schemas, and declarative outputs that cross those boundaries.