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
8 changes: 2 additions & 6 deletions .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@ if has asdf; then
use asdf
fi

# Load Guix shell if guix.scm exists
if has guix && [ -f guix.scm ]; then
# Load Guix shell if a Guix manifest exists (Nix is deprecated)
if has guix && { [ -f build/guix.scm ] || [ -f guix.scm ]; }; then
use guix
fi

# Load Nix flake if flake.nix exists
if has nix && [ -f flake.nix ]; then
fi

# Project environment variables
export PROJECT_NAME="Panoply"
export RSR_TIER="infrastructure"
Expand Down
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*.hs text eol=lf
*.chpl text eol=lf
*.scm text eol=lf
*.a2ml text eol=lf linguist-language=TOML
*.deed text eol=lf linguist-language=TOML
*.ncl text eol=lf
*.nix text eol=lf

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
# Security-sensitive files require explicit review
SECURITY.md @hyperpolymath
.github/workflows/ @hyperpolymath
Trustfile.a2ml @hyperpolymath
Trustfile.deed @hyperpolymath
.machine_readable/ @hyperpolymath
4 changes: 2 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ panoply/
├── spec/ # Spec tests (Perimeter 3)
├── tests/ # Test suite (Perimeter 2-3)
├── .machine_readable/ # ALL machine-readable content (Perimeter 1)
│ ├── *.a2ml # State files (STATE, META, ECOSYSTEM, etc.)
│ ├── *.deed # State files (STATE, META, ECOSYSTEM, etc.)
│ ├── bot_directives/ # Bot configs
│ └── contractiles/ # Policy contracts (k9, dust, lust, must, trust)
├── .well-known/ # Protocol files (Perimeter 1-3)
Expand All @@ -49,7 +49,7 @@ panoply/
├── MAINTAINERS.md
├── README.adoc
├── SECURITY.md
├── flake.nix # Nix flake — fallback (Perimeter 1)
├── build/guix.scm # Guix manifest + channels (Perimeter 1)
├── guix.scm # Guix package — primary (Perimeter 1)
└── Justfile # Task runner (Perimeter 1)
```
Expand Down
2 changes: 1 addition & 1 deletion .github/GOVERNANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ release schedules, contributor access, and community standards.
- ADR statuses: `proposed`, `accepted`, `deprecated`, `superseded`, `rejected`.
- ADRs provide a historical record of why decisions were made and what alternatives
were considered.
- See `.machine_readable/6a2/META.a2ml` for the machine-readable ADR index.
- See `.machine_readable/6a2/META.deed` for the machine-readable ADR index.

---

Expand Down
6 changes: 3 additions & 3 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>

## Before Writing Code

- Read `0-AI-MANIFEST.a2ml` in the repo root for canonical file locations.
- State files (.a2ml) live in `.machine_readable/` ONLY, never the root.
- Read `0-AI-MANIFEST.deed` in the repo root for canonical file locations.
- State files (.deed) live in `.machine_readable/` ONLY, never the root.

## License

Expand Down Expand Up @@ -56,5 +56,5 @@ Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
## State Files

Never create these in the repo root:
STATE.a2ml, META.a2ml, ECOSYSTEM.a2ml, AGENTIC.a2ml, NEUROSYM.a2ml, PLAYBOOK.a2ml.
STATE.deed, META.deed, ECOSYSTEM.deed, AGENTIC.deed, NEUROSYM.deed, PLAYBOOK.deed.
They belong in `.machine_readable/` only.
40 changes: 20 additions & 20 deletions .github/hooks/validate-a2ml.sh → .github/hooks/validate-deed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# validate-a2ml.sh — A2ML manifest validation script
#
# Scans for .a2ml and .deed files and validates:
# Scans for .deed and .deed files and validates:
# 1. Required fields: agent-id or pedigree name, version
# 2. SPDX-License-Identifier header presence
# 3. Attestation block structure (if present)
Expand Down Expand Up @@ -89,7 +89,7 @@
}

# ---------------------------------------------------------------------------
# Validator: check a single .a2ml or .deed file
# Validator: check a single .deed or .deed file
# ---------------------------------------------------------------------------
validate_a2ml() {
local file="$1"
Expand Down Expand Up @@ -120,7 +120,7 @@
# - agent-id = "..." or agent_id = "..."
# - pedigree block with name field
# - name = "..." at top level (for AI manifests)
# - project = "..." (for STATE.a2ml)
# - project = "..." (for STATE.deed)
local has_identity=false
local has_version=false
local first_form_seen=false
Expand Down Expand Up @@ -201,39 +201,39 @@
fi
done < "$file"

# AI manifest files (0-AI-MANIFEST.a2ml, 0.1-AI-MANIFEST.a2ml, etc.)
# AI manifest files (0-AI-MANIFEST.deed, 0.1-AI-MANIFEST.deed, etc.)
# use markdown-style headers and free text, so identity check is relaxed
local basename
basename="$(basename "$file")"
local is_manifest=false
# `.a2ml` ONLY. The exemption exists because AI manifests are markdown-ish
# `.deed` ONLY. The exemption exists because AI manifests are markdown-ish
# prose with no in-file identity; it is not a property of the name. Matching
# the bare basename meant `example-AI-MANIFEST.deed` was exempted from BOTH
# the identity and version checks — a deed that skipped the whole gate.
if [[ "$basename" == *"AI-MANIFEST"*.a2ml ]]; then
if [[ "$basename" == *"AI-MANIFEST"*.deed ]]; then
is_manifest=true
fi
# Canonical typed manifests under <machine tree>/descriptiles/ — identity comes
# from the enclosing directory + filename, not an in-file field. Sibling
# files in the same directory (ECOSYSTEM.a2ml, STATE.a2ml) DO carry their
# files in the same directory (ECOSYSTEM.deed, STATE.deed) DO carry their
# own $name/project and continue to be validated normally.
case "$basename" in

Check failure on line 220 in .github/hooks/validate-deed.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a default case (*) to handle unexpected values.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_panoply&issues=AaC-trf5Rffk6HRCi1wc&open=AaC-trf5Rffk6HRCi1wc&pullRequest=66
AGENTIC.a2ml|META.a2ml|NEUROSYM.a2ml|PLAYBOOK.a2ml|AI.a2ml)
# AI.a2ml = free-text "AI Assistant Instructions" manifest, the same
# doc type as 0-AI-MANIFEST.a2ml but with the bare name; identity is
AGENTIC.deed|META.deed|NEUROSYM.deed|PLAYBOOK.deed|AI.deed)
# AI.deed = free-text "AI Assistant Instructions" manifest, the same
# doc type as 0-AI-MANIFEST.deed but with the bare name; identity is
# carried by the enclosing repo/plugin dir, not an in-file field.
is_manifest=true
;;
# Dockerfile-style top-level typed manifests (Intentfile, Trustfile, …)
# use markdown-flavoured A2ML; identity is carried by the parent repo.
*file.a2ml)
*file.deed)
is_manifest=true
;;
esac

# Contractile-shape A2ML files use `@directive:` syntax instead of
# TOML `key = value`. Trustfile.a2ml, Intentfile.a2ml, Mustfile.a2ml,
# Adjustfile.a2ml etc. are policy / trust / intent / abstract files
# TOML `key = value`. Trustfile.deed, Intentfile.deed, Mustfile.deed,
# Adjustfile.deed etc. are policy / trust / intent / abstract files
# whose identity is implicit in their @-prefixed directives
# (`@trust-level`, `@intent`, ...) rather than a TOML name/version
# pair. Treating them as manifest-shape produces 100% false positives —
Expand Down Expand Up @@ -270,7 +270,7 @@
# ./-prefixed form that `find .` emits; spelling it out separately (as the
# original three-branch test did) is redundant. Verified equivalent across
# ./-prefixed, bare and absolute paths, and on the negative cases.
case "$file" in

Check failure on line 273 in .github/hooks/validate-deed.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a default case (*) to handle unexpected values.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_panoply&issues=AaC-trf5Rffk6HRCi1wd&open=AaC-trf5Rffk6HRCi1wd&pullRequest=66
*/machine-readable/*|machine-readable/*|*/.machine_readable/*|.machine_readable/*)
is_structural_identity=true
;;
Expand All @@ -283,9 +283,9 @@

# DEED is the live, grammar-bearing format: its schema version is required even
# under a machine-readable tree. The structural-identity exemption below stays
# scoped to legacy *.a2ml, which is no longer authored. (CodeRabbit, PR review.)
# scoped to legacy *.deed, which is no longer authored. (CodeRabbit, PR review.)
local version_exempt_structural="$is_structural_identity"
case "$file" in *.deed) version_exempt_structural=false ;; esac

Check failure on line 288 in .github/hooks/validate-deed.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a default case (*) to handle unexpected values.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_panoply&issues=AaC-trf5Rffk6HRCi1we&open=AaC-trf5Rffk6HRCi1we&pullRequest=66
if [[ "$has_version" == "false" && "$is_manifest" == "false" && "$is_contractile_shape" == "false" && "$version_exempt_structural" == "false" ]]; then
report_issue "warning" "$file" 1 \
"Missing version or schema_version field"
Expand Down Expand Up @@ -335,8 +335,8 @@
# Lines starting with [ should have a matching ]
if [[ "$line" =~ ^\[ && ! "$line" =~ ^\[.+\] ]]; then
# Exclude markdown-style links and multi-line values
if [[ ! "$line" =~ ^\[.*\]\( && ! "$line" =~ ^\[TODO && ! "$line" =~ ^\[YOUR ]]; then

Check warning on line 338 in .github/hooks/validate-deed.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Merge this if statement with the enclosing one.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_panoply&issues=AaC-trf5Rffk6HRCi1wf&open=AaC-trf5Rffk6HRCi1wf&pullRequest=66
report_issue "warning" "$file" "$line_num" \

Check warning on line 339 in .github/hooks/validate-deed.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of using the literal 'warning' 5 times.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_panoply&issues=AaC-trf5Rffk6HRCi1wh&open=AaC-trf5Rffk6HRCi1wh&pullRequest=66
"Possibly malformed section heading: unclosed bracket"
fi
fi
Expand All @@ -344,15 +344,15 @@
}

# ---------------------------------------------------------------------------
# Main: discover and validate .a2ml and .deed files
# Main: discover and validate .deed and .deed files
# ---------------------------------------------------------------------------

echo "::group::A2ML Manifest Validation"
echo "Scanning ${SCAN_PATH} for .a2ml and .deed files..."
echo "Scanning ${SCAN_PATH} for .deed and .deed files..."
echo ""

# Find all .a2ml and .deed files, excluding .git directory
mapfile -t a2ml_candidates < <(find "$SCAN_PATH" \( -name '*.a2ml' -o -name '*.deed' \) -not -path '*/.git/*' -type f | sort)
# Find all .deed and .deed files, excluding .git directory
mapfile -t a2ml_candidates < <(find "$SCAN_PATH" \( -name '*.deed' -o -name '*.deed' \) -not -path '*/.git/*' -type f | sort)

# Apply paths-ignore filter
a2ml_files=()
Expand All @@ -370,15 +370,15 @@
fi

if [[ ${#a2ml_files[@]} -eq 0 ]]; then
echo "::notice::No .a2ml or .deed files found in ${SCAN_PATH}"
echo "::notice::No .deed or .deed files found in ${SCAN_PATH}"
echo "files_scanned=0" >> "$GITHUB_OUTPUT_FILE" 2>/dev/null || true
echo "errors=0" >> "$GITHUB_OUTPUT_FILE" 2>/dev/null || true
echo "warnings=0" >> "$GITHUB_OUTPUT_FILE" 2>/dev/null || true
echo "::endgroup::"
exit 0
fi

echo "Found ${#a2ml_files[@]} .a2ml/.deed file(s)"
echo "Found ${#a2ml_files[@]} .deed/.deed file(s)"
echo ""

for file in "${a2ml_files[@]}"; do
Expand All @@ -405,7 +405,7 @@

# Exit with failure if errors were found
if [[ $ERRORS -gt 0 ]]; then
echo "::error::A2ML validation failed with ${ERRORS} error(s)"

Check warning on line 408 in .github/hooks/validate-deed.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_panoply&issues=AaC-trf5Rffk6HRCi1wg&open=AaC-trf5Rffk6HRCi1wg&pullRequest=66
exit 1
fi

Expand Down
6 changes: 3 additions & 3 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>

### As Applicable

- [ ] `.machine_readable/6a2/STATE.a2ml` updated (if project state changed)
- [ ] `.machine_readable/6a2/ECOSYSTEM.a2ml` updated (if integrations changed)
- [ ] `.machine_readable/6a2/META.a2ml` updated (if architectural decisions changed)
- [ ] `.machine_readable/6a2/STATE.deed` updated (if project state changed)
- [ ] `.machine_readable/6a2/ECOSYSTEM.deed` updated (if integrations changed)
- [ ] `.machine_readable/6a2/META.deed` updated (if architectural decisions changed)
- [ ] Documentation updated for user-facing changes
- [ ] `TOPOLOGY.md` updated (if architecture changed)
- [ ] `CHANGELOG` or release notes updated
Expand Down
36 changes: 20 additions & 16 deletions .github/workflows/dogfood-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ permissions:

jobs:
# ---------------------------------------------------------------------------
# Job 1: A2ML manifest validation
# Job 1: DEED manifest validation
# ---------------------------------------------------------------------------
a2ml-validate:
name: Validate A2ML manifests
deed-validate:
name: Validate DEED manifests
runs-on: ubuntu-latest
timeout-minutes: 15

Expand All @@ -34,30 +34,34 @@ jobs:
- name: Check for A2ML files
id: detect
run: |
COUNT=$(find . -type f \( -name '*.a2ml' -o -name '*.deed' \) -not -path './.git/*' | wc -l)
COUNT=$(find . -type f -name '*.deed' -not -path './.git/*' | wc -l)
echo "count=$COUNT" >> "$GITHUB_OUTPUT"
if [ "$COUNT" -eq 0 ]; then
echo "::warning::No .deed manifest files found. Every RSR repo should have 0-AI-MANIFEST.deed (.a2ml is legacy and no longer authored)"
echo "::warning::No .deed manifest files found. Every RSR repo should have 0-AI-MANIFEST.deed"
fi
if find . -name '*.a2ml' -not -path './.git/*' | grep -q .; then
echo "::error::Deprecated .a2ml files present; migrate to .deed"
exit 1
fi

- name: Validate A2ML manifests
- name: Validate DEED manifests
if: steps.detect.outputs.count > 0
run: bash .github/hooks/validate-a2ml.sh
run: bash .github/hooks/validate-deed.sh
- name: Write summary
run: |
A2ML_COUNT="${{ steps.detect.outputs.count }}"
if [ "$A2ML_COUNT" -eq 0 ]; then
DEED_COUNT="${{ steps.detect.outputs.count }}"
if [ "$DEED_COUNT" -eq 0 ]; then
cat <<'EOF' >> "$GITHUB_STEP_SUMMARY"
## A2ML Validation
## DEED Validation

:warning: **No manifest found.** Every RSR-compliant repo should have at least `0-AI-MANIFEST.deed`. (`.a2ml` still validates as legacy but is no longer authored.)
:warning: **No manifest found.** Every RSR-compliant repo should have at least `0-AI-MANIFEST.deed`.

Copy one from [rsr-template-repo](https://github.com/hyperpolymath/rsr-template-repo).
EOF
else
echo "## A2ML Validation" >> "$GITHUB_STEP_SUMMARY"
echo "## DEED Validation" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "Scanned **${A2ML_COUNT}** manifest file(s) (.deed, or legacy .a2ml). See step output for details." >> "$GITHUB_STEP_SUMMARY"
echo "Scanned **${DEED_COUNT}** .deed file(s)." >> "$GITHUB_STEP_SUMMARY"
fi

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -369,7 +373,7 @@ jobs:
name: Dogfooding compliance summary
runs-on: ubuntu-latest
timeout-minutes: 15
needs: [a2ml-validate, k9-validate, empty-lint, groove-check, eclexiaiser-validate]
needs: [deed-validate, k9-validate, empty-lint, groove-check, eclexiaiser-validate]
if: always()

steps:
Expand All @@ -382,7 +386,7 @@ jobs:
MAX=6

# A2ML manifest present?
if find . -type f \( -name '*.a2ml' -o -name '*.deed' \) -not -path './.git/*' | head -1 | grep -q .; then
if find . -type f -name '*.deed' -not -path './.git/*' | head -1 | grep -q .; then
SCORE=$((SCORE + 1))
A2ML_STATUS=":white_check_mark:"
else
Expand Down Expand Up @@ -436,7 +440,7 @@ jobs:

| Tool/Format | Status | Notes |
|-------------|--------|-------|
| AI manifest (0-AI-MANIFEST.deed, or legacy .a2ml) | ${A2ML_STATUS} | Required for all RSR repos |
| AI manifest (0-AI-MANIFEST.deed) | ${A2ML_STATUS} | Required for all RSR repos |
| K9 contracts | ${K9_STATUS} | Required for repos with config files |
| .editorconfig | ${EC_STATUS} | Required for all repos |
| Groove endpoint | ${GROOVE_STATUS} | Required for service repos |
Expand Down
21 changes: 11 additions & 10 deletions .github/workflows/guix-nix-policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ jobs:
contents: read
steps:
- uses: actions/checkout@v7.0.1
- name: Enforce Guix primary / Nix fallback
- name: Enforce Guix / channels (Nix deprecated)
run: |
# Check for package manager files
HAS_GUIX=$(find . -name "*.scm" -o -name ".guix-channel" -o -name "guix.scm" 2>/dev/null | head -1)
HAS_NIX=$(find . -name "*.nix" 2>/dev/null | head -1)
HAS_GUIX=$(find . \( -name "*.scm" -o -name ".guix-channel" -o -name "guix.scm" \) 2>/dev/null | head -1)
HAS_NIX=$(find . -name "*.nix" -not -path './.git/*' 2>/dev/null | head -1)

# Block new package-lock.json, yarn.lock, Gemfile.lock, etc.
NEW_LOCKS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E 'package-lock\.json|yarn\.lock|Gemfile\.lock|Pipfile\.lock|poetry\.lock|cargo\.lock' || true)
if [ -n "$NEW_LOCKS" ]; then
echo "⚠️ Lock files detected. Prefer Guix manifests for reproducibility."
fi

# Prefer Guix, fallback to Nix
if [ -n "$HAS_NIX" ]; then
echo "::error::Nix is deprecated in this estate. Use Guix + channels (build/guix.scm, build/.guix-channel). Found: $HAS_NIX"
exit 1
fi

if [ -n "$HAS_GUIX" ]; then
echo "✅ Guix package management detected (primary)"
elif [ -n "$HAS_NIX" ]; then
echo "✅ Nix package management detected (fallback)"
echo "✅ Guix package management detected"
else
echo "ℹ️ Consider adding guix.scm or flake.nix for reproducible builds"
echo "::error::Missing Guix channel/manifest (build/guix.scm or .guix-channel)"
exit 1
fi

echo "✅ Package policy check passed"
12 changes: 6 additions & 6 deletions .github/workflows/openssf-compliance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,18 @@ jobs:
exit 1
fi
echo "README: OK"
- name: Check .machine_readable directory and STATE.a2ml
- name: Check .machine_readable directory and STATE.deed
run: |
if [ ! -d ".machine_readable" ]; then
echo "::error::.machine_readable/ directory is required"
exit 1
fi

if [ ! -f ".machine_readable/6a2/STATE.a2ml" ]; then
echo "::error::.machine_readable/6a2/STATE.a2ml is required"
if [ ! -f ".machine_readable/6a2/STATE.deed" ]; then
echo "::error::.machine_readable/6a2/STATE.deed is required"
exit 1
fi
echo ".machine_readable/6a2/STATE.a2ml: OK"
echo ".machine_readable/6a2/STATE.deed: OK"
- name: Check CHANGELOG exists
run: |
if [ ! -f "CHANGELOG.md" ] && [ ! -f "CHANGELOG.adoc" ] && [ ! -f "CHANGES.md" ]; then
Expand All @@ -89,8 +89,8 @@ jobs:
# Collect all required files that exist
for f in SECURITY.md SECURITY.adoc .github/SECURITY.md LICENSE LICENSE.txt \
CONTRIBUTING.md CONTRIBUTING.adoc README.md README.adoc \
.machine_readable/6a2/STATE.a2ml .machine_readable/6a2/META.a2ml \
.machine_readable/6a2/ECOSYSTEM.a2ml CHANGELOG.md CHANGELOG.adoc; do
.machine_readable/6a2/STATE.deed .machine_readable/6a2/META.deed \
.machine_readable/6a2/ECOSYSTEM.deed CHANGELOG.md CHANGELOG.adoc; do
[ -f "$f" ] && REQUIRED_FILES="$REQUIRED_FILES $f"
done

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/rhodibot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ jobs:
[ -f "$f" ] && warn "stale snapshot present: $f (would be deleted)"
done
# would-RENAME: legacy manifest name
if [ -f "AI.a2ml" ] && [ ! -f "0-AI-MANIFEST.a2ml" ]; then
warn "AI.a2ml present without 0-AI-MANIFEST.a2ml (would be renamed)"
if [ -f "AI.deed" ] && [ ! -f "0-AI-MANIFEST.deed" ]; then
warn "AI.deed present without 0-AI-MANIFEST.deed (would be renamed)"
fi
# would-DELETE: duplicate community files
[ -f "CONTRIBUTING.md" ] && [ -f "CONTRIBUTING.adoc" ] && warn "duplicate CONTRIBUTING.md + CONTRIBUTING.adoc (one would be removed)"
Expand All @@ -74,7 +74,7 @@ jobs:
[ -f "CONTRIBUTING.md" ] || [ -f ".github/CONTRIBUTING.md" ] || warn "no CONTRIBUTING.md (would be created)"

# --- unfixable compliance gaps (also drift) ---
[ -f "0-AI-MANIFEST.a2ml" ] || [ -f "AI.a2ml" ] || warn "missing AI manifest (0-AI-MANIFEST.a2ml)"
[ -f "0-AI-MANIFEST.deed" ] || [ -f "AI.deed" ] || warn "missing AI manifest (0-AI-MANIFEST.deed)"
[ -f "LICENSE" ] || [ -f "LICENSE.md" ] || [ -f "LICENSE.txt" ] || warn "missing LICENSE file"
[ -f "README.adoc" ] || [ -f "README.md" ] || warn "missing README"

Expand Down
Loading
Loading