Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/deed-conformance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# SPDX-License-Identifier: MPL-2.0
# Behavioural test for .deed support in actions/validate/validate-a2ml.sh.
#
# Deliberately bash-only: it must not depend on the Idris2 toolchain, so that
# it reports on the shell validator independently of the CLI build.
name: Deed Conformance

# This workflow only reads the tree and runs a bash test script: it does not
# post statuses, comment, or write to the repository. read-all grants every
# read scope there is (actions, packages, deployments, security events...);
# contents: read is the only one actually exercised.
permissions:
contents: read

on:
push:
paths:
- 'actions/validate/**'
- '.github/workflows/deed-conformance.yml'
pull_request:
paths:
- 'actions/validate/**'
- '.github/workflows/deed-conformance.yml'
workflow_dispatch:

jobs:
deed-conformance:
name: Deed fixtures — all four ruled heads
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
Comment thread
coderabbitai[bot] marked this conversation as resolved.
with:
# No step here pushes or otherwise uses the token, and this workflow
# runs on pull_request against repository-controlled code, so leaving
# the credential in .git/config is exposure with no upside (CWE-522).
persist-credentials: false
- name: Run deed conformance tests
run: bash actions/validate/conformance/run-deed-tests.sh
44 changes: 44 additions & 0 deletions actions/validate/conformance/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
= Deed Conformance Fixtures

// SPDX-License-Identifier: MPL-2.0

Behavioural fixtures for `.deed` support in link:../validate-a2ml.sh[validate-a2ml.sh].

== Why these exist

The gap they guard was invisible to every source-level survey. The discovery
glob matched only `'*.a2ml'`, so `.deed` files were never opened at all: the
validator reported no errors and exited 0 having validated nothing. String
presence of a regex is not behavioural acceptance — only running it settles it.

link:run-deed-tests.sh[run-deed-tests.sh] therefore asserts on the discovery
COUNT as well as the exit code, because `exit 0` is exactly what the defect
produced.

== Layout

* `valid/` — one fixture per ruled deed head (DEED-GRAMMAR-SPEC
`<<document-forms>>`): `estate-deed`, `repo-deed`, `praxis-deed`,
`estate-atlas-deed`. All four must pass, strict and non-strict.
+
`ATLAS.deed` carries `:registry-version` and deliberately no
`:canonical-name`: per `<<identity>>` the head symbol itself satisfies the
structural half of identity, so the atlas form must pass on its head alone.

* `invalid/` — `deed-missing-head.deed` (no ruled head and no identity keyword)
and `deed-missing-version.deed` (no `:schema-version`). Both are *deliberate*
negatives; a repo-wide scan will report them, which is the intended behaviour.

== Severity

This fork treats identity as a lint *warning* (see the script header on
standards#435), where `a2ml-ecosystem/validate-action` treats it as an error.
The tests here assert that a problem is *flagged*, not at which severity, so
they hold under either policy. Reconciling the two forks is a separate matter.

== Run

[source,sh]
----
bash actions/validate/conformance/run-deed-tests.sh
----
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
;; SPDX-License-Identifier: MPL-2.0
;; Negative fixture: @abstract is a contractile Xfile directive, not a deed
;; identity form. The head here is NOT one of the four ruled heads, so this
;; document must be reported as identity-less even though @abstract appears.
(not-a-ruled-head
:schema-version "1.0.0")

@abstract "this is not a deed identity"
8 changes: 8 additions & 0 deletions actions/validate/conformance/invalid/deed-head-not-first.deed
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: MPL-2.0

(some-other-form
:x "y")

(estate-deed
:schema-version "1.0.0")
4 changes: 4 additions & 0 deletions actions/validate/conformance/invalid/deed-missing-head.deed
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: CC-BY-SA-4.0
(some-other-form
:unrelated "value")
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: CC-BY-SA-4.0
(repo-deed
:canonical-name "no-version")
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: MPL-2.0

(estate-atlas-deed
:registry-version "3")
5 changes: 5 additions & 0 deletions actions/validate/conformance/invalid/example-AI-MANIFEST.deed
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: MPL-2.0

(not-a-head
:nothing "here")
103 changes: 103 additions & 0 deletions actions/validate/conformance/run-deed-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
# SPDX-License-Identifier: MPL-2.0
#
# Behavioural test for .deed support in validate-action/validate-a2ml.sh.
#
# This exists because the gap it guards was invisible to every source-level
# survey. The discovery glob matched only '*.a2ml', so .deed files were never
# opened at all: the validator reported "no errors" and exited 0 having
# validated nothing. String presence of a regex is not behavioural acceptance —
# only running it settles it. So this runs the validator, and it asserts on the
# discovery COUNT, because "exit 0" is exactly what the bug produced.
#
# The four valid fixtures are one per ruled deed head (DEED-GRAMMAR-SPEC
# <<document-forms>>): estate-deed, repo-deed, praxis-deed, estate-atlas-deed.
set -uo pipefail

HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VALIDATOR="${HERE}/../validate-a2ml.sh"
FAILURES=0

ok() { local msg="$1"; echo " PASS: $msg"; return 0; }
fail() { local msg="$1"; echo " FAIL: $msg" >&2; FAILURES=$((FAILURES + 1)); return 0; }

# The two diagnostics under test, named once so a wording change cannot leave
# an assertion quietly matching nothing.
NO_IDENTITY='No identity found'
NO_VERSION='Missing version or schema_version field'

# The conformance directories hold .a2ml fixtures too. Isolate the .deed ones
# so the discovery count is exact rather than incidental.
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
mkdir -p "$WORK/valid" "$WORK/invalid"
cp "$HERE"/valid/*.deed "$WORK/valid/"
cp "$HERE"/invalid/*.deed "$WORK/invalid/"

echo "1. valid deeds — all four ruled heads, non-strict"
out="$(INPUT_PATH="$WORK/valid" bash "$VALIDATOR" 2>&1)"; rc=$?
grep -q 'Found 4 ' <<<"$out" && ok "discovered 4 deed files" \
|| fail "discovery: '$(grep -o 'Found [0-9]* [^ ]* file(s)' <<<"$out")' (expected 4)"
[[ $rc -eq 0 ]] && ok "exit 0" || fail "exit $rc (expected 0)"
grep -q '::error' <<<"$out" && fail "unexpected error annotation" || ok "no errors"

echo "2. valid deeds — strict"
out="$(INPUT_PATH="$WORK/valid" INPUT_STRICT=true bash "$VALIDATOR" 2>&1)"; rc=$?
[[ $rc -eq 0 ]] && ok "exit 0 under strict" || fail "exit $rc under strict (expected 0)"

# assert_ann <severity> <fixture-regex> <message-substring>
# Anchored on the fixture AND the message: "the filename appears somewhere in
# the output" was satisfiable by any annotation at all, so a broken version
# check still passed. `file=[^,]*` keeps the path free but stops the regex
# wandering into the next annotation.
assert_ann() {
local severity="$1" fixture="$2" message="$3"
grep -qE "::$severity file=[^,]*$fixture,line=[0-9]+::.*$message" <<<"$out" \
&& ok "$fixture -> ::$severity ($message)" \
|| fail "$fixture: expected ::$severity matching '$message'"
return 0
}

echo "3. invalid deeds — non-strict: every diagnostic, per fixture"
out="$(INPUT_PATH="$WORK/invalid" bash "$VALIDATOR" 2>&1)"; rc=$?
grep -q 'Found 6 ' <<<"$out" && ok "discovered 6 deed files" \
|| fail "discovery: '$(grep -o 'Found [0-9]* [^ ]* file(s)' <<<"$out")' (expected 5)"
[[ $rc -eq 0 ]] && ok "exit 0 (identity and version are warnings here)" \
|| fail "exit $rc non-strict (expected 0)"
assert_ann warning 'deed-missing-head\.deed' "$NO_IDENTITY"
assert_ann warning 'deed-missing-head\.deed' "$NO_VERSION"
assert_ann warning 'deed-missing-version\.deed' "$NO_VERSION"
# :registry-version is optional atlas metadata, never a schema version.
assert_ann warning 'deed-registry-version-only\.deed' "$NO_VERSION"
# A head that is not the FIRST form does not identify the document.
assert_ann warning 'deed-head-not-first\.deed' "$NO_IDENTITY"
# @abstract is a contractile Xfile directive with no deed production. Matched in
# a .deed it satisfied identity for a document with no ruled head at all.
assert_ann warning 'deed-abstract-identity\.deed' "$NO_IDENTITY"
# The AI-MANIFEST exemption is for .a2ml prose; a .deed is still a deed.
assert_ann warning 'example-AI-MANIFEST\.deed' "$NO_IDENTITY"
assert_ann warning 'example-AI-MANIFEST\.deed' "$NO_VERSION"
# Negative control: a diagnostic naming a fixture that has none would mean the
# anchoring above is matching across annotation boundaries.
grep -qE "::warning file=[^,]*deed-registry-version-only\.deed,line=[0-9]+::$NO_IDENTITY" <<<"$out" \
&& fail "atlas head wrongly reported identity-less" || ok "atlas head still identifies"

echo "4. invalid deeds — strict promotes every warning to an error"

Check warning on line 86 in actions/validate/conformance/run-deed-tests.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Redirect this error message to stderr (>&2).

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_a2ml2&issues=AaCFXCg4WhieGMaCTpQA&open=AaCFXCg4WhieGMaCTpQA&pullRequest=3
out="$(INPUT_PATH="$WORK/invalid" INPUT_STRICT=true bash "$VALIDATOR" 2>&1)"; rc=$?
[[ $rc -ne 0 ]] && ok "non-zero exit under strict" || fail "exit 0 under strict (expected non-zero)"
assert_ann error 'deed-missing-head\.deed' "$NO_IDENTITY"
assert_ann error 'deed-missing-version\.deed' "$NO_VERSION"
assert_ann error 'deed-registry-version-only\.deed' "$NO_VERSION"
assert_ann error 'deed-head-not-first\.deed' "$NO_IDENTITY"
assert_ann error 'deed-abstract-identity\.deed' "$NO_IDENTITY"
assert_ann error 'example-AI-MANIFEST\.deed' "$NO_VERSION"
grep -q '::warning' <<<"$out" && fail "::warning survived strict" || ok "no ::warning survives strict"

echo
if [[ $FAILURES -eq 0 ]]; then
echo "All deed validator tests passed."
else
echo "${FAILURES} deed validator test(s) failed." >&2
exit 1
fi
5 changes: 5 additions & 0 deletions actions/validate/conformance/valid/ATLAS.deed
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: CC-BY-SA-4.0
(estate-atlas-deed
:schema-version "1.0.0"
:registry-version "3")
8 changes: 8 additions & 0 deletions actions/validate/conformance/valid/cadastre_praxis.deed
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: CC-BY-SA-4.0
(praxis-deed
:schema-version "1.0.0"
:canonical-name "cadastre"
:beholding-chora #u5"estate/chora"
(rules
(rule :priority 10)))
7 changes: 7 additions & 0 deletions actions/validate/conformance/valid/estate_chora.deed
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: CC-BY-SA-4.0
(estate-deed
:schema-version "1.0.0"
:canonical-name "estate"
(vocabulary
(term :name "chora" :gloss "a place with a role")))
6 changes: 6 additions & 0 deletions actions/validate/conformance/valid/vexometer_chora.deed
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
;; SPDX-FileCopyrightText: © 2026 Jonathan D.A. Jewell (hyperpolymath)
;; SPDX-License-Identifier: CC-BY-SA-4.0
(repo-deed
:schema-version "1.0.0"
:canonical-name "vexometer"
:beholding-chora #u5"estate/chora")
Loading
Loading