Add A2ML Record Dialect specification + conformance vectors (#456) #731
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-License-Identifier: MPL-2.0 | |
| # | |
| # OPTIONAL: BoJ Server Build Trigger | |
| # This workflow notifies a BoJ Server instance when code is pushed. | |
| # It is a no-op if BOJ_SERVER_URL is not set or the server is unreachable. | |
| # To enable: set BOJ_SERVER_URL as a repository secret or variable. | |
| # To disable: delete this file or leave BOJ_SERVER_URL unset. | |
| name: BoJ Server Build Trigger | |
| on: | |
| push: | |
| branches: [main, master] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| trigger-boj: | |
| name: Trigger BoJ server | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| # No job-level gate: the `secrets` context is not available in `if:` | |
| # (referencing it is an "Unrecognized named-value: 'secrets'" startup | |
| # failure). The Trigger step below already self-gates — it exits 0 when | |
| # BOJ_URL (secret-or-var) is empty — so the whole job is a cheap no-op | |
| # when unconfigured. | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Trigger BoJ Server (Casket/ssg-mcp) | |
| env: | |
| BOJ_URL: ${{ secrets.BOJ_SERVER_URL || vars.BOJ_SERVER_URL }} | |
| REPO_NAME: ${{ github.repository }} | |
| BRANCH_NAME: ${{ github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "$BOJ_URL" ]; then | |
| echo "BOJ_SERVER_URL not configured - skipping" | |
| exit 0 | |
| fi | |
| payload="$(jq -cn \ | |
| --arg repo "$REPO_NAME" \ | |
| --arg branch "$BRANCH_NAME" \ | |
| --arg engine "casket" \ | |
| '{repo:$repo, branch:$branch, engine:$engine}')" | |
| curl -sf -X POST "${BOJ_URL}/cartridges/ssg-mcp/invoke" \ | |
| -H "Content-Type: application/json" \ | |
| --data "$payload" \ | |
| || echo "BoJ server unreachable - skipping (non-fatal)" | |
| # Contractile validation runs on every push, independent of whether a BoJ | |
| # server is configured — it validates THIS repo's own contractile set, so it | |
| # must not sit behind the trigger-boj `if:` guard. | |
| validate-contractiles: | |
| name: K9-SVC contractile validation | |
| timeout-minutes: 10 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: K9-SVC Validation | |
| run: | | |
| set -euo pipefail | |
| echo "Running K9-SVC contractile validation..." | |
| # Real structural validation (no placeholder): every Mustfile check | |
| # must carry a severity and a means of discharge (run or verification). | |
| # A hollow check fails loudly. See scripts/check-mustfile-structure.sh | |
| # (unit-tested by scripts/tests/wave0-false-green-test.sh). | |
| bash scripts/check-mustfile-structure.sh | |
| - name: Mustfile Enforcement (execute the checks) | |
| run: | | |
| set -euo pipefail | |
| # Execute the Mustfile's `- run:` invariants — the mandatory checks | |
| # that were previously declared but never run by any CI job. A failing | |
| # critical/high check fails the build (fail loudly); warning-severity | |
| # failures are reported but non-blocking. See scripts/run-mustfile.sh. | |
| bash scripts/run-mustfile.sh | |
| - name: Contractile Check | |
| run: | | |
| set -euo pipefail | |
| echo "Checking contractile completeness..." | |
| index=".machine_readable/contractiles/INDEX.a2ml" | |
| if [ ! -f "$index" ]; then | |
| echo "❌ Contractile registry not found: $index" | |
| exit 1 | |
| fi | |
| # Read the canonical verb set from the registry rather than hard-coding | |
| # it (INDEX.a2ml §Registry: consumers SHOULD discover verbs from here). | |
| # Each verb's trident lists "<verb>/<Verb>file.a2ml" as its first entry. | |
| mapfile -t files < <(grep -oE '"[a-z]+/[A-Z][a-z]+file\.a2ml"' "$index" | tr -d '"' | sort -u) | |
| if [ "${#files[@]}" -eq 0 ]; then | |
| echo "❌ No contractile files discovered in $index" | |
| exit 1 | |
| fi | |
| missing=0 | |
| for rel in "${files[@]}"; do | |
| if [ -f ".machine_readable/contractiles/$rel" ]; then | |
| echo "✅ $rel" | |
| else | |
| echo "❌ Missing: $rel" | |
| missing=$((missing + 1)) | |
| fi | |
| done | |
| if [ "$missing" -gt 0 ]; then | |
| echo "❌ $missing contractile(s) missing" | |
| exit 1 | |
| fi | |
| echo "✅ All ${#files[@]} contractiles present" |