ambitgraph 0.3.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ambitgraph-0.3.0/ambitgraph.egg-info → ambitgraph-0.5.0}/PKG-INFO +1 -1
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/export.py +6 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/graph.py +73 -0
- ambitgraph-0.5.0/ambit_map/langmirror.py +471 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/library.py +26 -31
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/orchestrate.py +8 -7
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/page.py +62 -1
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/registry.py +229 -7
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/serve.py +31 -1
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/theme.py +4 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/unitpage.py +36 -2
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/__init__.py +1 -1
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/cli.py +15 -12
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/codelib.py +204 -6
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/edges.py +1624 -16
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/langs.py +107 -40
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/portal.py +42 -2
- ambitgraph-0.5.0/ambitgraph/prompts.py +88 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/shell.py +145 -28
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/symbols.py +1552 -45
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/urcode.py +11 -20
- {ambitgraph-0.3.0 → ambitgraph-0.5.0/ambitgraph.egg-info}/PKG-INFO +1 -1
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph.egg-info/SOURCES.txt +1 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/pyproject.toml +1 -1
- ambitgraph-0.3.0/ambit_map/langmirror.py +0 -243
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/LICENSE +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/MANIFEST.in +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/README.md +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/__init__.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/__main__.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/ambit-map-enrich.md +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/ambit-mapllm-contract.md +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/cli.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/daemon.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/dialects/__init__.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/dialects/contract.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/dialects/express_pack.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/dialects/fastapi_pack.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/dialects/flask_pack.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/dialects/nextjs_pack.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/dialects/supabase_pack.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/families.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/island_layout.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/islands.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/judged.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/kitdemo.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/load.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/mapllm.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/matched.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/model.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/objects.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambit_map/paths.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/WALKTHROUGH.md +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/__main__.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/cockpit.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/config.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/console.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/demo.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/docs_discovery.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/doctor.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/duplication.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/emit.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/engine_identity.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/estimate.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/eval.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/feeds.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/gate.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/gate_check.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/gate_server.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/harvest.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/inventory.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/jscalls.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/mds.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/merge.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/merge_jsp.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/parameterize.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/pipeline.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/pycalls.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/ratify.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/report.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/reports.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/sample.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/secretary.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/stages.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/tables.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph/tasks.py +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph.egg-info/dependency_links.txt +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph.egg-info/entry_points.txt +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph.egg-info/requires.txt +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/ambitgraph.egg-info/top_level.txt +0 -0
- {ambitgraph-0.3.0 → ambitgraph-0.5.0}/setup.cfg +0 -0
|
@@ -23,6 +23,10 @@ GRAPH_EXPORT_CAP = 200 # the brief's cap
|
|
|
23
23
|
EXPORT_INDEX = "index.html"
|
|
24
24
|
EXPORT_MAP = reg.EXPORT_MAP_REL
|
|
25
25
|
EXPORT_LIBRARY = "library.html"
|
|
26
|
+
# The Whole map tab. NOT map.html -- that is the default GRAPH seed page
|
|
27
|
+
# and every existing link plus the manifest resolve to it; renaming it to
|
|
28
|
+
# free the nicer name would break links to fix an aesthetic.
|
|
29
|
+
EXPORT_OVERVIEW = reg.EXPORT_OVERVIEW_REL
|
|
26
30
|
MANIFEST_NAME = "ambitgraph-map.export.json" # U4 review fix (blocker): the
|
|
27
31
|
# scoped-prune manifest -- lists every relative path THIS export wrote, so
|
|
28
32
|
# the NEXT export deletes only what it itself owns, never a hand-placed file.
|
|
@@ -139,6 +143,8 @@ def page_rows(model, dialects):
|
|
|
139
143
|
# existing link and the manifest resolve to it. A real row now, not a copy.
|
|
140
144
|
rows.append(Row(EXPORT_MAP, "/graph", index_query, 0))
|
|
141
145
|
|
|
146
|
+
rows.append(Row(EXPORT_OVERVIEW, "/overview", "", 0))
|
|
147
|
+
|
|
142
148
|
routes_by_uid = lib._routes_by_uid(dialects)
|
|
143
149
|
units_iter = model.units.values() if hasattr(model, "units") else ()
|
|
144
150
|
order = fam.families_in_use(units_iter, routes_by_uid)
|
|
@@ -1972,3 +1972,76 @@ GRAPH_JS = '''
|
|
|
1972
1972
|
box.scrollTop = (H - box.clientHeight) / 2;
|
|
1973
1973
|
})();
|
|
1974
1974
|
'''
|
|
1975
|
+
|
|
1976
|
+
|
|
1977
|
+
# ---------------------------------------------------------------------------
|
|
1978
|
+
# 3.16 THE ISLANDS RENDERER (islands-render wave, 2026-09-05) -- the Whole
|
|
1979
|
+
# map tab's drawing half. COMPOSES AND DRAWS ONLY: island_layout.py already
|
|
1980
|
+
# decided every position (its own C7); this function's one piece of
|
|
1981
|
+
# arithmetic is pack_islands's own documented contract -- every island's
|
|
1982
|
+
# placement is normalized into the [0,1] whole-map unit square, so
|
|
1983
|
+
# composing means multiplying by a fixed pixel side, never recomputing a
|
|
1984
|
+
# bounding box or re-deriving a layout.
|
|
1985
|
+
#
|
|
1986
|
+
# REUSES the Graph tab's pan/zoom mechanism byte-for-byte: GRAPH_JS (drag
|
|
1987
|
+
# to pan, the three zoom buttons, SVG width/height-attribute zoom -- never
|
|
1988
|
+
# viewBox alone, the exact trap a design-panel review caught before this
|
|
1989
|
+
# was written) and the SAME .cm-canvas/.cm-canvas-wrap/.cm-zoom-ctrl
|
|
1990
|
+
# classes/button ids, so the script needs no adaptation. An island node
|
|
1991
|
+
# carries no edges (islands.py's own C5), so GRAPH_JS's edge-click/.cm-desc
|
|
1992
|
+
# half simply never fires here -- it is not wired to anything, and nothing
|
|
1993
|
+
# breaks by its absence (every DOM lookup in GRAPH_JS null-checks first).
|
|
1994
|
+
# ---------------------------------------------------------------------------
|
|
1995
|
+
|
|
1996
|
+
|
|
1997
|
+
def render_islands_canvas(layout):
|
|
1998
|
+
"""The `<div class="cm-canvas-wrap">...` markup for a DRAWABLE
|
|
1999
|
+
product-layout.json payload (the caller decides drawability -- this
|
|
2000
|
+
function assumes `layout["islands"]` is non-empty and never checks)."""
|
|
2001
|
+
side = reg.ISLANDS_CANVAS_SIDE
|
|
2002
|
+
pad = reg.ISLANDS_CANVAS_PADDING
|
|
2003
|
+
w = side + 2 * pad
|
|
2004
|
+
h = w
|
|
2005
|
+
|
|
2006
|
+
boundary_parts = []
|
|
2007
|
+
node_parts = []
|
|
2008
|
+
for isl in layout.get("islands", ()):
|
|
2009
|
+
bx = isl["x"] * side + pad
|
|
2010
|
+
by = isl["y"] * side + pad
|
|
2011
|
+
bs = isl["scale"] * side
|
|
2012
|
+
# A subtle region under the nodes, never a hard border or a label
|
|
2013
|
+
# (design-panel finding: pack_islands shelves islands with zero
|
|
2014
|
+
# gap, so shared placement alone can read as one cluster when it
|
|
2015
|
+
# is two touching ones).
|
|
2016
|
+
boundary_parts.append(
|
|
2017
|
+
'<rect class="isl-island" x="{x}" y="{y}" width="{s}" height="{s}" '
|
|
2018
|
+
'rx="6"></rect>'.format(x=_n(bx), y=_n(by), s=_n(bs)))
|
|
2019
|
+
for node in isl.get("nodes", ()):
|
|
2020
|
+
gx = bx + node["x"] * bs
|
|
2021
|
+
gy = by + node["y"] * bs
|
|
2022
|
+
degree = node.get("d", 0)
|
|
2023
|
+
r = min(reg.ISL_NODE_RADIUS_MAX,
|
|
2024
|
+
reg.ISL_NODE_RADIUS_MIN + degree * reg.ISL_NODE_RADIUS_PER_DEGREE)
|
|
2025
|
+
node_parts.append(
|
|
2026
|
+
'<a href="{href}"><circle class="isl-node" cx="{cx}" cy="{cy}" '
|
|
2027
|
+
'r="{r}"></circle></a>'.format(
|
|
2028
|
+
href=reg.href_unit(node["u"]), cx=_n(gx), cy=_n(gy), r=_n(r)))
|
|
2029
|
+
|
|
2030
|
+
svg = (
|
|
2031
|
+
'<svg class="isl-svg" viewBox="0 0 {w} {h}" width="{w}" height="{h}" '
|
|
2032
|
+
'data-zoom="1" role="img" aria-label="{aria}" data-amg-object="islands">'
|
|
2033
|
+
'<g class="isl-islands">{boundaries}</g>'
|
|
2034
|
+
'<g class="isl-nodes">{nodes}</g></svg>'
|
|
2035
|
+
).format(w=_n(w), h=_n(h), aria=reg.esc(reg.OVERVIEW_CANVAS_LABEL),
|
|
2036
|
+
boundaries="".join(boundary_parts), nodes="".join(node_parts))
|
|
2037
|
+
|
|
2038
|
+
return (
|
|
2039
|
+
'<div class="cm-canvas-wrap"><div class="cm-zoom-ctrl">'
|
|
2040
|
+
'<button type="button" id="cmZoomOut" title="{zo}" aria-label="{zo}">{zog}</button>'
|
|
2041
|
+
'<button type="button" id="cmZoomReset" title="{zr}" aria-label="{zr}">{zrg}</button>'
|
|
2042
|
+
'<button type="button" id="cmZoomIn" title="{zi}" aria-label="{zi}">{zig}</button>'
|
|
2043
|
+
'</div><div class="cm-canvas" data-canvas="1">{svg}</div></div>'
|
|
2044
|
+
).format(zo=reg.esc(reg.GRAPH_ZOOM_OUT_LABEL), zog=reg.esc(reg.GRAPH_ZOOM_OUT_GLYPH),
|
|
2045
|
+
zr=reg.esc(reg.GRAPH_ZOOM_RESET_LABEL), zrg=reg.esc(reg.GRAPH_ZOOM_RESET_GLYPH),
|
|
2046
|
+
zi=reg.esc(reg.GRAPH_ZOOM_IN_LABEL), zig=reg.esc(reg.GRAPH_ZOOM_IN_GLYPH),
|
|
2047
|
+
svg=svg)
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
"""ambit_map/langmirror.py -- the product-side ASSERTED MIRROR of
|
|
2
|
+
ambitgraph/langs.py's declared language vocabulary (R4-DESIGN.md, v2;
|
|
3
|
+
CENSUS.md).
|
|
4
|
+
|
|
5
|
+
ONE file replacing five scatterings: ambit_map/orchestrate.py's admission
|
|
6
|
+
copy + MAPLLM_EXTRA_INCLUDE_EXT, ambit_map/registry.py's JS_LANGS/PY_LANGS/
|
|
7
|
+
ROUTEDNESS_LANGS, ambit_map/paths.py's KIND_READER_LANGS/_GRAMMAR_EXTS, and
|
|
8
|
+
ambit_map/library.py's own blind-sentence language vocabulary. Every value
|
|
9
|
+
below is UNCHANGED from what its scattered original held -- this module
|
|
10
|
+
only gives them one address; see each field's own comment for its prior
|
|
11
|
+
location, and the module-docstring note below for R4's "no member
|
|
12
|
+
deletion" ruling.
|
|
13
|
+
|
|
14
|
+
THE WALL (tests/test_import_boundaries.py's violations helper, the
|
|
15
|
+
ambit_map stdlib-only rule inside rule_message, and that file's own
|
|
16
|
+
test_self_test_map_importing_contracts_is_caught test): ambit_map may
|
|
17
|
+
NEVER import ambitgraph, not even ambit_contracts, the house's own
|
|
18
|
+
shared-stdlib-only package -- there was never a choice of a third shared
|
|
19
|
+
package; the wall forecloses it outright (R4-DESIGN.md v2, "The
|
|
20
|
+
architecture ruling"). So this module cannot import ambitgraph/
|
|
21
|
+
langs.py and DERIVE its values the way ambitgraph/symbols.py, edges.py,
|
|
22
|
+
config.py and codelib.py now derive theirs from langs.py -- it is instead
|
|
23
|
+
an ASSERTED COPY: every value below is retyped by hand, checked against
|
|
24
|
+
langs.py's own values ONLY by a TEST (tests/test_langs_mirror_diff.py),
|
|
25
|
+
NEVER by any import at runtime. This is not a new exception -- the
|
|
26
|
+
identical both-sides-import shape is already live at
|
|
27
|
+
tests/test_map_serve.py's own
|
|
28
|
+
test_engine_include_ext_is_duplicated_by_value_and_never_drifts test
|
|
29
|
+
(ENGINE_DEFAULT_INCLUDE_EXT vs ScanConfig().include_ext), which this
|
|
30
|
+
module's own admission field below continues rather than replaces.
|
|
31
|
+
|
|
32
|
+
Unlike ambitgraph/langs.py (which imports `re` and `dataclasses` for its
|
|
33
|
+
own LangSpec declarations), this module is a pure, dependency-free LEAF:
|
|
34
|
+
no imports at all, not even stdlib. Every value below is a literal, and
|
|
35
|
+
the single function here (`blind_langs`) reads only the table declared
|
|
36
|
+
directly above it, so it needs no import either. Every
|
|
37
|
+
consumer inside this package (orchestrate.py, paths.py, registry.py,
|
|
38
|
+
library.py) imports IT; it imports NONE of them, so no existing consumer
|
|
39
|
+
of registry.py/paths.py/library.py/orchestrate.py risks a cycle by their
|
|
40
|
+
now also depending, transitively, on this module.
|
|
41
|
+
|
|
42
|
+
NO MEMBER DELETION (R4-DESIGN.md v2, ruling 1, refuting the v1 draft's
|
|
43
|
+
"delete the dead members" plan twice over -- JUDGES-DIGEST.txt LENS 3,
|
|
44
|
+
finding on ruling 1): tests/test_map_registry.py's own
|
|
45
|
+
test_kind_key_maps_import_by_source_language_not_by_kind test already
|
|
46
|
+
pins kind_key("include", "import", "ts") == "include/import.js" --
|
|
47
|
+
deleting "ts" from JS_LANGS reds that live pin. And ambit_map/load.py's
|
|
48
|
+
load_run reads a unit's `lang` value VERBATIM off of symbols.json with NO
|
|
49
|
+
vocabulary gate at all, under this product's own shipped producer-
|
|
50
|
+
portability contract (ambit-mapllm-contract.md, pyproject.toml) -- an
|
|
51
|
+
older or foreign producer's artifact can carry a `lang` this engine's OWN
|
|
52
|
+
current writer (ambitgraph/symbols.py's build_file_plane) never emits
|
|
53
|
+
today. So every grouping below keeps its READER-TOLERANCE members: they
|
|
54
|
+
document what a FILE may say, not only what this engine currently
|
|
55
|
+
writes.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
# ===========================================================================
|
|
59
|
+
# Admission -- CENSUS fact 1. Byte-duplicated from ambitgraph/langs.py's
|
|
60
|
+
# ENGINE_DEFAULT_INCLUDE_EXT, IN ORDER: the order is byte-load-bearing
|
|
61
|
+
# through ambitgraph/symbols.py's config_hash and through the cross-import
|
|
62
|
+
# equality pin at tests/test_map_serve.py's own
|
|
63
|
+
# test_engine_include_ext_is_duplicated_by_value_and_never_drifts test
|
|
64
|
+
# (see that engine module's own docstring for the full argument). Formerly
|
|
65
|
+
# hand-duplicated separately inside ambit_map/orchestrate.py;
|
|
66
|
+
# orchestrate.py now aliases this tuple instead of carrying its own
|
|
67
|
+
# literal.
|
|
68
|
+
# ===========================================================================
|
|
69
|
+
ENGINE_DEFAULT_INCLUDE_EXT = (
|
|
70
|
+
".py", ".js", ".ts", ".tsx", ".jsx", ".java", ".jsp", ".jspf",
|
|
71
|
+
".css", ".html", ".go", ".rb", ".php", ".cs", ".sql", ".sh",
|
|
72
|
+
".c", ".h",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# The extra extensions a mapllm run admits beyond the shared engine default
|
|
76
|
+
# above -- world-popularity order per the founder's list, the C++
|
|
77
|
+
# foundation first (formerly ambit_map/orchestrate.py's own
|
|
78
|
+
# MAPLLM_EXTRA_INCLUDE_EXT literal; this constant is not part of
|
|
79
|
+
# ambitgraph/langs.py at all -- it is this product's OWN scope extension,
|
|
80
|
+
# mirrored here only so orchestrate.py can source every admission fact
|
|
81
|
+
# from this one file). ".c"/".h" left this tuple once they gained a real
|
|
82
|
+
# LangSpec: they are ENGINE_DEFAULT_INCLUDE_EXT members above now, not a
|
|
83
|
+
# mapllm-only widening.
|
|
84
|
+
MAPLLM_EXTRA_INCLUDE_EXT = (".cpp", ".hpp", ".rs")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# ===========================================================================
|
|
88
|
+
# Naming's product-side grouping (CENSUS fact 2's third spelling) --
|
|
89
|
+
# formerly ambit_map/registry.py's own JS_LANGS/PY_LANGS literals, the pair
|
|
90
|
+
# kind_key's src_lang branch reads. READER-TOLERANCE VOCABULARY (see module
|
|
91
|
+
# docstring): today ambitgraph/symbols.py's build_file_plane (the only
|
|
92
|
+
# writer of a file row's `lang` field) folds .jsx/.mjs/.cjs/.ts/.tsx all
|
|
93
|
+
# into the single tag "js" -- so "jsx"/"mjs"/"cjs"/"ts"/"tsx" can never
|
|
94
|
+
# appear as a REAL `lang` value THIS engine emits today. They stay in
|
|
95
|
+
# JS_LANGS anyway: an older or foreign producer's symbols.json is free to
|
|
96
|
+
# spell it differently under this product's own producer-portability
|
|
97
|
+
# contract, and ambit_map/load.py's load_run reads `lang` with no
|
|
98
|
+
# vocabulary gate at all. PY_LANGS carries no such extra member -- "py" is
|
|
99
|
+
# the only tag ambitgraph/langs.py's "py" LangSpec ever declares.
|
|
100
|
+
#
|
|
101
|
+
# JAVA_LANGS (Java W1, 2026-09-02, additive): the identical one-tag
|
|
102
|
+
# grouping shape as PY_LANGS -- "java" is the only tag ambitgraph/langs.py's
|
|
103
|
+
# "java" LangSpec ever declares, so this carries no reader-tolerance member
|
|
104
|
+
# either. Exists as its own named grouping (never folded into JS_LANGS or
|
|
105
|
+
# PY_LANGS) because kind_key's import branch needs a THIRD disjoint
|
|
106
|
+
# src_lang bucket once include/import.java joins include/import.py and
|
|
107
|
+
# include/import.js.
|
|
108
|
+
# ===========================================================================
|
|
109
|
+
JS_LANGS = ("js", "jsx", "mjs", "cjs", "ts", "tsx")
|
|
110
|
+
PY_LANGS = ("py",)
|
|
111
|
+
JAVA_LANGS = ("java",)
|
|
112
|
+
# C_LANGS: the identical one-tag grouping shape as PY_LANGS/JAVA_LANGS --
|
|
113
|
+
# "c" is the only tag ambitgraph/langs.py's "c" LangSpec ever declares
|
|
114
|
+
# (its naming_exts {".c", ".h"} both fold to that one tag), so this
|
|
115
|
+
# carries no reader-tolerance member either. Read by kind_key's include
|
|
116
|
+
# branch, which maps a C preprocessor include onto the include/static row
|
|
117
|
+
# (see registry.py's own comment there), and by the unit story's type-kind
|
|
118
|
+
# count gate.
|
|
119
|
+
C_LANGS = ("c",)
|
|
120
|
+
|
|
121
|
+
# RB_LANGS (Ruby wave 1): the identical one-tag grouping shape as
|
|
122
|
+
# PY_LANGS/JAVA_LANGS/C_LANGS -- "rb" is the only tag ambitgraph/langs.py's
|
|
123
|
+
# "rb" LangSpec ever declares (naming_exts {".rb"}), so this carries no
|
|
124
|
+
# reader-tolerance member either. Read by kind_key's include branch, which
|
|
125
|
+
# maps a resolved `require_relative` onto the include/static row (see
|
|
126
|
+
# registry.py's own comment there), and by the unit story's type-kind
|
|
127
|
+
# count gate.
|
|
128
|
+
RB_LANGS = ("rb",)
|
|
129
|
+
|
|
130
|
+
# TYPE_SYMBOL_KINDS (Java W1 repair -- the wall-legal PRODUCT-side
|
|
131
|
+
# mirror of ambitgraph/codelib.py's own _TYPE_SYMBOL_KINDS): the literal
|
|
132
|
+
# kind strings symbols.py's own class alternation emits for a Java type
|
|
133
|
+
# declaration ("class"/"interface"/"enum"/"record") -- "constructor" is
|
|
134
|
+
# DELIBERATELY not a member, the same exclusion codelib.py's own set
|
|
135
|
+
# states (a constructor is a member OF a type, never itself a type
|
|
136
|
+
# declaration). Consumed by ambit_map/unitpage.py's own class-count
|
|
137
|
+
# bucket so a Java interface/enum/record renders in the class(es) count
|
|
138
|
+
# on the unit story, not silently in "other named symbol(s)". Diffed
|
|
139
|
+
# against ambitgraph.codelib._TYPE_SYMBOL_KINDS by
|
|
140
|
+
# tests/test_langs_mirror_diff.py (DIFFED_FACT_NAMES entry
|
|
141
|
+
# "type_symbol_kinds") -- one origin (symbols.py's own kind literals), two
|
|
142
|
+
# independently-declared copies, never a cross-wall import.
|
|
143
|
+
TYPE_SYMBOL_KINDS = ("class", "interface", "enum", "record")
|
|
144
|
+
|
|
145
|
+
# C_TYPE_SYMBOL_KINDS (the wall-legal PRODUCT-side mirror of
|
|
146
|
+
# ambitgraph/codelib.py's own _C_TYPE_SYMBOL_KINDS): the literal kind
|
|
147
|
+
# strings symbols.py's extract_c_symbols emits for a C type declaration --
|
|
148
|
+
# a tagged bodied "struct"/"union"/"enum", and "typedef". "function" is
|
|
149
|
+
# deliberately not a member (it is the callable half, the same boundary
|
|
150
|
+
# TYPE_SYMBOL_KINDS draws against "constructor"). Consumed by
|
|
151
|
+
# ambit_map/unitpage.py's class-count bucket under the C_LANGS gate above:
|
|
152
|
+
# "enum" is a member of BOTH this tuple and TYPE_SYMBOL_KINDS, and the two
|
|
153
|
+
# language gates are disjoint, so a TypeScript enum still renders as
|
|
154
|
+
# "other named symbol(s)" while a C enum counts as a type. Diffed against
|
|
155
|
+
# ambitgraph.codelib._C_TYPE_SYMBOL_KINDS by tests/test_langs_mirror_diff.py
|
|
156
|
+
# (DIFFED_FACT_NAMES entry "c_type_symbol_kinds") -- one origin
|
|
157
|
+
# (symbols.py's own kind literals), two independently-declared copies,
|
|
158
|
+
# never a cross-wall import.
|
|
159
|
+
C_TYPE_SYMBOL_KINDS = ("struct", "union", "enum", "typedef")
|
|
160
|
+
|
|
161
|
+
# RB_TYPE_SYMBOL_KINDS (Ruby wave 1 -- the wall-legal PRODUCT-side mirror
|
|
162
|
+
# of ambitgraph/codelib.py's own _RB_TYPE_SYMBOL_KINDS): the literal kind
|
|
163
|
+
# strings extract_ruby_symbols emits for a Ruby scope-opener declaration --
|
|
164
|
+
# "class" and "module", the two keywords _RB_SCOPE_LINE_RX matches. Unlike
|
|
165
|
+
# TYPE_SYMBOL_KINDS/C_TYPE_SYMBOL_KINDS above, this set already includes
|
|
166
|
+
# "class" itself (Ruby genuinely has classes), so it feeds BOTH halves of
|
|
167
|
+
# codelib.py's carve identically -- the same shape TYPE_SYMBOL_KINDS takes
|
|
168
|
+
# for Java, never C's shape (which unions "class" in separately because C
|
|
169
|
+
# never emits that literal kind at all). Consumed by
|
|
170
|
+
# ambit_map/unitpage.py's class-count bucket under the RB_LANGS gate
|
|
171
|
+
# above, WIDENING THE COUNT ONLY -- the word stays reg.UNIT_STORY_CLASSES
|
|
172
|
+
# for Ruby (unitpage.py's own class_word ternary is not gated on RB_LANGS
|
|
173
|
+
# at all): Ruby genuinely has classes, so mirroring C's word-swap here
|
|
174
|
+
# would render "N type(s)" about a language whose classes are exactly what
|
|
175
|
+
# the count is naming. Diffed against ambitgraph.codelib._RB_TYPE_SYMBOL_KINDS
|
|
176
|
+
# by tests/test_langs_mirror_diff.py (DIFFED_FACT_NAMES entry
|
|
177
|
+
# "rb_type_symbol_kinds") -- one origin (symbols.py's own kind literals),
|
|
178
|
+
# two independently-declared copies, never a cross-wall import.
|
|
179
|
+
RB_TYPE_SYMBOL_KINDS = ("class", "module")
|
|
180
|
+
|
|
181
|
+
# NAMESPACE_LANGS (Java W1 repair -- the wall-legal PRODUCT-side mirror of
|
|
182
|
+
# ambitgraph/langs.py's own NAMESPACE_LANGS): the `lang` tags whose units
|
|
183
|
+
# get the java-namespace treatment (the languages whose LangSpec declares
|
|
184
|
+
# namespace=True). Consumed by ambit_map/unitpage.py's class-count bucket
|
|
185
|
+
# as the language gate on TYPE_SYMBOL_KINDS above -- symbols.py emits the
|
|
186
|
+
# SAME literal kinds ("interface"/"enum") for TypeScript declarations,
|
|
187
|
+
# which must keep rendering as "other named symbol(s)", exactly the
|
|
188
|
+
# boundary ambitgraph/codelib.py draws with its own is_java_namespace
|
|
189
|
+
# check at export. Diffed against ambitgraph.langs.NAMESPACE_LANGS by
|
|
190
|
+
# tests/test_langs_mirror_diff.py (DIFFED_FACT_NAMES entry
|
|
191
|
+
# "namespace_langs") -- one origin (the LangSpec namespace flags), two
|
|
192
|
+
# independently-declared copies, never a cross-wall import.
|
|
193
|
+
NAMESPACE_LANGS = frozenset({"java", "jsp"})
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# ===========================================================================
|
|
197
|
+
# CENSUS fact 8 -- formerly ambit_map/registry.py's own ROUTEDNESS_LANGS
|
|
198
|
+
# literal. READER-TOLERANCE VOCABULARY, same law as JS_LANGS above: "jspf"
|
|
199
|
+
# can never appear as a real `lang` value today (ambitgraph/symbols.py's
|
|
200
|
+
# build_file_plane folds .jspf into the tag "jsp", never into "jspf"
|
|
201
|
+
# itself) but stays for the identical producer-portability reason.
|
|
202
|
+
# Consumed DIRECTLY by ambit_map/library.py's routedness gates
|
|
203
|
+
# (_routedness_is_silent, _blind_for_run) via `langm.ROUTEDNESS_LANGS` --
|
|
204
|
+
# no production call site reads it through registry.py anymore.
|
|
205
|
+
# ambit_map/registry.py still re-exports the name (`ROUTEDNESS_LANGS =
|
|
206
|
+
# langm.ROUTEDNESS_LANGS`), kept alive for backward compatibility and
|
|
207
|
+
# because tests/test_langs_value_pins.py's own R4.0 locked oracle pin
|
|
208
|
+
# still asserts `reg.ROUTEDNESS_LANGS` by value.
|
|
209
|
+
# ===========================================================================
|
|
210
|
+
ROUTEDNESS_LANGS = ("jsp", "jspf", "java")
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# ===========================================================================
|
|
214
|
+
# CENSUS fact 4's product-side mirror -- formerly ambit_map/paths.py's own
|
|
215
|
+
# KIND_READER_LANGS literal (the full reader-coverage matrix: 19
|
|
216
|
+
# ALLOWED_KINDS rows -> the Unit.lang frozenset each kind's reader covers).
|
|
217
|
+
# Java W1 (2026-09-02): the 19th row, include/import.java, is additive --
|
|
218
|
+
# every pre-existing row's value is UNCHANGED. Values UNCHANGED otherwise;
|
|
219
|
+
# the "why" narrative for each individual row (which real reader function
|
|
220
|
+
# backs it, what its own language gate looks like) stays in
|
|
221
|
+
# ambit_map/paths.py's own module comment beside its KIND_READER_LANGS
|
|
222
|
+
# alias -- this module only carries the literal.
|
|
223
|
+
#
|
|
224
|
+
# _kind_applicable's THREE NAMED DIVERGENCES (ambit_map/paths.py, unmoved
|
|
225
|
+
# -- these are about HOW paths.py USES this table, not part of the table's
|
|
226
|
+
# own values, so the overriding logic and its own inputs (TERMINAL_KINDS,
|
|
227
|
+
# MOUNT_CAPABLE_PACKS) stay declared in paths.py, not here):
|
|
228
|
+
# 1. TERMINAL_KINDS (table/read|write|ddl) -- LANGUAGE-AGNOSTIC by the
|
|
229
|
+
# real reader's own construction (ambitgraph/tables.py's build_tables
|
|
230
|
+
# carries no language gate at all): applicable whenever the model
|
|
231
|
+
# holds any unit at all -- this table's own three TERMINAL rows are
|
|
232
|
+
# never actually consulted for that decision.
|
|
233
|
+
# 2. "reference/script" -- unconditionally False: CONFIG-gated on
|
|
234
|
+
# ScanConfig.asset_roots, never language-gated, and this product's own
|
|
235
|
+
# scan config never sets asset_roots -- so this row's frozenset below
|
|
236
|
+
# is never actually consulted either; kept only so this dict's key set
|
|
237
|
+
# still equals paths.ALLOWED_KINDS.
|
|
238
|
+
# 3. "route/mount" -- language overlap against this row IS consulted, but
|
|
239
|
+
# is NECESSARY, not SUFFICIENT: applicability additionally requires at
|
|
240
|
+
# least one of MOUNT_CAPABLE_PACKS (express_pack/fastapi_pack/
|
|
241
|
+
# flask_pack) to have DETECTED this run.
|
|
242
|
+
# ===========================================================================
|
|
243
|
+
KIND_READER_LANGS = {
|
|
244
|
+
# "c" joins this row rather than opening a twentieth: the C
|
|
245
|
+
# preprocessor's own `#include` IS a static include -- the target is a
|
|
246
|
+
# literal read from the source text and never varies at runtime, which
|
|
247
|
+
# is this row's whole claim -- so registry.kind_key maps a C include
|
|
248
|
+
# edge here instead of minting a row whose sentence would repeat
|
|
249
|
+
# include/static's word for word. A C repo's include reader is
|
|
250
|
+
# therefore named as having run, where a missing member would report
|
|
251
|
+
# the include plane unmeasured on every C repo forever.
|
|
252
|
+
# "rb" joins this row the same way (Ruby wave 1): a resolved
|
|
253
|
+
# `require_relative` IS a static include -- a literal path read from
|
|
254
|
+
# the source text, spliced in at include time, never varying at
|
|
255
|
+
# runtime -- the identical claim this row already makes. Without the
|
|
256
|
+
# member a Ruby repo's 236-edge include lane would report the include
|
|
257
|
+
# plane unmeasured despite having just drawn every one of them.
|
|
258
|
+
"include/static": frozenset({"jsp", "c", "rb"}),
|
|
259
|
+
"include/import.py": frozenset({"py"}),
|
|
260
|
+
"include/import.js": frozenset({"js"}),
|
|
261
|
+
# Java W1 (2026-09-02), additive: langs.py's java LangSpec gains
|
|
262
|
+
# include_lane=True this wave -- the row sits beside its import.py/
|
|
263
|
+
# import.js siblings, same shape, one reader language.
|
|
264
|
+
"include/import.java": frozenset({"java"}),
|
|
265
|
+
"include/require": frozenset({"js"}),
|
|
266
|
+
"include/dynamic": frozenset({"jsp"}),
|
|
267
|
+
"include/reexport": frozenset({"js"}),
|
|
268
|
+
"include/dynamic-import": frozenset({"js"}),
|
|
269
|
+
"include/member-resolved": frozenset({"js"}),
|
|
270
|
+
# The Java exact-evidence call tiers (constructor resolution,
|
|
271
|
+
# static-receiver resolution, static-import binding) record PROVEN
|
|
272
|
+
# rows into this same "calls" kind: no new kind key, no new lang
|
|
273
|
+
# tag, no new symbol kind, and no new blind-prose word crosses the
|
|
274
|
+
# wall for them, so nothing about them enters this mirror or the
|
|
275
|
+
# DIFFED_FACT_NAMES set. Their twelve coverage keys -- the nine
|
|
276
|
+
# refusal/correction counters (java_ctor_target_missing,
|
|
277
|
+
# java_ctor_qualified_unresolved, java_expr_new_refused,
|
|
278
|
+
# java_static_receiver_undeclared,
|
|
279
|
+
# java_static_receiver_multisegment, java_static_import_overrides,
|
|
280
|
+
# java_static_import_target_missing,
|
|
281
|
+
# java_declaration_window_refused, java_annotation_window_refused)
|
|
282
|
+
# and the java_call_counter_samples/_files/_samples_omitted
|
|
283
|
+
# attribution trio -- are engine-side coverage keys with no
|
|
284
|
+
# product-side reader. A matched-marked calls carrier, if one
|
|
285
|
+
# ever lands, arrives as its OWN registry kind row and gains its
|
|
286
|
+
# own entry here beside this one.
|
|
287
|
+
# "c" joins this row with the C call lane (langs.py's c LangSpec
|
|
288
|
+
# declares call_lane=True and edges.py builds C its own definer pool):
|
|
289
|
+
# without the member a C repo would be told the calls reader never
|
|
290
|
+
# heard of C, the exact defect this table's own NAMESPACE_LANGS
|
|
291
|
+
# comment records for java.
|
|
292
|
+
# "rb" joins this row the same way (Ruby wave 1): langs.py's rb
|
|
293
|
+
# LangSpec declares call_lane=True and edges.py builds Ruby its own
|
|
294
|
+
# definer pool, landed independently of this stage.
|
|
295
|
+
"calls": frozenset({"jsp", "java", "py", "js", "c", "rb"}),
|
|
296
|
+
"reference/script": frozenset({"jsp"}),
|
|
297
|
+
"route/mount": frozenset({"py", "js"}),
|
|
298
|
+
"ui/component-use": frozenset({"js"}),
|
|
299
|
+
"net/fetch-route": frozenset({"js", "py"}),
|
|
300
|
+
"ui/component-use-matched": frozenset({"js"}),
|
|
301
|
+
"event/emit": frozenset({"js"}),
|
|
302
|
+
"table/read": frozenset({"sql", "js", "py", "jsp"}),
|
|
303
|
+
"table/write": frozenset({"sql", "js", "py", "jsp"}),
|
|
304
|
+
"table/ddl": frozenset({"sql", "js", "py", "jsp"}),
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
# ===========================================================================
|
|
309
|
+
# CENSUS fact 2's product-side mirror -- formerly ambit_map/paths.py's own
|
|
310
|
+
# _GRAMMAR_EXTS literal, a hand-kept copy of ambitgraph/symbols.py's
|
|
311
|
+
# _LANG_FOR_EXT key set (exactly the extensions with a real comment-
|
|
312
|
+
# blanking grammar). Unlike JS_LANGS/PY_LANGS/ROUTEDNESS_LANGS above, this
|
|
313
|
+
# set carries NO reader-tolerance members: it is a copy of the ENGINE's own
|
|
314
|
+
# key set (every ambitgraph/langs.py LangSpec's naming_exts, unioned), not
|
|
315
|
+
# a copy of a possibly-foreign `lang` value's vocabulary.
|
|
316
|
+
# ===========================================================================
|
|
317
|
+
_GRAMMAR_EXTS = frozenset({
|
|
318
|
+
".jsp", ".jspf", ".java", ".js", ".mjs", ".cjs", ".jsx", ".ts", ".tsx",
|
|
319
|
+
".py", ".sh", ".sql", ".c", ".h", ".rb",
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
# ===========================================================================
|
|
324
|
+
# CENSUS fact 8's disclosure-gate vocabulary -- THE PER-SENTENCE LANGUAGE
|
|
325
|
+
# TAG, product side. Formerly ambit_map/library.py's own
|
|
326
|
+
# _BLIND_SENTENCE_LANGS/_blind_langs pair; it lives here, with every other
|
|
327
|
+
# cross-wall copy, and library.py aliases the reader.
|
|
328
|
+
#
|
|
329
|
+
# The engine declares each blind sentence's own languages AT the sentence
|
|
330
|
+
# (ambitgraph.symbols.BlindSentence's `langs`, empty meaning the sentence
|
|
331
|
+
# holds for every run). That attribute cannot reach this side of the wall:
|
|
332
|
+
# this package reads a run's ARTIFACT FILES, and json.loads hands back
|
|
333
|
+
# plain strings, so the tag is mirrored here -- the same shape
|
|
334
|
+
# ambit_map/registry.py's CALL_BLIND_MATCH already uses, an opening
|
|
335
|
+
# fragment of one engine sentence held as a stable anchor.
|
|
336
|
+
# tests/test_blind_sentence_langs.py diffs the two declarations entry by
|
|
337
|
+
# entry, in both directions, so a sentence tagged on one side and not the
|
|
338
|
+
# other is red, never a page quietly telling a reader a law about a
|
|
339
|
+
# language it never scanned.
|
|
340
|
+
#
|
|
341
|
+
# Each row is (anchor, langs): the anchor is a fragment no other blind
|
|
342
|
+
# sentence contains, and `langs` is that sentence's own `lang` tags. A
|
|
343
|
+
# sentence no row matches is universal and renders on every run.
|
|
344
|
+
#
|
|
345
|
+
# TWO KINDS OF ANCHOR, one shape. The static sentences
|
|
346
|
+
# (ambitgraph.symbols.BLIND_SENTENCES) are anchored on their opening
|
|
347
|
+
# words. The C include lane's four sentences are built per scan and carry
|
|
348
|
+
# their counts at the END, so each is anchored on the FIXED OPENING PREFIX
|
|
349
|
+
# ambitgraph/edges.py declares beside it -- retyped here by value, exactly
|
|
350
|
+
# as this module retypes every other engine literal, because the wall
|
|
351
|
+
# forbids asking the engine for it. The prefix constants and these rows are
|
|
352
|
+
# held equal by the seam tests, never by an import.
|
|
353
|
+
#
|
|
354
|
+
# The prose-word sniffing this field used to carry (BLIND_LANG_PROSE_WORDS
|
|
355
|
+
# plus library.py's compiled _BLIND_LANG_FILTER) is retired: it was an
|
|
356
|
+
# all-or-nothing guess read off a sentence's English, wrong in both
|
|
357
|
+
# directions (Java-only pages rendering C sentences, C-only pages dropping
|
|
358
|
+
# their own call-coverage note), and the tag rows below are the declared
|
|
359
|
+
# answer that replaces it.
|
|
360
|
+
# ===========================================================================
|
|
361
|
+
_JSP_JAVA = frozenset({"jsp", "jspf", "java"})
|
|
362
|
+
_C = frozenset({"c"})
|
|
363
|
+
# _RB (Ruby wave 1): the identical one-tag alias shape as _C above -- "rb"
|
|
364
|
+
# is the only tag any Ruby-declared sentence ever carries this wave.
|
|
365
|
+
_RB = frozenset({"rb"})
|
|
366
|
+
BLIND_SENTENCE_LANGS = (
|
|
367
|
+
("Java declarations inside JSP scriptlet blocks", _JSP_JAVA),
|
|
368
|
+
("A Java class whose modifiers are written on their own line", _JSP_JAVA),
|
|
369
|
+
("A Java method declared inside an ANONYMOUS class body", _JSP_JAVA),
|
|
370
|
+
("A Java annotation-type declaration", _JSP_JAVA),
|
|
371
|
+
("A Java declaration with an annotation ANYWHERE on the declaration",
|
|
372
|
+
_JSP_JAVA),
|
|
373
|
+
("In Java, a constructor or static-receiver call can bind", _JSP_JAVA),
|
|
374
|
+
("A Java method inherited from a supertype", _JSP_JAVA),
|
|
375
|
+
("An anonymous class creation over a Java interface or class", _JSP_JAVA),
|
|
376
|
+
("A Java receiver separated from its method call by a line break",
|
|
377
|
+
_JSP_JAVA),
|
|
378
|
+
("Java call and type names under four characters", _JSP_JAVA),
|
|
379
|
+
("For Java, three exact-evidence tiers run before the name-match",
|
|
380
|
+
_JSP_JAVA),
|
|
381
|
+
# The call-coverage sentence names the C lane beside the JSP/Java one:
|
|
382
|
+
# a C-only run draws call edges and must keep the note that says how
|
|
383
|
+
# they were read. Anchor duplicated by value from
|
|
384
|
+
# ambit_map/registry.py's CALL_BLIND_MATCH (this module imports
|
|
385
|
+
# nothing, not even its own package's registry, which imports IT).
|
|
386
|
+
("call sites are read for the JSP/Java namespace", _JSP_JAVA | _C),
|
|
387
|
+
# The C declaration grammar's own gaps (ambitgraph.symbols.
|
|
388
|
+
# BLIND_SENTENCES), anchored on their opening words.
|
|
389
|
+
("A C `#define` is never read as a symbol", _C),
|
|
390
|
+
("A function that a macro DEFINES is not read at all", _C),
|
|
391
|
+
("Conditional and macro-body text is read exactly as written", _C),
|
|
392
|
+
("A K&R-style C definition", _C),
|
|
393
|
+
("A C definition is read at column 0 and brace depth 0 only", _C),
|
|
394
|
+
("A bodied `struct`/`union`/`enum` with no tag", _C),
|
|
395
|
+
("Only C definitions are read, never declarations", _C),
|
|
396
|
+
# The C include lane's four per-scan sentences, anchored on
|
|
397
|
+
# ambitgraph/edges.py's C_ANGLE_INCLUDE_SENTENCE_PREFIX,
|
|
398
|
+
# C_QUOTED_UNRESOLVED_SYSTEM_SENTENCE_PREFIX,
|
|
399
|
+
# C_QUOTED_UNRESOLVED_ABSENT_SENTENCE_PREFIX and
|
|
400
|
+
# C_QUOTED_UNRESOLVED_SENTENCE_PREFIX, in that order.
|
|
401
|
+
("Angle-bracket C includes are never drawn", _C),
|
|
402
|
+
("A quoted C include naming a C standard library header", _C),
|
|
403
|
+
("A quoted C include with no candidate anywhere in this scan", _C),
|
|
404
|
+
("A quoted C include this scan does hold a file for, but position "
|
|
405
|
+
"does not license,", _C),
|
|
406
|
+
# Ruby wave 1's own two STATIC, structural gaps (ambitgraph.symbols.
|
|
407
|
+
# BLIND_SENTENCES), anchored on their opening words -- the same
|
|
408
|
+
# shape as the C declaration grammar's own gaps just above.
|
|
409
|
+
("A Ruby heredoc body, from its opener line", _RB),
|
|
410
|
+
("A Ruby percent literal (", _RB),
|
|
411
|
+
# Ruby wave 1's seven PER-SCAN symbol-grammar sentences
|
|
412
|
+
# (ambitgraph.symbols.rb_symbol_blind_sentences), anchored on the
|
|
413
|
+
# fixed prefix constants declared beside that function -- retyped
|
|
414
|
+
# here by value, exactly as the C include lane's four prefixes are
|
|
415
|
+
# above.
|
|
416
|
+
("A method definition line whose name does not fit any Ruby method "
|
|
417
|
+
"name shape is refused outright", _RB),
|
|
418
|
+
("A method defined directly on one specific runtime object, or a "
|
|
419
|
+
"singleton class opened on an object other than self, is refused",
|
|
420
|
+
_RB),
|
|
421
|
+
("A private, protected, or module_function marker changes the "
|
|
422
|
+
"default visibility of every method written after it, a stateful "
|
|
423
|
+
"effect this wave discloses rather than simulates", _RB),
|
|
424
|
+
("An attr_accessor, attr_reader, or attr_writer call defines one or "
|
|
425
|
+
"more methods by name that this wave does not read as symbols",
|
|
426
|
+
_RB),
|
|
427
|
+
("A define_method, method_missing, class_eval, instance_eval, "
|
|
428
|
+
"alias, or alias_method call can define or rename a method by a "
|
|
429
|
+
"name this wave cannot predict", _RB),
|
|
430
|
+
("A class, module, or method opener sharing its physical line with "
|
|
431
|
+
"another statement, separated by a semicolon, is read for its own "
|
|
432
|
+
"name only", _RB),
|
|
433
|
+
("A method definition found indented with no enclosing class, "
|
|
434
|
+
"module, or singleton scope on the stack sits inside a block "
|
|
435
|
+
"construct this wave does not track", _RB),
|
|
436
|
+
# Ruby wave 1's six PER-SCAN edges.py sentences (the include lane's
|
|
437
|
+
# three, ambitgraph.edges.rb_include_blind_sentences, plus the call
|
|
438
|
+
# ceiling's three, ambitgraph.edges.rb_call_blind_sentences),
|
|
439
|
+
# anchored on their own fixed prefix constants, same discipline.
|
|
440
|
+
("A require naming a plain load-path string, rather than a "
|
|
441
|
+
"relative file, searches the Ruby runtime load path and is never "
|
|
442
|
+
"drawn as an edge", _RB),
|
|
443
|
+
("A require_relative naming a file this scan does hold somewhere, "
|
|
444
|
+
"but not at the position this call computes to, draws no edge",
|
|
445
|
+
_RB),
|
|
446
|
+
("A require_relative naming no file anywhere in this scan draws no "
|
|
447
|
+
"edge", _RB),
|
|
448
|
+
("Ruby calls need neither a receiver nor parentheses, so an EXACT "
|
|
449
|
+
"count of receiverless, parenless call sites is impossible", _RB),
|
|
450
|
+
("A method whose name is a setter or an operator can never be "
|
|
451
|
+
"reached by either call site shape this lane recognizes", _RB),
|
|
452
|
+
("A method name defined in more than one place is dropped from the "
|
|
453
|
+
"call resolution pool entirely rather than guessed at", _RB),
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def blind_langs(sentence):
|
|
458
|
+
"""The `lang` tags one blind sentence is about -- the union of every
|
|
459
|
+
anchor it carries, empty when it names no language at all. Empty is
|
|
460
|
+
the universal answer, not the unknown one: a sentence this vocabulary
|
|
461
|
+
does not describe is a sentence about the instrument, true on every
|
|
462
|
+
run, so it is kept rather than guessed at.
|
|
463
|
+
|
|
464
|
+
The one function in this module: it reads only the table right above
|
|
465
|
+
it and the string handed to it, so it stays as dependency-free as
|
|
466
|
+
every literal here."""
|
|
467
|
+
out = set()
|
|
468
|
+
for anchor, tags in BLIND_SENTENCE_LANGS:
|
|
469
|
+
if anchor in sentence:
|
|
470
|
+
out |= tags
|
|
471
|
+
return frozenset(out)
|