Repository navigation
Exploration: .affex — face-bridging file format for cross-exolanguage interop #84
Copy link
Copy link
Closed
Labels
enhancementNew capability or improvement to existing behaviourNew capability or improvement to existing behaviourmajorMajor issue — significant scope, broader impact than a feature/bugMajor issue — significant scope, broader impact than a feature/bugquestionFurther information is requestedFurther information is requestedrequirements-targetRequirements-target issue — only closes when Claude and user mutually agree the spec is satisfiedRequirements-target issue — only closes when Claude and user mutually agree the spec is satisfied
Description
Activity
- addedenhancementNew capability or improvement to existing behaviourNew capability or improvement to existing behaviourquestionFurther information is requestedFurther information is requestedmajorMajor issue — significant scope, broader impact than a feature/bugMajor issue — significant scope, broader impact than a feature/bugrequirements-targetRequirements-target issue — only closes when Claude and user mutually agree the spec is satisfiedRequirements-target issue — only closes when Claude and user mutually agree the spec is satisfied
on May 3, 2026 Spec draft: PR #93 (
docs/specs/affex-spec.md)After reviewing the four speculative shapes, I went with Shape 3 (face-interop manifest) as the primary form. Short rationale:
- The compiler already holds the canonical↔face bijection through the lowering pass — a manifest captures this once, keeping
.affexfiles small and non-redundant - Shape 1 (side-by-side listing) becomes a derived CLI output (
affinescript affex diff) rather than a stored artifact - Shape 3 maps directly to LSP use: hover tooltips and document outline can render in any reader face without storing N source copies
Key decisions in the draft:
- Tooling-only — compiler (
check,compile,eval) does not parse.affex - Per-package scope — one
<package>.affexat the package root affex/1JSON format — per-declaration, per-face signature renderings with body digests and hand-written override blocks- Three CLI subcommands:
generate,render,diff - LSP integration: reader-face rendering in hover/outline; does not rewrite source
PR #93 has explicit satisfaction criteria at §9. To close this issue per the requirements-target rule: please review the spec and, if it looks good, reply here with explicit agreement (or redirect with what needs to change). I'll match your agreement with mine and we can close.
Four open questions in §8 are flagged for your decision — the most load-bearing one is whether
headrendering should use the compiler's pretty-printer or store the raw source span.- The compiler already holds the canonical↔face bijection through the lowering pass — a manifest captures this once, keeping
- added a commit that references this issue
on May 11, 2026 - added a commit that references this issue
on May 11, 2026
Metadata
Metadata
Assignees
Labels
enhancementNew capability or improvement to existing behaviourNew capability or improvement to existing behaviourmajorMajor issue — significant scope, broader impact than a feature/bugMajor issue — significant scope, broader impact than a feature/bugquestionFurther information is requestedFurther information is requestedrequirements-targetRequirements-target issue — only closes when Claude and user mutually agree the spec is satisfiedRequirements-target issue — only closes when Claude and user mutually agree the spec is satisfied
Type: Exploration / sketch idea, not yet specified.
Surfaced by: cross-referenced from
hyperpolymath/accessibility-everywherePR #16 work, 2026-05-03. Externalising it here so it survives across Claude Code sessions and can be developed in a dedicated thread.Problem statement
AffineScript supports multiple faces (canonical, cafe, jaffa, lucid, pseudo, rattle, …). All faces lower to canonical, so the compiler doesn't care — but humans reading code in a face they don't speak are stuck.
The friction shows up:
Half-recalled sketch idea:
.affexOriginal framing (user, paraphrased): a file extension and file type —
.affex= "affine exolanguage", in the sense that the named faces (rattle, lucid, etc.) are exolanguage variants of canonical AffineScript. The file format would have properties analogous to ABI/FFI conventions, but applied between AffineScript faces rather than between distinct languages.Goals:
.affinefiles for the programmer using their preferred face — no need to leave their face to interop.Speculative shapes (not specified, just where the design space looks open)
These are Claude's extrapolations from the problem statement — not part of the original sketch — to seed the dedicated discussion thread:
.affexfile holds the same source in N faces side-by-side (or as a primary face + per-other-face footnotes). Reader picks the column they speak. Auto-generatable from the lowering pass since the compiler already has the bidirectional info..affexfile pairs face source with the canonical AST it lowers to, with shape correspondences marked (which canonical decl maps to which face span). Helps a reader translate small windows on demand instead of the whole file..affexdeclares how a face's idioms (e.g. rattle's indentation blocks) correspond to canonical structures, so tooling can render any.affinein any reader-preferred face. The "ABI" analogue: contract for round-tripping syntax..affexfile can both be hand-written (for tricky cross-face boundaries the compiler can't auto-generate cleanly) and be auto-generated (for bulk).Where this fits in the cardinal stance
The cardinal stance for the AffineScript ecosystem is "affine is the heart" — canonical is the centre, faces are peripheral.
.affexreinforces rather than competes with this: canonical stays the lowering target, faces remain surface conveniences, and.affexis a strictly additive bridging layer that makes the periphery liveable without diluting the core.What this is NOT
Externs.affineshims in the accessibility-everywhere migration..affexdoes not solve or replace that..affexonly earns its keep once an estate has multi-face adoption..affex. The audience is humans.What's needed before this can be built
.affexparsed by the compiler at all, or is it a docs/tooling artifact only?Status
Parked. Not blocking any migration. Will be developed in a dedicated thread when a concrete trigger surfaces (probably first multi-face adoption inside an estate).
🤖 Drafted by Claude Code in a session where the original sketch resurfaced; externalised to this issue so it cannot get lost again. See
feedback_affinescript_conventions.md"mentioned-but-undefined" section in the user's auto-memory for the local pointer.