Skip to content

fix(build): default emit output to gitignored .beagle-out/, never cwd… #190

fix(build): default emit output to gitignored .beagle-out/, never cwd…

fix(build): default emit output to gitignored .beagle-out/, never cwd… #190

Workflow file for this run

name: tests
# CI runs the full tiered suite (active + demoted). The CI=true env var
# triggers bin/beagle-test to include the demoted tier. Active failures
# block the build; demoted failures are advisory (logged in the run
# output and surface-debt.md tracks accumulated debt). See
# lab/journal/synthesis/design-principle.md "Test-cadence decomposition".
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install Racket
uses: Bogdanp/setup-racket@v1.14
with:
architecture: x64
distribution: full
variant: CS
version: '9.1'
- name: Link beagle packages
run: |
raco pkg install --auto --link \
beagle-lib/ beagle-test/ beagle/
# Babashka must be installed BEFORE the tiered suite: conformance.rkt's
# cross-target value-conformance harness uses bb as the real-Clojure ORACLE.
# Without it the oracle silently skips AND the pinned-divergence tests error
# (a missing #f exec path -> system* contract violation). It is also used by
# the graph-native gates further down. (Was installed too late, after the suite.)
- name: Install babashka (CLJ oracle + graph-native repair tooling)
run: curl -sL https://raw.githubusercontent.com/babashka/babashka/master/install | sudo bash
- name: Run tiered test suite
env:
CI: 'true'
run: bin/beagle-test
# Byte-stable emit (move 2): the claims->source pretty-printer must be a
# deterministic, LOCAL, comment-preserving, round-trip-preserving formatter —
# the precondition for making claims canonical and text a regenerable lowering.
# Racket-only (no fram/bb), so it runs right after the suite.
- name: Byte-stable emit — fixed-point + locality + comments gate
run: bin/test/byte-stable-emit/run.sh
# Build reproducibility: the same source compiles BYTE-IDENTICALLY every build.
# match's temp was (random ...) -> non-reproducible; now a deterministic counter.
- name: Build reproducibility — deterministic match temps
run: bin/test/build-reproducible/run.sh
# Graph-native repair: beagle-cascade derives its call graph from the Fram
# claim graph (scope-correct), not regex over text. That runs on the Fram
# engine, so we check out fram's committed classpath and gate the
# scope-correctness proof (a change to mod_a/helper must NOT blast mod_b's
# same-named helper). This is the load-bearing test for the thesis that
# graph-backed repair beats text-backed repair. (babashka installed above.)
- name: Checkout fram (the claim engine cascade runs on)
uses: actions/checkout@v5
with:
repository: tompassarelli/fram
path: .fram
# beagle-callgraph RENTS the scope-correct call-graph engine (resolve.clj),
# which was FOLDED into the fram repo at fram/chartroom (beagle source
# code-intelligence, renting fram's public claim+Datalog API). No separate
# chartroom checkout — it ships inside the fram checkout, so CHARTROOM points
# at .fram/chartroom. (The fold is licensed by lockstep cadence + this very
# friction relief; fram's core_code_blind_test guards the seam stays clean.)
- name: Graph-native cascade — scope-correctness gate
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" CHARTROOM="$GITHUB_WORKSPACE/.fram/chartroom" bin/test/cascade-graph/run.sh
# Reasoning call-graph cross-module completeness: the call graph is derived from the
# converged resolver (refers_to), so qualified cross-module calls (a/f, m/f) resolve
# and the blast radius is NOT silently emptied. Guards the dangerous "0 callers" lie.
- name: Reasoning call-graph — cross-module completeness gate
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" CHARTROOM="$GITHUB_WORKSPACE/.fram/chartroom" bin/test/callgraph-xmodule/run.sh
# Repair pipeline: beagle-repair consumes blame.rkt's semantic suspicions as
# STRUCTURED records, not by regex-scraping the prose SUSPECT line. Gates that
# a suspicion on a validly-named function the prose regex can't parse (e.g.
# `total=`) survives. (Needs racket + bb, both above; no fram.)
- name: Repair pipeline — structured semantic suspicions gate
run: bin/test/repair-semantic/run.sh
# Move 3: code can be claim-canonical. The loop .bclj -> lossless claims ->
# (through a real Fram store) -> claims -> byte-stable .bclj is datum-identical
# through the engine AND recompiles to the IDENTICAL program (modulo srcloc
# debug pointers). Proven over fram/src. Needs racket + bb + fram's out/.
- name: Code as canonical claims — recompile-identity gate
run: CODE_AS_CLAIMS_CORPUS="$GITHUB_WORKSPACE/.fram/src" FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" bin/test/code-as-claims/run.sh
# Scope-correct rename — the COMPLETE engine (chartroom's resolve.clj, refers_to),
# ONE gate across every scope hazard: mod_a/helper renamed but mod_b's untouched
# (collision); a shadowing local untouched (shadowing); every cross-module reader
# renamed (cross-file, fram.cnf/value! -> intern! over fram/src); a collision onto
# an existing binding refused; each renamed tree recompiles. Repair as a graph
# operation, O(1) (edits the def; references follow refers_to).
- name: Scope-correct rename (collision + shadowing + cross-module) gate
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" CHARTROOM="$GITHUB_WORKSPACE/.fram/chartroom" CODE_AS_CLAIMS_CORPUS="$GITHUB_WORKSPACE/.fram/src" bin/test/code-as-claims/rename.sh
# Delete as a graph op: the no-orphaned-references invariant. A safe delete omits
# the form + its subtree and renumbers siblings (no truncation); a delete that
# would orphan a reference (this module or a consumer) is refused, fail-closed.
- name: Delete as a graph op — no-orphaned-references invariant
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" CHARTROOM="$GITHUB_WORKSPACE/.fram/chartroom" bin/test/code-as-claims/delete.sh
# NL -> edit authoring layer: prose intent -> a structured edit (data an agent
# emits) -> the engine (rename/delete) -> recompile-gated commit, else fail closed.
- name: NL-to-edit authoring layer — recompile-gated transaction
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" CHARTROOM="$GITHUB_WORKSPACE/.fram/chartroom" bin/test/code-as-claims/authoring.sh
# Graph-native AUTHORING (the dogfood at the root): upsert-form (add/replace a def)
# and set-body are CLAIM operations on the AST-claims, not text patches — scope-correct
# by identity (an authored ref resolves through refers_to), recompile-gated, fail-closed.
- name: Authoring-as-claims — upsert-form + set-body verbs
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" CHARTROOM="$GITHUB_WORKSPACE/.fram/chartroom" bin/test/code-as-claims/authoring-verbs.sh
# One engine, both pillars, on REAL code: the blast radius (REASON) of fram.cnf/value!
# predicts the cross-module reach of renaming it (REPAIR), and the repaired tree
# recompiles — both derived from the same converged refers_to resolver.
- name: Engine demo — reason + repair consistent on real fram/src
run: FRAM_OUT="$GITHUB_WORKSPACE/.fram/out" CHARTROOM="$GITHUB_WORKSPACE/.fram/chartroom" CODE_AS_CLAIMS_CORPUS="$GITHUB_WORKSPACE/.fram/src" bin/test/engine-demo/run.sh
- name: Show accumulated surface debt
if: always()
run: |
if [ -f lab/surface-debt.md ]; then
head -20 lab/surface-debt.md
fi