Skip to content

Commit 9be1cfa

Browse files
hyperpolymathclaude
andcommitted
docs(estate): #229 foundation — post-#228 re-audit, RS inventory, canonical map (Refs #229)
#228/ADR-014 landed on main (#241), unblocking #229 step 2. This is the front-loaded #229 foundation (the #239-analogue for the estate-port arm): authoritative re-audit + true scope + language-grounded canonical map + escalations + the campaign reproducer. Re-audit (oracle = main w/ #241; same cached corpus = controlled): 552 PASS / 491 DRIFT-SYNTAX / 133 TYPE-ONLY over 1176 .affine. Zero class-delta vs the superseded #231 postfix (#241 reproduces ADR-014 parse behaviour exactly). Honest scope correction: DRIFT-SYNTAX (491) is NOT the workload. Most estate DRIFT is non-RS syntax drift, out of #229's contract. True RS scope = ~84 files / 12 repos (burble 32 + idaptik-dlc-vm 28 = 71%). Canonical RS->AffineScript map, derived language-side (grammar/spec/stdlib, each form cited), in four tiers: - Tier 1 mechanical: array<T>->[T], option/result-><Option|Result>[..], List(X)->[X], open Mod->use Mod::*;, type rec->type (parser.mly:486/394/172, prelude.affine:19-21, traits.affine:89). - Tier 2 semantic redesign: mutable-field, labelled (~x), Belt/Js stdlib. - Tier 3 escalated language-side (the #228 bidirectional-evidence discipline): %%raw -> #245, JSON.t -> #246, Dict.t -> #247. - Tier 4 cross-unit gate: import X as Y parses + alias registers (resolve.ml:787-797) but qualified-value calls hit the INT-01 #178 gap (resolve.ml:719/797) => idaptik-dlc-vm's 28-file port is gated on INT-01 #178; burble + the List(X) quick wins are not. Adds: - tools/estate-rs-audit/ — audit.sh + rs-inventory.sh + repo list + captured data (results.post228.tsv, rs-inventory.tsv) + README. The durable in-repo home the prior /tmp harness lacked. - docs/RESCRIPT-ELIMINATION.adoc — authoritative #229 ledger. - TECH-DEBT CORE-03 truthed (#241 merged; re-audit done; ledger ptr). - ECOSYSTEM see-also cross-link. No compiler/build input changed (docs + tools + data only); dune build clean; 270 gate unaffected by construction. Refs #229 (not Closes — multi-repo, sequenced, human-gated; per-repo port PRs follow). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d187eec commit 9be1cfa

9 files changed

Lines changed: 2217 additions & 3 deletions

File tree

docs/ECOSYSTEM.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,5 +227,7 @@ filed when their blocker closes.
227227
* link:CAPABILITY-MATRIX.adoc[CAPABILITY-MATRIX.adoc] — authoritative
228228
per-feature readiness.
229229
* link:TECH-DEBT.adoc[TECH-DEBT.adoc] — the coordination ledger.
230+
* link:RESCRIPT-ELIMINATION.adoc[RESCRIPT-ELIMINATION.adoc] — the estate
231+
ReScript-surface elimination ledger (#229), the spine's estate-port arm.
230232
* `hyperpolymath/typed-wasm` `LEVEL-STATUS.md` — the target spec & proofs.
231233
* `hyperpolymath/ephapax` — the other typed-wasm producer.

docs/RESCRIPT-ELIMINATION.adoc

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// SPDX-FileCopyrightText: 2024-2026 hyperpolymath
3+
= Estate ReScript-surface elimination — authoritative ledger (issue #229)
4+
:toc: macro
5+
:toclevels: 3
6+
:icons: font
7+
8+
[IMPORTANT]
9+
====
10+
This document is authoritative for issue #229: the post-#228 re-audit numbers,
11+
the *true* RS-surface scope, the language-grounded canonical RS→AffineScript
12+
map, the escalation set (constructs with no clean target), and the per-repo
13+
port plan. It is the #229 analogue of the front-loaded ledger established by
14+
#239 for the spine. Per-feature readiness remains
15+
link:CAPABILITY-MATRIX.adoc[CAPABILITY-MATRIX.adoc]; the coordination ledger
16+
remains link:TECH-DEBT.adoc[TECH-DEBT.adoc]; the spine remains
17+
link:ECOSYSTEM.adoc[ECOSYSTEM.adoc]. Reproducer:
18+
`tools/estate-rs-audit/`.
19+
====
20+
21+
toc::[]
22+
23+
== What #229 is
24+
25+
A subset of estate `.affine` files are unfinished ReScript→AffineScript
26+
hand-ports: the file declares itself AffineScript (`module …;`) but the body
27+
still carries ReScript surface syntax. Such a file is neither valid ReScript
28+
nor valid AffineScript — debt in limbo that cannot be oracle-certified. The
29+
committed goal is *zero ReScript surface in any estate `.affine`*. #229 was
30+
blocked on #228 (ADR-014, module-qualified type/effect paths) because the
31+
oracle stops at the *first* parse error: qualified-path faults masked each
32+
file's full RS inventory. #228 landed on `main` via #241 — this re-audit is
33+
the now-unblocked step 2.
34+
35+
== Post-#228 re-audit (authoritative)
36+
37+
Oracle = affinescript `main` with #241/ADR-014 (parse-equivalent to the
38+
`int01-178-xmod` build: zero `lib/`+`bin/` delta vs `origin/main`). Same
39+
cached estate corpus as the pre-#228 baseline (controlled: only the oracle
40+
changed). Harness + raw data: `tools/estate-rs-audit/`.
41+
42+
[cols="2,1,4"]
43+
|===
44+
|Class |n |Meaning
45+
46+
|`PASS` |552 |parses + typechecks on the oracle
47+
|`DRIFT-SYNTAX` |491 |first line is a parse/syntax error
48+
|`TYPE-ONLY` |133 |parses; fails later (resolution/type) — not a syntax port
49+
|*total* |*1176* |`.affine` across 28 estate repos
50+
|===
51+
52+
Zero class-delta vs the superseded #231 postfix — #241 reproduces ADR-014
53+
parse behaviour exactly; #231 was superseded for *implementation* reasons, not
54+
behaviour. This table is now the post-#228 baseline of record.
55+
56+
== The honest scope correction
57+
58+
[WARNING]
59+
====
60+
`DRIFT-SYNTAX` (491) is *not* the #229 workload. Most estate DRIFT is *non-RS*
61+
syntax drift — out of #229's contract by design. The true #229 scope is the
62+
files that carry a detected ReScript construct in
63+
`tools/estate-rs-audit/data/rs-inventory.tsv`: *~84 files across 12 repos*,
64+
two of which hold 71%.
65+
====
66+
67+
=== True RS-surface scope (excludes the affinescript repo's own intentional negative fixtures)
68+
69+
[cols="2,1,4"]
70+
|===
71+
|Repo |RS files |Shape
72+
73+
|`burble` |32 |Whole-repo RS port; richest construct mix (e.g.
74+
`client/lib/src/BurbleClient.affine` carries 7 RS construct families). Not
75+
module-import-coupled — proceeds first.
76+
|`idaptik-dlc-vm` |28 |Uniform `import … as` VM dispatch. *Gated on the
77+
INT-01 #178 qualified-value resolver* (see §"Cross-unit gating").
78+
|`standards` |4 |
79+
|`developer-ecosystem` |4 |
80+
|`stapeln` |3 |
81+
|`proof-burrower` |3 |
82+
|`idaptik` |3 |
83+
|`bofj-kitt` |3 |
84+
|`panll` |1 |`src/ui/tea/wizard.affine` — `mutable-field`
85+
|`invariant-path` |1 |`src/ui/tea/invariant_path_gui.affine` — `List(X)` only
86+
|`git-scripts` |1 |`src/ui/tea/git_scripts_gui.affine` — `List(X)` only
87+
|`game-server-admin` |1 |`src/ui/tea/gsa_gui.affine` — `List(X)` only
88+
|*total* |*~84* |over 12 repos
89+
|===
90+
91+
The four `*_gui.affine` single-file repos are pure `List(X)` — Tier-1
92+
mechanical, no module coupling: the genuine quick wins.
93+
94+
=== Non-RS DRIFT (NOT #229 scope — recorded so it is not mistaken for it)
95+
96+
`standards` 112, `proof-burrower` 98, `developer-ecosystem` 97, `bofj-kitt`
97+
96, `affinescript` 84 (its own negative fixtures), `airborne-submarine-squadron`
98+
13, `accessibility-everywhere` 13, `idaptik` 9, `stapeln` 6, `burble` 3,
99+
singletons elsewhere. These DRIFT for non-ReScript reasons; they belong to
100+
separate workstreams, not #229.
101+
102+
== Construct frequency (estate, excl. affinescript)
103+
104+
`import-as` 31 · `mutable-field` 29 · `rs-generic<>` 26 · `array<T>` 17 ·
105+
`%%raw` 14 · `labelled-(~x)` 12 · `List(X)` 7 · `JSON.t` 7 · `Dict.t` 6 ·
106+
`rs-stdlib` 4 · `open-Mod` 4 · `type-rec` 3.
107+
108+
== The canonical RS→AffineScript map (language-grounded)
109+
110+
Derived from the language side — grammar / spec v2.0 / stdlib — *not guessed*.
111+
Every target form carries its grounding citation. Four tiers.
112+
113+
=== Tier 1 — Mechanical (clean grammar target; scriptable, oracle-revalidated)
114+
115+
[cols="2,2,3"]
116+
|===
117+
|ReScript |AffineScript |Grounding
118+
119+
|`array<T>` |`[T]` |list/array type is `[T]` — `stdlib/collections.affine`,
120+
`stdlib/prelude.affine`; `lib/parser.mly:486,394` (type-app is `[ ]`)
121+
|`option<T>` / `result<T,E>` |`Option[T]` / `Result[T, E]` |
122+
`stdlib/prelude.affine:19-21` `pub type Option<T> = Some(T) \| None` /
123+
`Result<T,E> = Ok(T) \| Err(E)`; type-app `[ ]` per `lib/parser.mly:486`,
124+
`stdlib/traits.affine:89` `Into[T]`
125+
|generic `name<T>` |`Name[T]` |capitalise + `[ ]`; `lib/parser.mly:486`
126+
|`List(X)` |`[X]` |list type is `[T]` (the four `*_gui.affine` quick wins)
127+
|`open Mod` |`use Mod::*;` |`lib/parser.mly:172` `ImportGlob`
128+
|`type rec t = …` |`type t = …` |AS `type`/`enum` decls are self-referential
129+
by default (`stdlib/prelude.affine:19-21`); drop `rec`
130+
|===
131+
132+
=== Tier 2 — Semantic redesign (maps onto the affine model; per-case, NO blind codemod)
133+
134+
[cols="2,3"]
135+
|===
136+
|ReScript |Why it is not mechanical
137+
138+
|`mutable` record field |AffineScript is immutable-by-default with *explicit
139+
mutation via ownership* (`docs/spec.md:38`; `mut τ` `docs/spec.md:563`).
140+
There is no `mutable` field keyword; each record is re-expressed against the
141+
ownership model — a redesign, reviewed per record.
142+
|`(~x) =>` labelled args |No labelled/named-argument syntax in the grammar or
143+
stdlib (stdlib is uniformly positional, e.g. `stdlib/option.affine`).
144+
Rewrite to positional — a call-convention change, reviewed per call site.
145+
|`Belt.*` / `Js.*` / `Rescript.*` |ReScript stdlib; no 1:1 AffineScript
146+
target. Per-symbol remap to the estate stdlib, semantic.
147+
|===
148+
149+
=== Tier 3 — Escalate as a language-side issue/ADR (bidirectional evidence — the #228 discipline)
150+
151+
These have *no clean AffineScript target today*. Per #229 step 3 they are
152+
escalated language-side rather than patched divergently across N repos — the
153+
same discipline that produced #228.
154+
155+
[cols="1,2,4"]
156+
|===
157+
|Esc |Construct |Finding
158+
159+
|*ESC-01* (#245) |`%%raw("…")` (14) |AffineScript has *no raw-host-expression
160+
/ FFI escape*. The only host bridge is typed `extern fn` / `extern type`
161+
(`lib/parser.mly:185+`) — host-supplied, typed, no arbitrary-source escape.
162+
Needs a language decision on a raw/FFI form (or an explicit "port every
163+
`%%raw` to typed `extern`" doctrine).
164+
|*ESC-02* (#246) |`JSON.t` (7) |No stdlib JSON type (`stdlib/` has `Ajv` but
165+
no `Json`). Needs a stdlib JSON type.
166+
|*ESC-03* (#247) |`Dict.t` (6) |No stdlib `Map`/`Dict` type
167+
(`stdlib/collections.affine` is list ops only; `stdlib/Http.affine:16`
168+
already flags the `Dict` gap, tied to #160/#162). Needs a stdlib `Map` type —
169+
coordinate with #160/#162.
170+
|===
171+
172+
=== Tier 4 — Cross-unit gating (a sequencing finding, language-grounded)
173+
174+
`import X as Y` ports to `use X as Y;`. That *parses* and the alias *registers*
175+
(`lib/parser.mly:168` `ImportSimple(path, Some alias)`;
176+
`lib/resolve.ml:787-797` registers the alias on `lookup_qualified` success).
177+
*But* qualified-value call sites `Y.fn(x)` hit the post-#228 INT-01 #178
178+
qualified-*value* resolution gap (`lib/resolve.ml:719,797`
179+
`UndefinedModule`) — the exact gap recorded as the next spine unit.
180+
181+
⇒ *`idaptik-dlc-vm` (28 files, 33% of #229 scope) is gated on the INT-01 #178
182+
qualified-value resolver.* `burble` (rs-generic/array/mutable/%%raw-dominated,
183+
not module-coupled) and the four `List(X)` quick-win repos are not gated and
184+
proceed first. This does not reorder the mandate (#229 foundation first, as
185+
instructed); it is the foundation's own finding that the `idaptik-dlc-vm`
186+
*slice* of the per-repo work naturally sequences after INT-01 #178.
187+
188+
== Per-repo port plan
189+
190+
Each repo: oracle-validate locally first (estate CI does not compile
191+
`.affine`), one branch + squash-merge PR per repo, noreply author,
192+
`Refs #229` (multi-repo, sequenced, human-gated — never `Closes`). *Per-repo
193+
hands-off confirm before touching*: policy hands-off is the ReScript
194+
*ecosystem* (`.res`); `.affine`-with-RS is an in-scope unfinished port — but
195+
confirm per repo it is an intended AffineScript target, not a deliberate
196+
interop artefact (burble's standing caveat), before removal.
197+
198+
. *Quick wins (Tier-1 only, no coupling):* `git-scripts`, `game-server-admin`,
199+
`invariant-path` (one `List(X)` file each), then `panll` (`mutable-field`,
200+
Tier-2 single file).
201+
. *`burble`* (32): Tier-1 mechanical pass first (re-validated), Tier-2
202+
`mutable`/labelled per-case, Tier-3 constructs blocked on ESC-01..03.
203+
. *Small tail:* `standards`, `developer-ecosystem`, `stapeln`,
204+
`proof-burrower`, `idaptik`, `bofj-kitt` (≤4 RS files each).
205+
. *`idaptik-dlc-vm`* (28): after INT-01 #178 resolver lands (Tier-4 gate).
206+
207+
== Reproduce / see also
208+
209+
* `tools/estate-rs-audit/` — harness + captured data + how-to.
210+
* link:ECOSYSTEM.adoc[ECOSYSTEM.adoc] — the spine; #229 is its estate-port arm.
211+
* link:TECH-DEBT.adoc[TECH-DEBT.adoc] — coordination ledger.
212+
* #228 / link:specs/SETTLED-DECISIONS.adoc[ADR-014] — the unblocker.

docs/TECH-DEBT.adoc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,13 @@ EH proposal or CPS). The #225 CPS line closes the async slice. |S2 |partial
106106
|CORE-03 |ADR-014: module-qualified type/effect path. Decision settled
107107
(both `.`/`::` accepted, `Pkg::Type` canonical, `.`→`::` for free via the
108108
`::`-fold). Was the estate's dominant parse blocker (525/1177 .affine).
109-
*Grammar LANDED* (PR #241, Refs #228, gate 267/267, **zero Menhir
109+
*Grammar LANDED + MERGED* (PR #241, Refs #228, **zero Menhir
110110
conflict delta** — 21 S/R + 1 R/R unchanged); ADR-014 recorded in
111111
META.a2ml + SETTLED-DECISIONS.adoc. Supersedes DRAFT #231. |S1 |grammar
112-
in PR #241 (open); estate `.affine` re-audit + ReScript residue #229
113-
follow separately
112+
merged (#241). Post-#228 estate re-audit DONE — true #229 scope is
113+
~84 files/12 repos (not the 491 DRIFT; bulk is non-RS, out of contract);
114+
authoritative ledger + language-grounded canonical map + ESC-01..03
115+
escalations: link:RESCRIPT-ELIMINATION.adoc[RESCRIPT-ELIMINATION.adoc]
114116
|CORE-04 |Traits: associated-type substitution, where-clause supertraits,
115117
coherence checking. |S2 |partial
116118
|CORE-05 |Dependent/refinement types: predicate reduction / SMT. |S3

tools/estate-rs-audit/README.adoc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// SPDX-FileCopyrightText: 2024-2026 hyperpolymath
3+
= Estate ReScript-surface elimination — campaign infrastructure
4+
:toc: macro
5+
6+
Campaign tooling for issue #229 (total ReScript-surface elimination from every
7+
estate `.affine`). The authoritative findings, scope, and the canonical
8+
RS→AffineScript map live in link:../../docs/RESCRIPT-ELIMINATION.adoc[docs/RESCRIPT-ELIMINATION.adoc];
9+
this directory is the *reproducer*.
10+
11+
toc::[]
12+
13+
== Why this is in-repo
14+
15+
The oracle is the affinescript compiler itself. The audit is only meaningful
16+
against a specific compiler revision, so the harness, the repo list, and the
17+
captured results are versioned alongside the compiler that produced them. The
18+
prior throwaway home (`/tmp`, then `~/dev/repos/.affine-audit`) did not survive
19+
`/tmp` wipes and was not attributable to a compiler SHA — this is.
20+
21+
== Files
22+
23+
[cols="1,3"]
24+
|===
25+
|`audit.sh` |Per-repo: shallow-clone the default branch, run the oracle
26+
`main.exe check` on every `.affine`, classify on stdout
27+
(`PASS` / `DRIFT-SYNTAX` / `TYPE-ONLY`). Exit-code-blind by design (the oracle
28+
always returns 0; classification is on the first line of output).
29+
|`rs-inventory.sh` |Scans the *text* of every non-`PASS` file for the ReScript
30+
construct set named in #229. Text-scan, not oracle-classify: the oracle stops
31+
at the *first* parse error and hides the rest of a file's RS inventory.
32+
|`affine_repos.txt` |The estate repo list (NWO, one per line).
33+
|`data/results.post228.tsv` |The authoritative post-#228 (ADR-014 / #241 on
34+
`main`) re-audit. 552 PASS / 491 DRIFT-SYNTAX / 133 TYPE-ONLY over 1176 files.
35+
|`data/rs-inventory.tsv` |Per-file RS-construct inventory derived from the
36+
above. `<no-RS-construct:non-RS-drift>` marks DRIFT that is *not* #229 scope.
37+
|===
38+
39+
== Reproduce
40+
41+
[source,sh]
42+
----
43+
# 1. Build the oracle from the compiler revision under test
44+
cd <affinescript> && opam exec --switch=. -- dune build bin/main.exe
45+
46+
# 2. Re-audit (clones cached under .affine-audit/clones; same corpus = controlled)
47+
ORC=<affinescript>/_build/default/bin/main.exe \
48+
STDL=<affinescript>/stdlib \
49+
bash tools/estate-rs-audit/audit.sh
50+
51+
# 3. Rebuild the per-file RS construct inventory
52+
bash tools/estate-rs-audit/rs-inventory.sh
53+
----
54+
55+
NOTE: re-run against the *same cached clones* so an oracle change is measured
56+
in isolation (corpus drift would confound it). Refresh clones only for a
57+
deliberate new-corpus snapshot.
58+
59+
== Method note (honest scope)
60+
61+
`DRIFT-SYNTAX` is *not* a synonym for "ReScript surface". Most estate DRIFT is
62+
non-RS syntax drift (out of #229's contract). Only files with a detected RS
63+
construct in `data/rs-inventory.tsv` are #229 scope — see the ledger for the
64+
per-repo true-scope breakdown and the canonical map.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
hyperpolymath/accessibility-everywhere
2+
hyperpolymath/aerie
3+
hyperpolymath/affinescript
4+
hyperpolymath/airborne-submarine-squadron
5+
hyperpolymath/ambientops
6+
hyperpolymath/bofj-kitt
7+
hyperpolymath/burble
8+
hyperpolymath/cafescripto
9+
hyperpolymath/developer-ecosystem
10+
hyperpolymath/echidna
11+
hyperpolymath/game-server-admin
12+
hyperpolymath/git-scripts
13+
hyperpolymath/idaptik
14+
hyperpolymath/idaptik-dlc-vm
15+
hyperpolymath/invariant-path
16+
hyperpolymath/jaffascript
17+
hyperpolymath/lucidscript
18+
hyperpolymath/my-lang
19+
hyperpolymath/nextgen-language-evangeliser
20+
hyperpolymath/odds-and-sods-package-manager
21+
hyperpolymath/panll
22+
hyperpolymath/proof-burrower
23+
hyperpolymath/pseudoscript
24+
hyperpolymath/rattlescript
25+
hyperpolymath/standards
26+
hyperpolymath/stapeln
27+
hyperpolymath/tma-mark2
28+
hyperpolymath/ubicity

tools/estate-rs-audit/audit.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env bash
2+
# Estate AffineScript dialect-conformance audit driver.
3+
# Per repo: shallow-clone default branch, run the oracle `check` on every
4+
# .affine, classify on stdout text (rc is always 0).
5+
#
6+
# Durable home (survives /tmp wipes): /home/hyperpolymath/dev/repos/.affine-audit
7+
# Destined for affinescript tools/ as #229 campaign infrastructure.
8+
#
9+
# Env overrides:
10+
# ORC path to a built affinescript main.exe (the oracle)
11+
# STDL path to the matching stdlib dir
12+
set -u
13+
ORC=${ORC:-/home/hyperpolymath/dev/repos/affinescript/_build/default/bin/main.exe}
14+
export AFFINESCRIPT_STDLIB=${STDL:-/home/hyperpolymath/dev/repos/affinescript/stdlib}
15+
BASE=/home/hyperpolymath/dev/repos/.affine-audit
16+
WS="$BASE/clones"
17+
OUT="$BASE/results.tsv"
18+
REPOS="$BASE/affine_repos.txt"
19+
mkdir -p "$WS"
20+
: > "$OUT"
21+
22+
while read -r NWO; do
23+
[ -z "$NWO" ] && continue
24+
case "$NWO" in '{'*|*'rate limit'*) continue;; esac # skip stray API-error lines
25+
REPO=${NWO#hyperpolymath/}
26+
D="$WS/$REPO"
27+
if [ ! -d "$D/.git" ]; then
28+
git clone --depth 1 --quiet "https://github.com/$NWO.git" "$D" 2>/dev/null \
29+
|| { echo -e "$REPO\t<clone-failed>\tCLONE-FAIL\t-" >> "$OUT"; continue; }
30+
fi
31+
SHA=$(git -C "$D" rev-parse --short HEAD 2>/dev/null)
32+
mapfile -t FILES < <(find "$D" -name '*.affine' -type f 2>/dev/null | sort)
33+
if [ "${#FILES[@]}" -eq 0 ]; then
34+
echo -e "$REPO\t<none>\tNO-AFFINE\t$SHA" >> "$OUT"; continue
35+
fi
36+
for F in "${FILES[@]}"; do
37+
REL=${F#$D/}
38+
MSG=$("$ORC" check "$F" 2>&1 | head -1 | tr '\t' ' ' | cut -c1-180)
39+
if echo "$MSG" | grep -q "Type checking passed"; then
40+
CLASS=PASS
41+
elif echo "$MSG" | grep -qiE "parse error|Syntax error"; then
42+
CLASS=DRIFT-SYNTAX
43+
else
44+
CLASS=TYPE-ONLY
45+
fi
46+
echo -e "$REPO\t$REL\t$CLASS\t$MSG" >> "$OUT"
47+
done
48+
done < "$REPOS"
49+
50+
echo "AUDIT-COMPLETE $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$OUT"

0 commit comments

Comments
 (0)