Skip to content

Commit aa0a2bb

Browse files
committed
deferred item: scope-correct rename (shadowing), gated; Layer-2 boundary verified
(A) Scope-correct rename — the local-shadowing gap, CLOSED. The name-based rename over-renames a shadowing local (param/let named like the def); the fix is identity not spelling. chartroom's resolve.clj (Turtle #5) is a lexical resolver adding refers_to edges (nearest enclosing scope), so renaming a def edits ONE node + references follow refers_to — a shadowing local is a different node, untouched. That's the principled "id-references" fix the deferral named, and it's Layer 2 (chartroom owns the engine). bin/test/code-as-claims/rename-scope.sh (CI-gated, checks out chartroom) proves: def + caller-ref renamed; shadowing param + its use untouched; recompiles. rename-in-store noted as the simpler module-local version. (B) Layer-2 boundary — VERIFIED, not relocated. The language core (parse/check/ emit-clj/js/nix/types/ast) is clean: zero graph-engine machinery, only tombstone comments for the removed (claim …) surface form. The code-intelligence engine (resolver/rename/call-graph) is Layer 2 in chartroom; beagle gates RENT it. A physical repo-split of bin/ tooling is org churn the principle doesn't require (language already clean) and would risk the dev loop/gates — documented in fram/docs as a separate deliberate migration, not a cleanliness fix. Also: independently re-ran the eddy crm-v2 spike over its artifact with my own reaches-closure — blast(contact.company)={contact.display-name}, decoy note.company excluded. Unification confirmed both sides.
1 parent c4089b3 commit aa0a2bb

4 files changed

Lines changed: 82 additions & 0 deletions

File tree

.github/workflows/test.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ jobs:
5858
repository: tompassarelli/fram
5959
path: .fram
6060

61+
- name: Checkout chartroom (Layer-2 code-intelligence: the refers_to resolver)
62+
uses: actions/checkout@v5
63+
with:
64+
repository: tompassarelli/chartroom
65+
path: .chartroom
66+
6167
- name: Graph-native cascade — scope-correctness gate
6268
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" bin/test/cascade-graph/run.sh
6369

@@ -95,6 +101,12 @@ jobs:
95101
- name: Authoring substrate — recompile-gated edit transaction
96102
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" bin/test/code-as-claims/author.sh
97103

104+
# Scope-correct rename: renaming a def leaves a SHADOWING local of the same name
105+
# untouched, via chartroom's refers_to resolver (binding identity, not spelling).
106+
# The Layer-2 code-intelligence engine driven by a beagle gate.
107+
- name: Scope-correct rename (shadowing) — refers_to resolver gate
108+
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" CHARTROOM="$GITHUB_WORKSPACE/.chartroom" bin/test/code-as-claims/rename-scope.sh
109+
98110
- name: Show accumulated surface debt
99111
if: always()
100112
run: |

bin/test/code-as-claims/rename-in-store.clj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
;; toolchain owns it. Refuses (exit 3) if `new` already binds in a target module
1212
;; (the rename-doesn't-collide invariant) — no claims mutated on refusal.
1313
;;
14+
;; SCOPE: this is the MODULE-LOCAL, name-based rename (renames every same-named
15+
;; symbol leaf in the target module) — correct across MODULES (the mod_a/mod_b
16+
;; collision), but it would over-rename a SHADOWING local of the same name. The
17+
;; scope-correct-under-shadowing rename is chartroom's resolve.clj (Turtle #5,
18+
;; refers_to identity) — gated by bin/test/code-as-claims/rename-scope.sh.
19+
;;
1420
;; bb -cp <fram>/out rename-in-store.clj <old> <new> <target-substr> <outdir> <edn>...
1521
(ns rename-in-store
1622
(:require [clojure.edn :as edn]
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env bash
2+
# Scope-correct rename — the deferred local-shadowing gap, CLOSED.
3+
#
4+
# The name-based rename (rename-in-store) renames every same-named symbol leaf in a
5+
# module, so it CORRUPTS a shadowing local (a param/let named like the def). The fix
6+
# is identity, not spelling: chartroom's resolve.clj (Turtle #5) is a lexical
7+
# resolver that adds `refers_to <binding-node-id>` edges (nearest enclosing scope),
8+
# so renaming a DEF edits one node + references follow refers_to — a shadowing local
9+
# is a DIFFERENT node and is left untouched. That is the principled "id-references"
10+
# fix the deferral named, and it lives in chartroom = Layer 2 (the code-intelligence
11+
# engine); this beagle gate drives it (a consumer renting the engine).
12+
#
13+
# Fixture: `helper` is a top-level def AND a shadowing param in `other`. Renaming the
14+
# def must rename the def + the caller's reference, and leave the shadowing param
15+
# (and its use) ALONE. Needs racket + bb + fram out/ + chartroom's resolve.clj.
16+
set -uo pipefail
17+
18+
HERE="$(cd "$(dirname "$0")" && pwd)"
19+
ROOT="$(cd "$HERE/../../.." && pwd)"
20+
RT="$ROOT/beagle-lib/private/claims-roundtrip.rkt"
21+
FRAM_OUT="${FRAM_OUT:-$HOME/code/fram/out}"
22+
CHARTROOM="${CHARTROOM:-$HOME/code/chartroom}"
23+
RES="$CHARTROOM/src/resolve.clj"
24+
fail=0
25+
26+
echo "================ scope-correct rename — shadowing handled (refers_to resolver) ================"
27+
[ -d "$FRAM_OUT" ] || { echo " (need FRAM_OUT)"; exit 3; }
28+
[ -f "$RES" ] || { echo " (need chartroom resolve.clj at $RES — set CHARTROOM)"; exit 3; }
29+
30+
W="$(mktemp -d)"; trap 'rm -rf "$W" /tmp/resolved-mod.bclj.edn' EXIT
31+
racket "$RT" --emit-edn "$HERE/shadow-corpus/mod.bclj" 2>/dev/null > "$W/a.edn"
32+
# the Layer-2 engine: scope-correct rename of the DEF `helper` -> `safe-add`
33+
bb -cp "$FRAM_OUT" "$RES" rename helper safe-add mod "$W/a.edn" 2>/dev/null
34+
racket "$RT" --render /tmp/resolved-mod.bclj.edn 2>/dev/null > "$W/regen.bclj"
35+
echo "--- rename result ---"; sed 's/^/ /' "$W/regen.bclj"
36+
37+
R="$W/regen.bclj"
38+
chk() { if eval "$2"; then echo " PASS $1"; else echo " FAIL $1"; fail=1; fi; }
39+
echo "--- assertions ---"
40+
chk "def renamed: '(defn safe-add'" "grep -q '(defn safe-add' '$R'"
41+
chk "def name 'helper' gone as a def" "! grep -q '(defn helper' '$R'"
42+
chk "caller reference renamed: '(safe-add y)'" "grep -q '(safe-add y)' '$R'"
43+
chk "SHADOWING param untouched: 'other \[helper'" "grep -qE 'other \[helper' '$R'"
44+
chk "SHADOWING use untouched: '(* helper 2)'" "grep -qF '(* helper 2)' '$R'"
45+
echo "--- recompiles ---"
46+
mkdir -p "$W/r/fram"; cp "$R" "$W/r/fram/mod.bclj"
47+
if "$ROOT/bin/beagle-build-all" "$W/r" --out "$W/o" 2>&1 | grep -q '0 error'; then
48+
echo " PASS renamed module builds clean"
49+
else echo " FAIL renamed module does not build"; fail=1; fi
50+
51+
echo
52+
if [ "$fail" = 0 ]; then
53+
echo "RESULT: PASS — rename follows binding identity: def + refs renamed, shadowing local untouched."
54+
else
55+
echo "RESULT: FAIL"; exit 1
56+
fi
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#lang beagle/clj
2+
;; `helper` is a top-level def AND a shadowing param in `other`.
3+
(defn helper [x :- Int] :- Int
4+
(+ x 1))
5+
(defn other [helper :- Int] :- Int
6+
(* helper 2))
7+
(defn caller [y :- Int] :- Int
8+
(helper y))

0 commit comments

Comments
 (0)