Skip to content

Commit d4f04d2

Browse files
committed
chore: add descriptiles and check-root-shape.sh
1 parent 64a264a commit d4f04d2

6 files changed

Lines changed: 685 additions & 0 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
3+
#
4+
# STATE.a2ml — Project state checkpoint (META-TEMPLATE)
5+
#
6+
# This is the STATE file for rsr-template-repo itself.
7+
# When consumed by a new project, replace {{PLACEHOLDER}} tokens
8+
# and customize sections below for the target project.
9+
10+
[metadata]
11+
project = "rsr-template-repo"
12+
version = "0.2.0"
13+
last-updated = "2026-02-28"
14+
status = "active" # active | paused | archived
15+
16+
[project-context]
17+
name = "rsr-template-repo"
18+
purpose = "Canonical RSR-compliant repository template providing scaffolding for all hyperpolymath projects — including CI/CD, AI manifests, ABI/FFI standards, container ecosystem, and governance infrastructure."
19+
completion-percentage = 95
20+
21+
[position]
22+
phase = "maintenance" # design | implementation | testing | maintenance | archived
23+
maturity = "production" # experimental | alpha | beta | production | lts
24+
25+
[route-to-mvp]
26+
milestones = [
27+
{ name = "Phase 0: Core scaffolding (justfile, CI/CD, .machine_readable)", completion = 100 },
28+
{ name = "Phase 1: ABI/FFI standard (Idris2/Zig templates)", completion = 100 },
29+
{ name = "Phase 1b: AI Gatekeeper Protocol (0-AI-MANIFEST.a2ml)", completion = 100 },
30+
{ name = "Phase 1c: TOPOLOGY.md standard and guide", completion = 100 },
31+
{ name = "Phase 1d: Maintenance gate (axes, checklist, approach)", completion = 100 },
32+
{ name = "Phase 1e: Trustfile / contractiles", completion = 100 },
33+
{ name = "Phase 2: Container ecosystem templates (stapeln)", completion = 100 },
34+
{ name = "Phase 3: Multi-forge sync hardening", completion = 0 },
35+
{ name = "Phase 4: Guix reproducible shells", completion = 50 },
36+
]
37+
38+
[blockers-and-issues]
39+
# No active blockers
40+
41+
[critical-next-actions]
42+
actions = [
43+
"Container templates complete — test with `just container-init`",
44+
"Validate container templates across wolfi-base and static Chainguard images",
45+
"Harden multi-forge sync for GitLab/Bitbucket mirroring edge cases",
46+
"Expand Guix development shell templates",
47+
]
48+
49+
[maintenance-status]
50+
last-run-utc = "never"
51+
last-report = "docs/reports/maintenance/latest.json"
52+
last-result = "unknown" # unknown | pass | warn | fail
53+
open-warnings = 0
54+
open-failures = 0
55+
56+
[ecosystem]
57+
part-of = ["RSR Framework", "stapeln ecosystem"]
58+
depends-on = ["stapeln", "selur-compose", "cerro-torre", "svalinn", "vordr", "k9-svc"]
59+
60+
# ---------------------------------------------------------------------------
61+
# NOTE FOR CONSUMERS: When using this template to create a new repo, reset
62+
# the fields above to your project's values and replace all {{PLACEHOLDER}}
63+
# tokens. The milestones above describe the TEMPLATE's evolution, not yours.
64+
# ---------------------------------------------------------------------------

scripts/check-no-md-in-docs.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
4+
#
5+
# check-no-md-in-docs.sh — enforce "AsciiDoc by default for general docs".
6+
#
7+
# Estate rule: .adoc for general docs (TOPOLOGY, READINESS, ROADMAP, etc.);
8+
# .md only for files GitHub's community-health rules special-case by name
9+
# (CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, CHANGELOG, etc.) — those live at
10+
# root or in .github/, never under docs/.
11+
#
12+
# Fails if any .md files exist under docs/. Add justified entries to the
13+
# ALLOWED list below if a docs/-rooted .md is genuinely needed (rare).
14+
#
15+
# Exit codes:
16+
# 0 — no .md files under docs/ (or all matches are allow-listed)
17+
# 1 — disallowed .md files found
18+
# 2 — usage / setup error
19+
20+
set -euo pipefail
21+
22+
REPO_ROOT="${1:-.}"
23+
DOCS_DIR="$REPO_ROOT/docs"
24+
25+
# Justified exceptions, relative to repo root. Empty by default.
26+
ALLOWED=()
27+
28+
if [ ! -d "$DOCS_DIR" ]; then
29+
echo "PASS: no docs/ directory (nothing to check)"
30+
exit 0
31+
fi
32+
33+
mapfile -t HITS < <(find "$DOCS_DIR" -name '*.md' -type f 2>/dev/null | sort)
34+
35+
EXTRAS=()
36+
for hit in "${HITS[@]}"; do
37+
rel="${hit#"$REPO_ROOT/"}"
38+
skip=0
39+
for allowed in "${ALLOWED[@]}"; do
40+
if [ "$rel" = "$allowed" ]; then skip=1; break; fi
41+
done
42+
if [ $skip -eq 0 ]; then EXTRAS+=("$rel"); fi
43+
done
44+
45+
if [ ${#EXTRAS[@]} -eq 0 ]; then
46+
echo "PASS: no .md files under docs/ (${#HITS[@]} total found, ${#ALLOWED[@]} allow-listed)"
47+
exit 0
48+
fi
49+
50+
echo "FAIL: ${#EXTRAS[@]} .md files found under docs/ (estate rule: AsciiDoc by default):" >&2
51+
for e in "${EXTRAS[@]}"; do
52+
echo " - $e" >&2
53+
done
54+
echo "" >&2
55+
echo "Convert these to .adoc, or add a justified entry to the ALLOWED list" >&2
56+
echo "in scripts/check-no-md-in-docs.sh." >&2
57+
exit 1

scripts/check-no-vlang.sh

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
4+
#
5+
# check-no-vlang.sh — enforce "V-lang is banned in the estate".
6+
#
7+
# Estate rule: V-lang (vlang.io) is banned estate-wide (2026-04-10). It was
8+
# migrated to Zig — the estate's default FFI/API/gateway language — via the
9+
# `zig-unified-api-adapter`. Zig is ALLOWED and is deliberately NOT matched by
10+
# this check; only V-lang references are treated as drift and must be removed.
11+
#
12+
# Searches for V-lang-specific content patterns in tracked files. The .v file
13+
# extension is intentionally NOT used as a marker because Coq theorem files
14+
# share that extension; this check looks at content patterns instead.
15+
#
16+
# Excludes:
17+
# .git/ (vcs internals)
18+
# affinescript/ (a separately-licensed AffineScript subtree; pattern hits
19+
# there are not estate-managed and false-positive on `.v` mentions in
20+
# linguistic / academic prose).
21+
#
22+
# Exit codes:
23+
# 0 — no V-lang references found
24+
# 1 — V-lang references found (treat as drift)
25+
# 2 — usage / setup error
26+
27+
set -euo pipefail
28+
29+
REPO_ROOT="${1:-.}"
30+
31+
# Patterns that uniquely indicate V-lang code, scaffolding, or naming.
32+
# Zig is the estate FFI/API default and is deliberately NOT matched here.
33+
# Coq's `.v` extension and the affinescript subtree are excluded by path.
34+
PATTERNS=(
35+
'gen-v-connector'
36+
'V-TRIPLE'
37+
'v-triple'
38+
'vlang'
39+
'connectors/v-'
40+
)
41+
42+
PATTERN_OR=$(IFS='|'; echo "${PATTERNS[*]}")
43+
44+
# Files that document the V-lang ban itself (the rule's own description
45+
# legitimately names "V-lang", "vlang", "V-TRIPLE", etc.). Excluded by name.
46+
DOC_EXCLUSIONS=(
47+
"estate-rules.yml" # the workflow that calls this script
48+
"check-no-vlang.sh" # this script itself
49+
"PLAYBOOK.a2ml" # documents the [rsr-repo-skeleton] rules
50+
"feedback_v_lang_banned.md" # memory entry documenting the ban
51+
"project_zig_unified_api.md" # memory entry documenting the replacement
52+
)
53+
54+
EXCLUDE_ARGS=()
55+
for f in "${DOC_EXCLUSIONS[@]}"; do
56+
EXCLUDE_ARGS+=(--exclude="$f")
57+
done
58+
59+
# Build grep arguments. Use -r to recurse, -n for line numbers, -i for
60+
# case-insensitive matching. Exclude .git, the affinescript subtree, and
61+
# files that legitimately document the ban.
62+
HITS=$(grep -rni -E "$PATTERN_OR" "$REPO_ROOT" \
63+
--exclude-dir=.git \
64+
--exclude-dir=affinescript \
65+
--exclude-dir=node_modules \
66+
"${EXCLUDE_ARGS[@]}" \
67+
2>/dev/null || true)
68+
69+
if [ -z "$HITS" ]; then
70+
echo "PASS: no V-lang references"
71+
exit 0
72+
fi
73+
74+
# Count matches
75+
LINES=$(echo "$HITS" | wc -l | tr -d ' ')
76+
77+
echo "FAIL: $LINES V-lang reference(s) found (estate rule: V-lang is banned):" >&2
78+
echo "$HITS" | sed 's|^| |' >&2
79+
echo "" >&2
80+
echo "V-lang has been replaced by Zig (the zig-unified-api-adapter). Remove these references." >&2
81+
exit 1

scripts/check-root-shape.sh

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
4+
#
5+
# check-root-shape.sh — fail when the repository root contains entries that
6+
# are not on the canonical allowlist (.machine_readable/root-allow.txt).
7+
#
8+
# Companion to scripts/validate-template.sh: that script enforces required
9+
# files; this one enforces that nothing else has crept in.
10+
#
11+
# Exit codes:
12+
# 0 — root matches allowlist
13+
# 1 — extras found at root (drift)
14+
# 2 — usage / setup error
15+
16+
set -euo pipefail
17+
18+
REPO_ROOT="${1:-.}"
19+
ALLOW_FILE="${REPO_ROOT}/.machine_readable/root-allow.txt"
20+
21+
if [ ! -f "$ALLOW_FILE" ]; then
22+
echo "ERROR: allowlist not found at $ALLOW_FILE" >&2
23+
exit 2
24+
fi
25+
26+
# Build the allow set: strip comments, trailing slashes, and blank lines.
27+
mapfile -t ALLOW < <(
28+
sed -E 's/[[:space:]]*#.*$//' "$ALLOW_FILE" \
29+
| sed -E 's|/$||' \
30+
| awk 'NF'
31+
)
32+
33+
declare -A ALLOW_SET=()
34+
for entry in "${ALLOW[@]}"; do
35+
ALLOW_SET["$entry"]=1
36+
done
37+
38+
# Enumerate everything tracked or present at the repository root.
39+
mapfile -t ACTUAL < <(
40+
cd "$REPO_ROOT" && \
41+
find . -mindepth 1 -maxdepth 1 \
42+
! -name '.' \
43+
-printf '%f\n' \
44+
| sort
45+
)
46+
47+
EXTRAS=()
48+
for entry in "${ACTUAL[@]}"; do
49+
if [ -z "${ALLOW_SET[$entry]+x}" ]; then
50+
EXTRAS+=("$entry")
51+
fi
52+
done
53+
54+
if [ ${#EXTRAS[@]} -eq 0 ]; then
55+
echo "PASS: root matches allowlist (${#ACTUAL[@]} entries, ${#ALLOW[@]} permitted)"
56+
exit 0
57+
fi
58+
59+
echo "FAIL: ${#EXTRAS[@]} root entries are not on the allowlist:" >&2
60+
for e in "${EXTRAS[@]}"; do
61+
if [ -d "$REPO_ROOT/$e" ]; then
62+
echo " - $e/ (directory)" >&2
63+
else
64+
echo " - $e" >&2
65+
fi
66+
done
67+
echo "" >&2
68+
echo "Either move them into the appropriate subdirectory, or add a justified" >&2
69+
echo "entry to .machine_readable/root-allow.txt." >&2
70+
exit 1

scripts/invariant-path.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
5+
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
6+
IP_ROOT="${REPO_ROOT}/../invariant-path"
7+
8+
if [[ ! -f "${IP_ROOT}/Cargo.toml" ]]; then
9+
echo "invariant-path workspace not found at ${IP_ROOT}" >&2
10+
exit 1
11+
fi
12+
13+
if [[ $# -eq 0 ]]; then
14+
set -- scan --profile generic --file "${REPO_ROOT}/README.adoc" --artifact-uri "repo://README.adoc"
15+
elif [[ "$1" == "scan" ]]; then
16+
shift
17+
has_profile="false"
18+
for arg in "$@"; do
19+
if [[ "$arg" == "--profile" ]]; then
20+
has_profile="true"
21+
break
22+
fi
23+
done
24+
if [[ "${has_profile}" == "true" ]]; then
25+
set -- scan "$@"
26+
else
27+
set -- scan --profile generic "$@"
28+
fi
29+
fi
30+
31+
exec cargo run --manifest-path "${IP_ROOT}/Cargo.toml" -p invariant-path-cli -- "$@"

0 commit comments

Comments
 (0)