Skip to content

No presentation-layer artifact role: templates and static output land as roles=["unknown"] #212

Description

@rahlk

Is your feature request related to a problem? Please describe.

discover_artifacts classifies files against RULES (codeanalyzer/artifacts/discovery.py:13-60) into an open, kebab-case role set — dependency-manifest, tool-config, container-image, service-topology, iac, ci, env, packaging, legal, docs, script, unknown. There is no presentation-layer role. A Jinja2 template, a Django template, and everything under static/ all land as format="text", roles=["unknown"] — indistinguishable from a file the analyzer has never heard of.

Consequences today: a graph consumer cannot ask "which templates does this application ship", the artifact inventory reports an application's whole view layer as unknown, and unknown stops being a useful signal — it means both "not classified" and "classified as a thing we have no name for".

codeanalyzer-java is adding view-template artifact roles (.jsp, .xhtml, Thymeleaf .html) and a bundler-output inventory (static/, dist/) as part of its web-application theme. The roles vocabulary is shared and open across all three analyzers, and no analyzer has coined a template role yet (python: 44 rules, none; codeanalyzer-typescript rules.ts: none). Whoever lands first fixes the spelling for everyone — a term coined twice is permanently wrong.

So this issue exists to hold the python end of that thread, not to race it.

Describe the solution you'd like

  • A presentation-layer role value exists in the shared vocabulary, spelled identically in all three analyzers.
  • Python's Jinja2 / Django templates and static output carry it instead of ["unknown"].
  • format values for template files are added alongside, so a consumer can tell a JSP from a Jinja2 file without pattern-matching the path.

Describe alternatives you've considered

Not stated in the original issue.

Additional context

Scope boundary

In scope: adopting the role and format values java coins, and adding the RULES entries that classify python's equivalents — Jinja2 (templates/**.html, *.jinja, *.j2), Django templates, and bundler/static output.

Out of scope: parsing template internals ({{ }}, {% %}) into nodes, template↔code dataflow, and view-dispatch edges from render_template / render / TemplateResponse to the template artifact. Those are separate decisions on the same theme and each is larger than this one.

Blocked on codeanalyzer-java for the names only. Nothing else about it is blocked.

The naming input python owes java

  • view-template over bare template. template already means Helm chart templates and cookiecutter scaffolding in this ecosystem, and values.yaml / Chart.yaml are already service-topology here. view-template is unambiguous and reads correctly for JSP, Thymeleaf, Jinja2, and .ejs/.hbs/.vue on the TypeScript side.
  • format is a separate axis from roles. Artifact carries both (codeanalyzer/neo4j/schema.py, :Artifact props), so .jsp / .xhtml / .html are new format values and one new role — not one conflated string.
  • Bundler output needs its own role, not the template one. A minified dist/app.js is not a view template; it is a shipped asset. Whatever java picks for row 6 of its table should be a sibling value, and python wants the same one for static/.

Caveats and known risks

  • Template discovery in python is convention, not declaration: Flask's default is templates/, Django's is per-app templates/ plus DIRS in settings, and both are configurable. RULES is glob-based, so the rule will over- and under-match; that is acceptable for a role hint and must not be presented as authoritative.
  • templates/**.html and a plain docs/*.html are the same extension. Ordering inside RULES decides which wins, and the existing table already relies on that (the generic *.ini fallback sits after tox.ini on purpose).
  • roles is a list, so a file can be both — no need to force a single winner where view-template and something else genuinely both apply.
  • Every non-.py file gets read_bytes() + full-text capture in discover_artifacts, so widening what counts as interesting has a memory cost on large static/ trees. See The analyzer ingests its own output when -o sits inside -i, growing analysis.json exponentially #207 — the output-dir self-ingestion bug — which is the same code path and should land first.
  • Additive: schema_version and the graph SCHEMA_VERSION stay 2.0.0 under the 2026-09-07 hold. Consumers gate on the analyzer version floor.

Definition of done

  • Role and format spellings confirmed against codeanalyzer-java's landed work, cited by issue or PR number in this thread.
  • RULES entries for Jinja2 / Django templates and for static/bundler output.
  • A fixture with a templates/ directory asserts the role and format on the emitted artifact, in both projections.
  • unknown is no longer produced for those files.
  • codeanalyzer-typescript notified (or an issue filed there) so the third analyzer adopts the same spelling rather than coining a third.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions