Skip to content

A2ML: dialect architecture + the manifest-dialect spec (59% of the corpus) - #569

Merged
hyperpolymath merged 3 commits into
mainfrom
docs/a2ml-dialect-architecture
Aug 3, 2026
Merged

A2ML: dialect architecture + the manifest-dialect spec (59% of the corpus)#569
hyperpolymath merged 3 commits into
mainfrom
docs/a2ml-dialect-architecture

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

A design record, not a change to anything validated. It exists so the next person starts from the architecture rather than rediscovering it from 1,543 files.

The architecture is already real — the spec just doesn't say so

SPEC.adoc §3.1 already makes the Idris2 model in a2ml/src/A2ML/ authoritative and the prose shape informative. Eleven modules implement it, and the presence of Surface.idr and Translator.idr and Converters.idr is itself the evidence: the design always assumed several surfaces mapping onto one core.

   surface dialects                canonical form
   markup    (@directive)  ─┐
   record    ([section])   ─┼──▶   Idris2 typed core   ──▶  proofs, attestation
   manifest  (--- YAML)    ─┘      a2ml/src/A2ML/

So A2ML is a typed core with surface projections, not a markup format with variants. A surface is legitimate exactly when it defines a translation into the core — which makes new surfaces additive rather than fragmenting, and is why leaving one unspecified is the actual problem.

Census, re-measured 2026-08-03

1,543 .a2ml files, classified by first non-comment non-blank line:

Dialect Files Specified by
manifest (--- frontmatter) 913 nothing
record ([section]) 376 RECORD-DIALECT-SPEC.adoc
markup (@directive) 139 SPEC.adoc §2
unclassified 115

The manifest dialect is 59% of the corpus and has no grammar. grep -niE 'frontmatter|yaml' across both specs returns zero hits, and SPEC.adoc §2 has no key-value production at all.

An earlier census reported 906/456/154. Totals agree at 1,543 and the ordering is unchanged; the difference is that this pass separates the unclassified group. Both figures are recorded so neither looks authoritative on its own.

New finding: 27 of the 115 unclassified files open with ; or ;; — Scheme/Lisp comment syntax. A small s-expression-shaped population exists that neither spec counts. That strengthens the family-type design: surfaces accrete whether or not a spec permits them.

Why it blocks IANA

The registration (Revision 2, 2026-04-03) declares application/vnd.a2ml with charset as its only optional parameter. Submitting it would point IANA at a specification that does not describe 59% of its own corpus, and give a recipient no way to know which grammar a document follows.

Worse — three other media-type forms are already written down across the repo, none matching the registration:

Form Files
application/vnd.a2ml+text 2
text/a2ml 3
application/vnd.{format}+a2ml 2

The fix — mostly already decided

RECORD-DIALECT-SPEC.adoc §14 recommends a dialect= parameter on one family type rather than separate types, and explicitly declines to impose it alone. This document takes that up:

  1. Write MANIFEST-DIALECT-SPEC.adocthe only substantial new writing
  2. Promote SPEC.adoc to family root: name the core canonical, name the dialects, define dialect=, state the translation rule
  3. Add dialect= to the registration and reconcile the three stale forms
  4. Then submit

K9 supplies the precedent: it already registers an optional parameter — security-level, default kennel, advisory on the wire and authoritative in the document. dialect= should follow that shape exactly.

K9 has an independent blocker — found while checking that precedent

says
k9-svc/IANA-MEDIA-TYPE-APPLICATION.md registers application/vnd.k9 without a structured syntax suffix
k9-svc/SPEC.adoc line 34 Standard ID | application/vnd.k9+nickel

The spec and the application disagree on the media type, on current main. That's a live contradiction, not a design question, and it must be settled before K9 submits.

Note also that the mandatory K9! magic line is not valid Nickel, so a .k9.ncl file isn't parseable by a stock Nickel toolchain — which argues for dropping +nickel, since the suffix implies exactly that parseability.

Verified, not asserted

Every path cited exists. The validator exemption is quoted from a2ml/actions/validate/validate-a2ml.sh lines 20–26 and 151–156; the "435 files … conform to a grammar that existed only by imitation" quote is RECORD-DIALECT-SPEC.adoc lines 23–24; the three stale media-type strings were counted, not remembered.

Two claims failed verification while drafting and were corrected rather than shipped: the validator path (it's under a2ml/actions/validate/, not .githooks/), and the census figures.

Deliberately not done

Writing the manifest grammar. That needs the corpus surveyed for the YAML constructs actually used first — a permissive spec written blind is much harder to narrow later than a narrow one is to widen.

🤖 Generated with Claude Code

…submission

A design record, not a change to anything validated. It exists so the next
person starts from the architecture rather than rediscovering it from 1,543
files.

== The architecture is already real; the spec does not say so

SPEC.adoc §3.1 already makes the Idris2 model in a2ml/src/A2ML/ authoritative
and the prose shape informative. Eleven modules implement it, and the presence
of Surface.idr AND Translator.idr AND Converters.idr is itself the evidence that
the design always assumed several surfaces mapping onto one core.

So A2ML is a typed core with surface projections, not a markup format with
variants. A surface is legitimate exactly when it defines a translation into the
core. That rule makes new surfaces additive rather than fragmenting, and it is
why leaving one unspecified is the actual problem.

== Census, re-measured 2026-08-03

1,543 .a2ml files, classified by first non-comment non-blank line:

    manifest   (--- frontmatter)   913   specified by NOTHING
    record     ([section])         376   RECORD-DIALECT-SPEC.adoc
    markup     (@directive)        139   SPEC.adoc §2
    unclassified                   115   see below

The manifest dialect is 59% of the corpus and has no grammar. `grep -niE
'frontmatter|yaml'` across both specs returns zero hits, and SPEC.adoc §2 has no
key-value production at all.

An earlier census reported 906/456/154. Totals agree at 1,543 and the ordering is
unchanged; the difference is that this pass separates the unclassified group.
Both are recorded so neither figure looks authoritative on its own.

New finding: 27 of the 115 unclassified files open with `;` or `;;` — Scheme/Lisp
comment syntax. A small s-expression-shaped population exists that neither
written spec counts. That strengthens the family-type design rather than
complicating it: surfaces accrete whether or not a spec permits them.

== Why it blocks IANA

The registration (Revision 2, 2026-04-03) declares application/vnd.a2ml with
`charset` as the only optional parameter. Submitting it would point IANA at a
specification that does not describe 59% of its own corpus, and give a recipient
no way to know which grammar a document follows.

Worse, three OTHER media-type forms are already written down across the repo —
application/vnd.a2ml+text (2 files), text/a2ml (3), application/vnd.{format}+a2ml
(2) — none matching the registration. Reconciling those is part of the same pass.

== The fix, which is mostly already decided

RECORD-DIALECT-SPEC.adoc §14 recommends a `dialect=` parameter on one family type
rather than separate types, and explicitly declines to impose it alone. This
document takes that up:

  1. Write MANIFEST-DIALECT-SPEC.adoc — the only substantial new writing.
  2. Promote SPEC.adoc to family root: name the core canonical, name the
     dialects, define `dialect=`, state the translation rule.
  3. Add dialect= to the registration and reconcile the three stale forms.
  4. Then submit.

K9 supplies the precedent: it already registers an optional parameter
(`security-level`, default `kennel`, advisory on the wire and authoritative in
the document). dialect= should follow that shape exactly.

== K9 has an independent blocker, found while checking the precedent

k9-svc/IANA-MEDIA-TYPE-APPLICATION.md says it "registers application/vnd.k9
without a structured syntax suffix". k9-svc/SPEC.adoc line 34 still declares
`application/vnd.k9+nickel`. The spec and the application disagree on the media
type, on current main. That is a live contradiction, not a design question, and
it must be settled before K9 submits.

Note also that the mandatory `K9!` magic line is not valid Nickel, so a .k9.ncl
file is not parseable by a stock Nickel toolchain — which argues for dropping
`+nickel`, since the suffix implies exactly that parseability.

== Verified, not asserted

Every path cited exists; the validator exemption is quoted from
a2ml/actions/validate/validate-a2ml.sh lines 20-26 and 151-156; the "435 files
... conform to a grammar that existed only by imitation" quote is
RECORD-DIALECT-SPEC.adoc lines 23-24; the three stale media-type strings were
counted, not remembered.

Deliberately NOT done: writing the manifest grammar. That needs the corpus
surveyed for the YAML constructs actually used first — a permissive spec written
blind is harder to narrow than a narrow one is to widen.
@gitar-bot

gitar-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

Note

Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime.
Learn more

Code Review ✅ Approved

Documents the A2ML dialect architecture and identifies the missing manifest grammar blocking IANA submission. No issues found.

Auto-approved and auto-merge armed: No blocking issues found.
Please see Auto-approve Docs for details on setting custom approval criteria. — merges when pipeline and required approvals pass.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Important

Your trial ends in 7 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more.

Was this helpful? React with 👍 / 👎 | Gitar

@gitar-bot
gitar-bot Bot enabled auto-merge (squash) August 3, 2026 18:23
@gitar-bot gitar-bot Bot added the gitar-approved Added by Gitar label Aug 3, 2026
gitar-bot[bot]
gitar-bot Bot previously approved these changes Aug 3, 2026

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gitar has auto-approved this PR and enabled auto-merge (configure)

The largest A2ML surface in the estate had no specification. SPEC.adoc §2 has no
key-value production and neither spec mentions frontmatter, so 894 files
conformed to a grammar that existed only by imitation — the same condition
RECORD-DIALECT-SPEC.adoc was written to fix for the record dialect, at twice the
size.

Written from a census, not from YAML. Every rule traces to a measured count.

== What the corpus actually uses

    key: value            2706        double-quoted        1799
    integer                880        block sequence (- )    29
    comment                893        block scalar (| >)      2
    nested (indented)       19        flow seq [..]           2
    bare scalar              6

    indent widths: 0 (2684), 4 (15), 2 (7)     29 distinct keys

And what it does NOT use, anywhere in 894 files:

    anchors &     0      aliases *      0      tags !        0
    flow maps {}  0      single quotes  0      multi-doc     0

Excluding those is not a restriction, it is a description — and it closes the
three constructs most often implicated in YAML parser differentials for free.
Anchors and aliases also defeat attestation over a canonical hash form, since
they make a document's meaning non-local.

== A spec bug the validator caught

The first draft admitted the block-scalar introducer `|` but said nothing about
its continuation lines, so the validator rejected Trustfile.a2ml:

    signature: |
          -----BEGIN HYBRID SIGNATURE-----
          BASE64_Ed448+Dilithium5_SIGNATURE_OF_THIS_FILE
          -----END HYBRID SIGNATURE-----

A grammar that admits `|` but not its content rejects precisely the construct
A2ML exists to carry. §4 now defines `block-body` as opaque: a `#` inside one is
signature data, and a `---` inside one does not close the frontmatter.

Corpus conformance went 893/894 -> 894/894. This is why the spec was written
against a running validator rather than by inspection.

== The 19 "malformed" files are not this dialect

Nineteen files open `---` after their header and never close it. A naive
classifier calls them broken manifests. They are not: 7 use `key = value`
(record dialect) and 12 use `## heading` (markup), with `---` as a horizontal
rule.

So `---` is AMBIGUOUS ACROSS DIALECTS. §8 resolves it one way — in the manifest
dialect a leading `---` opens frontmatter — and records that the family root
must say which dialect claims the token in first position. The 19 files are
listed as a known fix, not a surprise.

== Reference validator

a2ml/actions/validate/validate-manifest-dialect.py — 894/894 conforming, exits
non-zero on failure so it can gate CI.

Proved it can fail: injecting a YAML anchor into one file gives 893/894 and
exit 1; removing it returns exit 0.

== Deliberately not done

Fixing the vocabulary. Key semantics belong to the base record vocabulary and the
profile mechanism in SPEC.adoc; this document specifies only the surface.

Removing the AI-MANIFEST exemption in validate-a2ml.sh. It should go now that a
grammar exists, but that is a behaviour change to a gate the estate runs, and it
belongs in its own commit. Tracked in §9.
@hyperpolymath hyperpolymath changed the title A2ML dialect architecture — and what actually blocks the IANA submission A2ML: dialect architecture + the manifest-dialect spec (59% of the corpus) Aug 3, 2026
@hyperpolymath

Copy link
Copy Markdown
Owner Author

Update — the manifest dialect is now specified

The one substantial piece of writing this PR originally deferred is done: a2ml/MANIFEST-DIALECT-SPEC.adoc, plus a reference validator.

Written from a census, not from YAML

Every rule traces to a measured count across the 894 well-formed files:

construct count construct count
key: value 2,706 double-quoted 1,799
integer 880 comment 893
block sequence - 29 nested (indented) 19
bare scalar 6 block scalar | > 2

And what the corpus does not contain, anywhere:

anchors & 0 · aliases * 0 · tags ! 0 · flow maps {} 0 · single quotes 0 · multi-doc 0

Excluding those isn't a restriction — it's a description. It also closes the three constructs most often implicated in YAML parser differentials, for free. Anchors and aliases additionally defeat attestation over a canonical hash form, since they make a document's meaning non-local.

The validator caught a spec bug

The first draft admitted the block-scalar introducer | but said nothing about its continuation lines, so it rejected Trustfile.a2ml:

signature: |
      -----BEGIN HYBRID SIGNATURE-----
      BASE64_Ed448+Dilithium5_SIGNATURE_OF_THIS_FILE
      -----END HYBRID SIGNATURE-----

A grammar that admits | but not its content rejects precisely the construct A2ML exists to carry. §4 now defines block-body as opaque — a # inside one is signature data, and a --- inside one does not close the frontmatter.

Corpus conformance: 893/894 → 894/894. That's why the spec was written against a running validator rather than by inspection.

The 19 "malformed" files are a different dialect

Nineteen files open --- and never close it. A naive classifier calls them broken manifests. They aren't — 7 use key = value (record) and 12 use ## heading (markup), with --- as a horizontal rule.

So --- is ambiguous across dialects. §8 resolves it one way for this dialect and records that the family root must declare which dialect claims the token in first position. The 19 are listed as a known fix.

Reference validator

a2ml/actions/validate/validate-manifest-dialect.py894/894, exits non-zero on failure so it can gate CI.

Proved it can fail: injecting a YAML anchor gives 893/894 and exit 1; removing it returns exit 0.

Remaining before submission

Write the manifest spec ✅ this update
Promote SPEC.adoc to family root open
Add dialect= + reconcile 3 stale media-type forms open
Resolve the K9 spec/application contradiction open
Remove the AI-MANIFEST exemption from validate-a2ml.sh open — behaviour change to a live gate, deserves its own commit

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
@hyperpolymath
hyperpolymath disabled auto-merge August 3, 2026 18:37
@hyperpolymath
hyperpolymath merged commit 5a59772 into main Aug 3, 2026
19 of 26 checks passed
@hyperpolymath
hyperpolymath deleted the docs/a2ml-dialect-architecture branch August 3, 2026 18:37
@sonarqubecloud

sonarqubecloud Bot commented Aug 3, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gitar-approved Added by Gitar

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants