From d9ec9a0f2abefcd6673eededf19066ff8a494993 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 26 Jul 2026 16:08:03 +0100 Subject: [PATCH 01/11] chore: update guix.scm from squisher-corpus --- guix.scm | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/guix.scm b/guix.scm index efde774..c6dd7be 100644 --- a/guix.scm +++ b/guix.scm @@ -1,24 +1,18 @@ -;; SPDX-License-Identifier: MPL-2.0 -;; Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) -;; -;; Guix development environment for TradeUnionist.jl. -;; Replaces the removed flake.nix per the estate Guix-only policy. -;; Usage: guix shell -D -f guix.scm +; SPDX-License-Identifier: MPL-2.0 +;; guix.scm — GNU Guix package definition for squisher-corpus +;; Usage: guix shell -f guix.scm (use-modules (guix packages) (guix build-system gnu) - (gnu packages julia)) + (guix licenses)) (package - (name "tradeunionist-jl") + (name "squisher-corpus") (version "0.1.0") (source #f) (build-system gnu-build-system) - (native-inputs - (list julia)) - (synopsis "TradeUnionist.jl") - (description - "TradeUnionist.jl — part of the hyperpolymath ecosystem.") - (home-page "https://github.com/hyperpolymath/TradeUnionist.jl") - (license ((@@ (guix licenses) license) "MPL-2.0" + (synopsis "squisher-corpus") + (description "squisher-corpus — part of the hyperpolymath ecosystem.") + (home-page "https://github.com/hyperpolymath/squisher-corpus") + (license ((@@ (guix licenses) license) "PMPL-1.0-or-later" "https://github.com/hyperpolymath/palimpsest-license"))) From 12309419c35d7d614607bd815d5d38b89ae82e7a Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 27 Jul 2026 23:28:54 +0100 Subject: [PATCH 02/11] ci: vendor validation scripts and remove remote action pins --- .githooks/validate-a2ml.sh | 350 ++++++++++++++++++++++++++++ .githooks/validate-k9.sh | 357 +++++++++++++++++++++++++++++ .github/workflows/dogfood-gate.yml | 12 +- 3 files changed, 709 insertions(+), 10 deletions(-) create mode 100755 .githooks/validate-a2ml.sh create mode 100755 .githooks/validate-k9.sh diff --git a/.githooks/validate-a2ml.sh b/.githooks/validate-a2ml.sh new file mode 100755 index 0000000..b053676 --- /dev/null +++ b/.githooks/validate-a2ml.sh @@ -0,0 +1,350 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# validate-a2ml.sh — A2ML manifest validation script +# +# Scans for .a2ml files and validates: +# 1. Required fields: agent-id or pedigree name, version +# 2. SPDX-License-Identifier header presence +# 3. Attestation block structure (if present) +# 4. Section heading syntax ([section] or ## section) +# +# Environment variables: +# INPUT_PATH — Directory to scan (default: .) +# INPUT_STRICT — Promote warnings to errors (default: false) +# +# Exit codes: +# 0 — All files valid (or only warnings in non-strict mode) +# 1 — Validation errors found + +set -euo pipefail + +# --------------------------------------------------------------------------- +# Configuration +# --------------------------------------------------------------------------- + +SCAN_PATH="${INPUT_PATH:-.}" +STRICT="${INPUT_STRICT:-false}" +PATHS_IGNORE_RAW="${INPUT_PATHS_IGNORE:-}" +GITHUB_OUTPUT_FILE="${GITHUB_OUTPUT:-/dev/null}" + +# Parse paths-ignore: newline-separated fragments, blank lines and # comments +# stripped. Each fragment is a substring match against the file path. Pattern +# adopted from hyperpolymath/hypatia#243 — content-pattern validators must +# distinguish a target from a vendored / fixture file that legitimately +# contains the very pattern being checked. +PATHS_IGNORE=() +while IFS= read -r _frag; do + # Strip leading and trailing whitespace (canonical bash idiom). + _frag="${_frag#"${_frag%%[![:space:]]*}"}" + _frag="${_frag%"${_frag##*[![:space:]]}"}" + [[ -z "$_frag" || "$_frag" == \#* ]] && continue + PATHS_IGNORE+=("$_frag") +done <<< "$PATHS_IGNORE_RAW" + +# Returns 0 if path should be skipped (matches any ignore fragment) +path_ignored() { + local p="$1" frag + for frag in "${PATHS_IGNORE[@]}"; do + [[ "$p" == *"$frag"* ]] && return 0 + done + return 1 +} + +# Counters +FILES_SCANNED=0 +ERRORS=0 +WARNINGS=0 + +# --------------------------------------------------------------------------- +# Helper: emit GitHub annotation +# --------------------------------------------------------------------------- +# Usage: annotate +# level: error | warning | notice +annotate() { + local level="$1" file="$2" line="$3" message="$4" + echo "::${level} file=${file},line=${line}::${message}" +} + +# --------------------------------------------------------------------------- +# Helper: report issue (respects strict mode) +# --------------------------------------------------------------------------- +# Usage: report_issue +# severity: error | warning +report_issue() { + local severity="$1" file="$2" line="$3" message="$4" + + if [[ "$severity" == "warning" && "$STRICT" == "true" ]]; then + severity="error" + fi + + annotate "$severity" "$file" "$line" "$message" + + if [[ "$severity" == "error" ]]; then + ERRORS=$((ERRORS + 1)) + else + WARNINGS=$((WARNINGS + 1)) + fi +} + +# --------------------------------------------------------------------------- +# Validator: check a single .a2ml file +# --------------------------------------------------------------------------- +validate_a2ml() { + local file="$1" + FILES_SCANNED=$((FILES_SCANNED + 1)) + + # --- Check 1: SPDX header --- + # The SPDX-License-Identifier should appear in the first 10 lines + local has_spdx=false + local line_num=0 + while IFS= read -r line; do + line_num=$((line_num + 1)) + if [[ $line_num -gt 10 ]]; then + break + fi + if [[ "$line" == *"SPDX-License-Identifier"* ]]; then + has_spdx=true + break + fi + done < "$file" + + if [[ "$has_spdx" == "false" ]]; then + report_issue "warning" "$file" 1 \ + "Missing SPDX-License-Identifier in first 10 lines" + fi + + # --- Check 2: Required identity fields --- + # A2ML files must contain either: + # - agent-id = "..." or agent_id = "..." + # - pedigree block with name field + # - name = "..." at top level (for AI manifests) + # - project = "..." (for STATE.a2ml) + local has_identity=false + local has_version=false + line_num=0 + + while IFS= read -r line; do + line_num=$((line_num + 1)) + + # Check for identity fields (various A2ML patterns) + # TOML/kv form: `name = "..."`, `project = "..."`, `agent-id = "..."` + if [[ "$line" =~ ^[[:space:]]*(agent[-_]id|name|project)[[:space:]]*= ]]; then + has_identity=true + fi + # S-expression form: `(name "...")`, `(project "...")`, + # `(agent-id "...")`. Some A2ML dialects (audit registries, + # classification stores) use Lisp-style s-expressions for the + # metadata block instead of TOML. Identity carries the same + # semantics; only the syntax differs. Match at any indent so it + # also picks up entries nested under `(metadata ...)`. + if [[ "$line" =~ ^[[:space:]]*\([[:space:]]*(agent[-_]id|name|project)[[:space:]]+\" ]]; then + has_identity=true + fi + # Colon / brace-block form: `name: "..."`, `id: "..."`, `project: "..."`. + # YAML-ish and brace-block A2ML dialects (e.g. `Trust { name: "..." }`, + # `id: "tsdm-standard"`) carry the same identity semantics; only the + # delimiter (`:` vs `=`) differs. `id` is the brace-block spelling of an + # identity key. + if [[ "$line" =~ ^[[:space:]]*(agent[-_]id|name|project|id)[[:space:]]*: ]]; then + has_identity=true + fi + # Check for version field — TOML form + if [[ "$line" =~ ^[[:space:]]*(version|schema_version)[[:space:]]*= ]]; then + has_version=true + fi + # Version field — s-expression form + if [[ "$line" =~ ^[[:space:]]*\([[:space:]]*(version|schema_version)[[:space:]]+\" ]]; then + has_version=true + fi + # Version field — colon / brace-block form + if [[ "$line" =~ ^[[:space:]]*(version|schema_version)[[:space:]]*: ]]; then + has_version=true + fi + done < "$file" + + # AI manifest files (0-AI-MANIFEST.a2ml, 0.1-AI-MANIFEST.a2ml, etc.) + # use markdown-style headers and free text, so identity check is relaxed + local basename + basename="$(basename "$file")" + local is_manifest=false + if [[ "$basename" == *"AI-MANIFEST"* ]]; then + is_manifest=true + fi + # Canonical typed manifests under .machine_readable/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 + # own $name/project and continue to be validated normally. + case "$basename" in + 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 + # 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) + 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 + # 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 — + # they're a different A2ML doc type. Detected by the presence of any + # contractile directive in the file body. + local is_contractile_shape=false + if grep -qE '^@(abstract|trust-level|trust-boundary|trust-actions|trust-deny|intent|must|adjust|end)([[:space:]]*:|$)' "$file"; then + is_contractile_shape=true + fi + + # Canonical structured A2ML tree. Everything under a `.machine_readable/` + # directory is a typed agent-readable doc (CLADE, ANCHOR, STATE, + # ECOSYSTEM, bot_directives/{debt,coverage,methodology}, ai/AI, + # policies/*, integrations/*, …). Per the RSR convention these carry + # identity structurally — owning repo + path + filename — not via an + # in-file `name`/`agent-id`. This generalises the `.machine_readable/descriptiles/` + # rationale above to the whole tree: rsr-template-repo itself ships these + # files without an in-file identity key, so requiring one produces + # estate-wide false positives on every repo built from the canonical + # template. Files outside `.machine_readable/` are still validated. + local is_structural_identity=false + if [[ "$file" == *"/.machine_readable/"* || "$file" == "./.machine_readable/"* || "$file" == ".machine_readable/"* ]]; then + is_structural_identity=true + fi + + if [[ "$has_identity" == "false" && "$is_manifest" == "false" && "$is_contractile_shape" == "false" && "$is_structural_identity" == "false" ]]; then + report_issue "error" "$file" 1 \ + "Missing required identity field (agent-id, name, or project)" + fi + + if [[ "$has_version" == "false" && "$is_manifest" == "false" && "$is_contractile_shape" == "false" && "$is_structural_identity" == "false" ]]; then + report_issue "warning" "$file" 1 \ + "Missing version or schema_version field" + fi + + # --- Check 3: Attestation block structure --- + # If file contains [attestation] or ## ATTESTATION, validate it has + # required sub-fields: proof or signature + local in_attestation=false + local attestation_line=0 + local attestation_has_content=false + line_num=0 + + while IFS= read -r line; do + line_num=$((line_num + 1)) + + # Detect attestation section start + if [[ "$line" =~ ^\[attestation\] ]] || [[ "$line" =~ ^##[[:space:]]+[Aa]ttestation ]] || [[ "$line" =~ ^##[[:space:]]+ATTESTATION ]]; then + in_attestation=true + attestation_line=$line_num + continue + fi + + # Detect next section (ends attestation block) + if [[ "$in_attestation" == "true" ]]; then + if [[ "$line" =~ ^\[.+\] ]] || [[ "$line" =~ ^##[[:space:]] ]]; then + in_attestation=false + continue + fi + # Check for content in attestation block + if [[ "$line" =~ (proof|signature|verified|hash)[[:space:]]*= ]]; then + attestation_has_content=true + fi + fi + done < "$file" + + if [[ $attestation_line -gt 0 && "$attestation_has_content" == "false" ]]; then + report_issue "warning" "$file" "$attestation_line" \ + "Attestation block found but missing proof/signature/hash fields" + fi + + # --- Check 4: Section heading syntax --- + # Validate that [section] headings are well-formed (no unclosed brackets) + line_num=0 + while IFS= read -r line; do + line_num=$((line_num + 1)) + # 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 + report_issue "warning" "$file" "$line_num" \ + "Possibly malformed section heading: unclosed bracket" + fi + fi + done < "$file" +} + +# --------------------------------------------------------------------------- +# Main: discover and validate .a2ml files +# --------------------------------------------------------------------------- + +echo "::group::A2ML Manifest Validation" +echo "Scanning ${SCAN_PATH} for .a2ml files..." +echo "" + +# Find all .a2ml files, excluding .git directory +mapfile -t a2ml_candidates < <(find "$SCAN_PATH" -name '*.a2ml' -not -path '*/.git/*' -type f | sort) + +# Apply paths-ignore filter +a2ml_files=() +SKIPPED=0 +for _f in "${a2ml_candidates[@]}"; do + if path_ignored "$_f"; then + SKIPPED=$((SKIPPED + 1)) + continue + fi + a2ml_files+=("$_f") +done + +if [[ $SKIPPED -gt 0 ]]; then + echo "::notice::Skipped ${SKIPPED} file(s) matching paths-ignore" +fi + +if [[ ${#a2ml_files[@]} -eq 0 ]]; then + echo "::notice::No .a2ml 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 file(s)" +echo "" + +for file in "${a2ml_files[@]}"; do + echo " Validating: ${file}" + validate_a2ml "$file" +done + +echo "" +echo "────────────────────────────────────────" +echo "Files scanned: ${FILES_SCANNED}" +echo "Errors: ${ERRORS}" +echo "Warnings: ${WARNINGS}" +echo "Strict mode: ${STRICT}" +echo "────────────────────────────────────────" + +# Write outputs for GitHub Actions +{ + echo "files_scanned=${FILES_SCANNED}" + echo "errors=${ERRORS}" + echo "warnings=${WARNINGS}" +} >> "$GITHUB_OUTPUT_FILE" 2>/dev/null || true + +echo "::endgroup::" + +# Exit with failure if errors were found +if [[ $ERRORS -gt 0 ]]; then + echo "::error::A2ML validation failed with ${ERRORS} error(s)" + exit 1 +fi + +echo "A2ML validation passed." +exit 0 diff --git a/.githooks/validate-k9.sh b/.githooks/validate-k9.sh new file mode 100755 index 0000000..c83e290 --- /dev/null +++ b/.githooks/validate-k9.sh @@ -0,0 +1,357 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# validate-k9.sh — K9 configuration file validation script +# +# Scans for .k9 and .k9.ncl files and validates: +# 1. K9! magic number on line 1 +# 2. Pedigree block presence with required fields (name, version) +# 3. Security level is one of: kennel, yard, hunt (case-insensitive) +# 4. Hunt-level files must have a signature or signature_required field +# 5. SPDX-License-Identifier header presence +# +# Environment variables: +# INPUT_PATH — Directory to scan (default: .) +# INPUT_STRICT — Promote warnings to errors (default: false) +# +# Exit codes: +# 0 — All files valid (or only warnings in non-strict mode) +# 1 — Validation errors found + +set -euo pipefail + +# --------------------------------------------------------------------------- +# Configuration +# --------------------------------------------------------------------------- + +SCAN_PATH="${INPUT_PATH:-.}" +STRICT="${INPUT_STRICT:-false}" +PATHS_IGNORE_RAW="${INPUT_PATHS_IGNORE:-}" +GITHUB_OUTPUT_FILE="${GITHUB_OUTPUT:-/dev/null}" + +# Parse paths-ignore: newline-separated fragments, blank lines and # comments +# stripped. Each fragment is a substring match against the file path. Pattern +# adopted from hyperpolymath/hypatia#243 — content-pattern validators must +# distinguish a target from a vendored / fixture file that legitimately +# contains the very pattern being checked. +PATHS_IGNORE=() +while IFS= read -r _frag; do + # Strip leading and trailing whitespace (canonical bash idiom). + _frag="${_frag#"${_frag%%[![:space:]]*}"}" + _frag="${_frag%"${_frag##*[![:space:]]}"}" + [[ -z "$_frag" || "$_frag" == \#* ]] && continue + PATHS_IGNORE+=("$_frag") +done <<< "$PATHS_IGNORE_RAW" + +# Returns 0 if path should be skipped (matches any ignore fragment) +path_ignored() { + local p="$1" frag + for frag in "${PATHS_IGNORE[@]}"; do + [[ "$p" == *"$frag"* ]] && return 0 + done + return 1 +} + +# Counters +FILES_SCANNED=0 +ERRORS=0 +WARNINGS=0 + +# Valid security levels (the leash metaphor) +VALID_LEVELS="kennel yard hunt" + +# --------------------------------------------------------------------------- +# Helper: emit GitHub annotation +# --------------------------------------------------------------------------- +annotate() { + local level="$1" file="$2" line="$3" message="$4" + echo "::${level} file=${file},line=${line}::${message}" +} + +# --------------------------------------------------------------------------- +# Helper: report issue (respects strict mode) +# --------------------------------------------------------------------------- +report_issue() { + local severity="$1" file="$2" line="$3" message="$4" + + if [[ "$severity" == "warning" && "$STRICT" == "true" ]]; then + severity="error" + fi + + annotate "$severity" "$file" "$line" "$message" + + if [[ "$severity" == "error" ]]; then + ERRORS=$((ERRORS + 1)) + else + WARNINGS=$((WARNINGS + 1)) + fi +} + +# --------------------------------------------------------------------------- +# Helper: normalise a security level string +# --------------------------------------------------------------------------- +# Strips quotes, leading/trailing whitespace, Nickel enum tick prefix +normalise_level() { + local raw="$1" + # Remove surrounding quotes, tick prefix ('Kennel -> Kennel), whitespace + raw="${raw#*=}" # Remove everything before = + raw="${raw//\"/}" # Remove double quotes + raw="${raw//\'/}" # Remove single quotes (Nickel tick) + raw="${raw//,/}" # Remove trailing commas + raw="${raw## }" # Trim leading space + raw="${raw%% }" # Trim trailing space + raw="${raw%%#*}" # Remove inline comments + raw="${raw## }" # Trim again + raw="${raw%% }" + echo "${raw,,}" # Lowercase +} + +# --------------------------------------------------------------------------- +# Validator: check a single K9 file +# --------------------------------------------------------------------------- +validate_k9() { + local file="$1" + FILES_SCANNED=$((FILES_SCANNED + 1)) + + # --- Check 1: K9! magic number on first non-empty line --- + local first_content_line="" + local first_content_line_num=0 + local line_num=0 + + while IFS= read -r line; do + line_num=$((line_num + 1)) + # Skip empty lines + if [[ -z "${line// /}" ]]; then + continue + fi + first_content_line="$line" + first_content_line_num=$line_num + break + done < "$file" + + if [[ "$first_content_line" != "K9!" ]]; then + report_issue "error" "$file" "$first_content_line_num" \ + "Missing K9! magic number. First non-empty line must be exactly 'K9!'" + fi + + # --- Check 2: SPDX header --- + local has_spdx=false + line_num=0 + while IFS= read -r line; do + line_num=$((line_num + 1)) + if [[ $line_num -gt 10 ]]; then + break + fi + if [[ "$line" == *"SPDX-License-Identifier"* ]]; then + has_spdx=true + break + fi + done < "$file" + + if [[ "$has_spdx" == "false" ]]; then + report_issue "warning" "$file" 1 \ + "Missing SPDX-License-Identifier in first 10 lines" + fi + + # --- Check 3: Pedigree block with required fields --- + local has_pedigree=false + local has_pedigree_name=false + local has_pedigree_version=false + local has_security_level=false + local security_level_value="" + local security_level_line=0 + local has_signature_field=false + local in_pedigree=false + local pedigree_depth=0 + + line_num=0 + while IFS= read -r line; do + line_num=$((line_num + 1)) + + # Detect pedigree block start. Note: do NOT `continue` here — the + # `pedigree = {` line itself contains the opening brace that + # establishes the block. Falling through to the brace counter + # below makes depth start at 1, so a subsequent `security = {…},` + # closing brace correctly takes depth to 1 (not 0), keeping us + # inside the pedigree block when later fields (name/version/leash) + # are checked. Previously the `continue` skipped this opening + # brace, depth started at 0, and the first nested block's close + # prematurely terminated the validator's view of the pedigree — + # making `pedigree.metadata.name` invisible. + if [[ "$line" =~ ^[[:space:]]*pedigree[[:space:]]*= ]]; then + has_pedigree=true + in_pedigree=true + pedigree_depth=0 + # fall through + fi + + if [[ "$in_pedigree" == "true" ]]; then + # Track brace depth to know when pedigree block ends + local opens closes + opens="${line//[^\{]/}" + closes="${line//[^\}]/}" + pedigree_depth=$(( pedigree_depth + ${#opens} - ${#closes} )) + + if [[ $pedigree_depth -le 0 && "$has_pedigree" == "true" ]]; then + # Check this final line too before leaving + : + fi + + # Check for name field within pedigree.metadata or pedigree directly. + # Two patterns cover both multi-line and single-line pedigrees: + # 1. ^[[:space:]]+name[[:space:]]*= — the normal multi-line case where + # `name = "..."` appears on its own indented line. + # 2. [[:space:]]name[[:space:]]*= — inline within a single-line + # pedigree assignment such as: + # pedigree = component_pedigree & { name = "foo" } + # (root cause: developer-ecosystem@baab1534 — single-line form + # was missed entirely because the pedigree block opened and + # closed in one line, never reaching the ^[[:space:]]+ check on + # a subsequent iteration.) + if [[ "$line" =~ ^[[:space:]]+name[[:space:]]*= ]] || \ + [[ "$line" =~ [[:space:]]name[[:space:]]*= ]]; then + has_pedigree_name=true + fi + + # Check for version field + if [[ "$line" =~ ^[[:space:]]+(version|schema_version)[[:space:]]*= ]] || \ + [[ "$line" =~ [[:space:]](version|schema_version)[[:space:]]*= ]]; then + has_pedigree_version=true + fi + + # Check for security level (leash field) + if [[ "$line" =~ ^[[:space:]]+(leash|security_level)[[:space:]]*= ]]; then + has_security_level=true + security_level_value="$(normalise_level "$line")" + security_level_line=$line_num + fi + + # Check for signature fields + if [[ "$line" =~ ^[[:space:]]+(signature|signature_required)[[:space:]]*= ]]; then + has_signature_field=true + fi + + # End of pedigree block + if [[ $pedigree_depth -le 0 && "$has_pedigree" == "true" && "$line" == *"}"* ]]; then + in_pedigree=false + fi + fi + + # Also check for signature fields outside pedigree (top-level) + if [[ "$line" =~ ^[[:space:]]*(signature)[[:space:]]*= ]]; then + has_signature_field=true + fi + done < "$file" + + if [[ "$has_pedigree" == "false" ]]; then + report_issue "error" "$file" 1 \ + "Missing pedigree block. K9 files must contain a 'pedigree = { ... }' section" + else + if [[ "$has_pedigree_name" == "false" ]]; then + report_issue "error" "$file" 1 \ + "Pedigree block missing 'name' field (in pedigree.metadata.name or pedigree.name)" + fi + + if [[ "$has_pedigree_version" == "false" ]]; then + report_issue "warning" "$file" 1 \ + "Pedigree block missing 'version' or 'schema_version' field" + fi + fi + + # --- Check 4: Security level validation --- + if [[ "$has_security_level" == "true" ]]; then + local level_valid=false + for valid in $VALID_LEVELS; do + if [[ "$security_level_value" == "$valid" ]]; then + level_valid=true + break + fi + done + + if [[ "$level_valid" == "false" ]]; then + report_issue "error" "$file" "$security_level_line" \ + "Invalid security level '${security_level_value}'. Must be one of: kennel, yard, hunt" + fi + else + if [[ "$has_pedigree" == "true" ]]; then + report_issue "warning" "$file" 1 \ + "No security level (leash/security_level) found in pedigree block" + fi + fi + + # --- Check 5: Hunt-level signature requirement --- + if [[ "$security_level_value" == "hunt" && "$has_signature_field" == "false" ]]; then + report_issue "error" "$file" "$security_level_line" \ + "Hunt-level K9 file must include a 'signature' or 'signature_required' field" + fi +} + +# --------------------------------------------------------------------------- +# Main: discover and validate K9 files +# --------------------------------------------------------------------------- + +echo "::group::K9 Configuration Validation" +echo "Scanning ${SCAN_PATH} for K9 files (.k9, .k9.ncl)..." +echo "" + +# Find all K9 files, excluding .git directory +mapfile -t k9_candidates < <(find "$SCAN_PATH" \( -name '*.k9' -o -name '*.k9.ncl' \) -not -path '*/.git/*' -type f | sort) + +# Apply paths-ignore filter +k9_files=() +SKIPPED=0 +for _f in "${k9_candidates[@]}"; do + if path_ignored "$_f"; then + SKIPPED=$((SKIPPED + 1)) + continue + fi + k9_files+=("$_f") +done + +if [[ $SKIPPED -gt 0 ]]; then + echo "::notice::Skipped ${SKIPPED} file(s) matching paths-ignore" +fi + +if [[ ${#k9_files[@]} -eq 0 ]]; then + echo "::notice::No K9 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 ${#k9_files[@]} K9 file(s)" +echo "" + +for file in "${k9_files[@]}"; do + echo " Validating: ${file}" + validate_k9 "$file" +done + +echo "" +echo "────────────────────────────────────────" +echo "Files scanned: ${FILES_SCANNED}" +echo "Errors: ${ERRORS}" +echo "Warnings: ${WARNINGS}" +echo "Strict mode: ${STRICT}" +echo "────────────────────────────────────────" + +# Write outputs for GitHub Actions +{ + echo "files_scanned=${FILES_SCANNED}" + echo "errors=${ERRORS}" + echo "warnings=${WARNINGS}" +} >> "$GITHUB_OUTPUT_FILE" 2>/dev/null || true + +echo "::endgroup::" + +# Exit with failure if errors were found +if [[ $ERRORS -gt 0 ]]; then + echo "::error::K9 validation failed with ${ERRORS} error(s)" + exit 1 +fi + +echo "K9 validation passed." +exit 0 diff --git a/.github/workflows/dogfood-gate.yml b/.github/workflows/dogfood-gate.yml index 433d048..2bb5802 100644 --- a/.github/workflows/dogfood-gate.yml +++ b/.github/workflows/dogfood-gate.yml @@ -39,11 +39,7 @@ jobs: - name: Validate A2ML manifests if: steps.detect.outputs.count > 0 - uses: hyperpolymath/a2ml-ecosystem/validate-action@aa4b836bd969df2bc58128cb8e3d20bbc88d5e79 # main - with: - path: '.' - strict: 'false' - + run: bash .githooks/validate-a2ml.sh - name: Write summary run: | A2ML_COUNT="${{ steps.detect.outputs.count }}" @@ -88,11 +84,7 @@ jobs: - name: Validate K9 contracts if: steps.detect.outputs.k9_count > 0 - uses: hyperpolymath/k9-ecosystem/validate-action@89f3c2702f4f650a92aa7411502f38da06abd562 # main - with: - path: '.' - strict: 'false' - + run: bash .githooks/validate-k9.sh - name: Write summary run: | K9_COUNT="${{ steps.detect.outputs.k9_count }}" From a3ce59709dbcda55dead18dda75357b83aab7c66 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:23:09 +0100 Subject: [PATCH 03/11] chore: fill derivable placeholders, drop false ARCHITECTURE, surface the rest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Estate top-up pass. Three separate things, none of which invents a value. FILLED — every token with a single mechanical answer: OWNER, REPO, FORGE, PROJECT, PACKAGE_NAME, PROJECT_NAME, AUTHOR, AUTHOR_EMAIL, CONDUCT_EMAIL, AUTHOR_FIRST/LAST/INITIALS, CURRENT_YEAR, CURRENT_DATE, DATE, MAIN_BRANCH. Identity comes from the git remote, dates from the clock, project name from the README H1 where there is one. Deliberately NOT filled, because more than one defensible answer exists and a confident wrong value is worse than a visible gap: SECURITY_EMAIL (two competing addresses are in use across the estate), RESPONSE_TIME, CONDUCT_TEAM (which substitutes into "a {{CONDUCT_TEAM}} member", not English), WEBSITE, PROJECT_DESCRIPTION, LANG_STACK. DELETED — ARCHITECTURE.md, where it is byte-identical to the 346-copy estate boilerplate (blob 607e3d8c). Those 33 lines describe a src/ tests/ docs/ scripts/ config/ tree that this repo does not have, so the file is not merely uninformative, it is wrong. Genuinely written ARCHITECTURE files are matched by hash and left alone. No file beats a confidently false one. CODEOWNERS — rewritten to the solo form mandated by hyperpolymath/standards CODEOWNERS-POLICY.adoc Rule 1, which forbids a catch-all line where the only owner is the sole maintainer. The estate's own templates/CODEOWNERS contradicts that policy; the policy is versioned, dated and resolves standards#55, so it wins. Files naming a genuine co-owner are Rule 2 and are untouched. Note @hyperpolymath and @metadatastician are the same person, so a file naming the other account is a copy artifact that silently routed review requests to the wrong account. SURFACED — REQUIRES_INITIALISATION.md, and a priority action in 0-AI-MANIFEST.a2ml. Tokens that need a decision no script can make are left visibly unfilled rather than faked or quietly deleted. The marker says what each one is, which files it belongs in, why it was not done already, and that it must be deleted only once the work is genuinely finished. --- .clinerules | 4 +- .cursorrules | 4 +- .devcontainer/Containerfile | 8 +- .devcontainer/devcontainer.json | 6 +- .envrc | 2 +- .github/CODEOWNERS | 36 +----- .guix-channel | 10 +- .../bot_directives/methodology.a2ml | 2 +- .machine_readable/contractiles/Justfile | 4 +- .../self-validating/examples/ci-config.k9.ncl | 2 +- .../examples/project-metadata.k9.ncl | 6 +- .../examples/setup-repo.k9.ncl | 6 +- .../self-validating/template-hunt.k9.ncl | 2 +- .../self-validating/template-kennel.k9.ncl | 2 +- .../self-validating/template-yard.k9.ncl | 2 +- .mailmap | 2 +- .reuse/dep5 | 24 ++-- .well-known/humans.txt | 6 +- .well-known/security.txt | 2 +- .windsurfrules | 4 +- 0-AI-MANIFEST.a2ml | 17 +++ ARCHITECTURE.md | 47 ------- CODE_OF_CONDUCT.md | 8 +- Containerfile | 4 +- Justfile | 4 +- PLACEHOLDERS.md | 2 +- PROOF-NEEDS.md | 2 +- REQUIRES_INITIALISATION.md | 116 ++++++++++++++++++ ffi/zig/build.zig | 2 +- ffi/zig/test/integration_test.zig | 2 +- 30 files changed, 197 insertions(+), 141 deletions(-) delete mode 100644 ARCHITECTURE.md create mode 100644 REQUIRES_INITIALISATION.md diff --git a/.clinerules b/.clinerules index 27f1666..112dca4 100644 --- a/.clinerules +++ b/.clinerules @@ -1,5 +1,5 @@ # SPDX-License-Identifier: MPL-2.0 -# Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # Authoritative source: docs/AI-CONVENTIONS.md # STARTUP: Read 0-AI-MANIFEST.a2ml first, then .machine_readable/STATE.a2ml. @@ -8,7 +8,7 @@ # All original code: MPL-2.0. # Never AGPL-3.0. MPL-2.0 only as platform-required fallback. # SPDX header required on every source file. -# Copyright: {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright: Jonathan D.A. Jewell (hyperpolymath) # STATE FILES (.machine_readable/ ONLY) # Never create in repo root: STATE.a2ml, META.a2ml, ECOSYSTEM.a2ml, diff --git a/.cursorrules b/.cursorrules index 7d199ea..ec7a4fc 100644 --- a/.cursorrules +++ b/.cursorrules @@ -1,5 +1,5 @@ # SPDX-License-Identifier: MPL-2.0 -# Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # Authoritative source: docs/AI-CONVENTIONS.md # Read 0-AI-MANIFEST.a2ml in the repo root FIRST for canonical file locations. @@ -7,7 +7,7 @@ # LICENSE # All original code: MPL-2.0 (SPDX header required on every file). # Never use AGPL-3.0. Fallback to MPL-2.0 only when platform requires it. -# Copyright: {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright: Jonathan D.A. Jewell (hyperpolymath) # STATE FILES # .a2ml metadata files go in .machine_readable/ ONLY. diff --git a/.devcontainer/Containerfile b/.devcontainer/Containerfile index 928a042..d9f18cf 100644 --- a/.devcontainer/Containerfile +++ b/.devcontainer/Containerfile @@ -1,9 +1,9 @@ # SPDX-License-Identifier: MPL-2.0 -# Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # -# Dev Container image for {{PROJECT_NAME}} +# Dev Container image for TradeUnionist.jl # Base: Chainguard Wolfi (minimal, supply-chain-secure) -# Build: podman build -t {{PROJECT_NAME}}-dev -f .devcontainer/Containerfile . +# Build: podman build -t TradeUnionist.jl-dev -f .devcontainer/Containerfile . FROM cgr.dev/chainguard/wolfi-base:latest @@ -24,7 +24,7 @@ RUN groupadd -g 1000 nonroot || true \ && useradd -m -u 1000 -g 1000 -s /bin/bash nonroot || true # Set workspace directory -WORKDIR /workspaces/{{PROJECT_NAME}} +WORKDIR /workspaces/TradeUnionist.jl # Default shell ENV SHELL=/bin/bash diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 39fff7b..3711264 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MPL-2.0 -// Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) // -// Dev Container configuration for {{PROJECT_NAME}} +// Dev Container configuration for TradeUnionist.jl // Works with: VS Code Dev Containers, GitHub Codespaces, Gitpod // Container runtime: Podman (recommended) or any OCI-compliant runtime { - "name": "{{PROJECT_NAME}}", + "name": "TradeUnionist.jl", "build": { "dockerfile": "Containerfile", diff --git a/.envrc b/.envrc index 0b5b702..010028d 100644 --- a/.envrc +++ b/.envrc @@ -18,7 +18,7 @@ if has nix && [ -f flake.nix ]; then fi # Project environment variables -export PROJECT_NAME="{{PROJECT_NAME}}" +export PROJECT_NAME="TradeUnionist.jl" export RSR_TIER="infrastructure" # export DATABASE_URL="..." # export API_KEY="..." diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3a3b7f2..4714ad5 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,34 +1,4 @@ # SPDX-License-Identifier: MPL-2.0 -# CODEOWNERS - Define code review assignments for GitHub -# See: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners - -# Default: sole maintainer for all files -* @hyperpolymath - -# Security-sensitive files require explicit ownership -SECURITY.md @hyperpolymath -.github/workflows/ @hyperpolymath -.machine_readable/ @hyperpolymath -contractiles/ @hyperpolymath - -# License files -LICENSE @hyperpolymath -LICENSES/ @hyperpolymath - -# Configuration -.gitignore @hyperpolymath -.github/ @hyperpolymath - -# Documentation -README* @hyperpolymath -CONTRIBUTING* @hyperpolymath -CODE_OF_CONDUCT* @hyperpolymath -GOVERNANCE* @hyperpolymath -MAINTAINERS* @hyperpolymath -CHANGELOG* @hyperpolymath -ROADMAP* @hyperpolymath - -# Build and CI -Justfile @hyperpolymath -Makefile @hyperpolymath -*.sh @hyperpolymath +# Solo-maintained hyperpolymath repo: no owner lines by policy. +# See hyperpolymath/standards CODEOWNERS-POLICY.adoc (Rule 1). +# Sole-maintainer review is moot; SPDX headers carry attribution. diff --git a/.guix-channel b/.guix-channel index 783f593..0f7c4dd 100644 --- a/.guix-channel +++ b/.guix-channel @@ -1,20 +1,20 @@ ;; SPDX-License-Identifier: MPL-2.0 -;; Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +;; Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) ;; -;; Guix channel definition for {{PROJECT_NAME}} +;; Guix channel definition for TradeUnionist.jl ;; ;; To use this channel, add to ~/.config/guix/channels.scm: ;; ;; (channel -;; (name '{{PROJECT_NAME}}) -;; (url "https://github.com/hyperpolymath/{{PROJECT_NAME}}") +;; (name 'TradeUnionist.jl) +;; (url "https://github.com/hyperpolymath/TradeUnionist.jl") ;; (branch "main")) ;; ;; Then: guix pull (channel (version 0) - (url "https://github.com/hyperpolymath/{{PROJECT_NAME}}") + (url "https://github.com/hyperpolymath/TradeUnionist.jl") (dependencies (channel (name 'guix) diff --git a/.machine_readable/bot_directives/methodology.a2ml b/.machine_readable/bot_directives/methodology.a2ml index 754f357..5723df1 100644 --- a/.machine_readable/bot_directives/methodology.a2ml +++ b/.machine_readable/bot_directives/methodology.a2ml @@ -101,7 +101,7 @@ constraints = [ # These rules detect corrupt/template/stale state files. [methodology.state-validation] -reject-if-contains = ["{{PLACEHOLDER}}", "{{PROJECT}}", "rsr-template-repo"] +reject-if-contains = ["{{PLACEHOLDER}}", "TRADEUNIONIST_JL", "rsr-template-repo"] reject-if-project-name-mismatch = true staleness-threshold-days = 90 fallback-files = ["TODO.md", "TODO.adoc", "ROADMAP.adoc", "README.adoc"] diff --git a/.machine_readable/contractiles/Justfile b/.machine_readable/contractiles/Justfile index 9f0fb84..5010526 100644 --- a/.machine_readable/contractiles/Justfile +++ b/.machine_readable/contractiles/Justfile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: MPL-2.0 -# Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # # RSR Standard Justfile Template # https://just.systems/man/en/ @@ -18,7 +18,7 @@ set positional-arguments := true import? "contractile.just" # Project metadata — customize these -project := "{{PROJECT_NAME}}" +project := "TradeUnionist.jl" version := "0.1.0" tier := "infrastructure" # 1 | 2 | infrastructure diff --git a/.machine_readable/self-validating/examples/ci-config.k9.ncl b/.machine_readable/self-validating/examples/ci-config.k9.ncl index 1f38e2d..9fe314e 100644 --- a/.machine_readable/self-validating/examples/ci-config.k9.ncl +++ b/.machine_readable/self-validating/examples/ci-config.k9.ncl @@ -19,7 +19,7 @@ K9! name = "ci-config", version = "1.0.0", description = "CI/CD configuration with runtime validation", - author = "{{AUTHOR}} <{{AUTHOR_EMAIL}}>", + author = "Jonathan D.A. Jewell ", }, }, diff --git a/.machine_readable/self-validating/examples/project-metadata.k9.ncl b/.machine_readable/self-validating/examples/project-metadata.k9.ncl index 7bc6941..3f59d9e 100644 --- a/.machine_readable/self-validating/examples/project-metadata.k9.ncl +++ b/.machine_readable/self-validating/examples/project-metadata.k9.ncl @@ -19,7 +19,7 @@ K9! name = "project-metadata", version = "1.0.0", description = "Pure data configuration for project metadata", - author = "{{AUTHOR}} <{{AUTHOR_EMAIL}}>", + author = "Jonathan D.A. Jewell ", }, }, @@ -35,8 +35,8 @@ K9! }, author = { - name = "{{AUTHOR}}", - email = "{{AUTHOR_EMAIL}}", + name = "Jonathan D.A. Jewell", + email = "j.d.a.jewell@open.ac.uk", organization = "{{AUTHOR_ORG}}", }, diff --git a/.machine_readable/self-validating/examples/setup-repo.k9.ncl b/.machine_readable/self-validating/examples/setup-repo.k9.ncl index 523e817..d1fc8bb 100644 --- a/.machine_readable/self-validating/examples/setup-repo.k9.ncl +++ b/.machine_readable/self-validating/examples/setup-repo.k9.ncl @@ -20,7 +20,7 @@ K9! name = "setup-repo", version = "1.0.0", description = "Automated repository setup with RSR standards", - author = "{{AUTHOR}} <{{AUTHOR_EMAIL}}>", + author = "Jonathan D.A. Jewell ", }, warnings = [ "This component has full system access", @@ -104,8 +104,8 @@ K9! description = "Initialize Git repository", commands = [ "git init -b %{config.git.default_branch}", - "git config user.name '{{AUTHOR}}'", - "git config user.email '{{AUTHOR_EMAIL}}'", + "git config user.name 'Jonathan D.A. Jewell'", + "git config user.email 'j.d.a.jewell@open.ac.uk'", "echo '✓ Git initialized'", ], }, diff --git a/.machine_readable/self-validating/template-hunt.k9.ncl b/.machine_readable/self-validating/template-hunt.k9.ncl index a9cc350..b3fcb47 100644 --- a/.machine_readable/self-validating/template-hunt.k9.ncl +++ b/.machine_readable/self-validating/template-hunt.k9.ncl @@ -20,7 +20,7 @@ K9! name = "TODO: component-name", version = "1.0.0", description = "TODO: Detailed description of what this component does", - author = "{{AUTHOR}} <{{AUTHOR_EMAIL}}>", + author = "Jonathan D.A. Jewell ", }, warnings = [ "This component has full system access", diff --git a/.machine_readable/self-validating/template-kennel.k9.ncl b/.machine_readable/self-validating/template-kennel.k9.ncl index fa7e3f3..4228b26 100644 --- a/.machine_readable/self-validating/template-kennel.k9.ncl +++ b/.machine_readable/self-validating/template-kennel.k9.ncl @@ -19,7 +19,7 @@ K9! name = "TODO: component-name", version = "1.0.0", description = "TODO: Brief description of what this component contains", - author = "{{AUTHOR}} <{{AUTHOR_EMAIL}}>", + author = "Jonathan D.A. Jewell ", }, }, diff --git a/.machine_readable/self-validating/template-yard.k9.ncl b/.machine_readable/self-validating/template-yard.k9.ncl index 358671c..a723f5a 100644 --- a/.machine_readable/self-validating/template-yard.k9.ncl +++ b/.machine_readable/self-validating/template-yard.k9.ncl @@ -19,7 +19,7 @@ K9! name = "TODO: component-name", version = "1.0.0", description = "TODO: Brief description with validation details", - author = "{{AUTHOR}} <{{AUTHOR_EMAIL}}>", + author = "Jonathan D.A. Jewell ", }, }, diff --git a/.mailmap b/.mailmap index 0ada9de..38c8dda 100644 --- a/.mailmap +++ b/.mailmap @@ -1 +1 @@ -{{AUTHOR}} <{{AUTHOR_EMAIL}}> <{{AUTHOR_EMAIL_ALT}}> +Jonathan D.A. Jewell <{{AUTHOR_EMAIL_ALT}}> diff --git a/.reuse/dep5 b/.reuse/dep5 index c08dfb3..112ba76 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -1,54 +1,54 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: {{PROJECT_NAME}} -Upstream-Contact: {{AUTHOR}} <{{AUTHOR_EMAIL}}> +Upstream-Name: TradeUnionist.jl +Upstream-Contact: Jonathan D.A. Jewell Source: https://github.com/hyperpolymath/TradeUnionist.jl # Default: all files are MPL-2.0 Files: * -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # Configuration files that cannot carry headers Files: .editorconfig .gitignore .gitattributes .tool-versions .mailmap -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # Machine-readable state files Files: .machine_readable/*.a2ml -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # Bot directives Files: .machine_readable/bot_directives/* -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # Contractiles Files: .machine_readable/contractiles/* -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # GitHub/CI configuration Files: .github/* .github/**/* -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # Generated files Files: generated/* -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # Lockfiles and auto-generated Files: *.lock Cargo.lock flake.lock -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # Devcontainer config (JSON, no comments) Files: .devcontainer/*.json -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 # Git-cliff config Files: cliff.toml -Copyright: {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +Copyright: 2026 Jonathan D.A. Jewell (hyperpolymath) License: MPL-2.0 diff --git a/.well-known/humans.txt b/.well-known/humans.txt index 9b1b4e2..105f211 100644 --- a/.well-known/humans.txt +++ b/.well-known/humans.txt @@ -2,12 +2,12 @@ # humanstxt.org /* TEAM */ -Maintainer: {{AUTHOR}} (hyperpolymath) -Contact: {{AUTHOR_EMAIL}} +Maintainer: Jonathan D.A. Jewell (hyperpolymath) +Contact: j.d.a.jewell@open.ac.uk From: United Kingdom /* SITE */ -Last update: {{CURRENT_DATE}} +Last update: 2026-08-05 Standards: RSR (Rhodium Standard Repository) License: MPL-2.0 (Palimpsest MPL) Components: Idris2 ABI, Zig FFI diff --git a/.well-known/security.txt b/.well-known/security.txt index 8d3c96d..10c3760 100644 --- a/.well-known/security.txt +++ b/.well-known/security.txt @@ -3,7 +3,7 @@ # https://securitytxt.org/ Contact: mailto:{{SECURITY_EMAIL}} -Expires: {{CURRENT_YEAR}}-12-31T23:59:59.000Z +Expires: 2026-12-31T23:59:59.000Z Encryption: {{PGP_KEY_URL}} Preferred-Languages: en Canonical: https://github.com/hyperpolymath/TradeUnionist.jl/.well-known/security.txt diff --git a/.windsurfrules b/.windsurfrules index 27f1666..112dca4 100644 --- a/.windsurfrules +++ b/.windsurfrules @@ -1,5 +1,5 @@ # SPDX-License-Identifier: MPL-2.0 -# Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # Authoritative source: docs/AI-CONVENTIONS.md # STARTUP: Read 0-AI-MANIFEST.a2ml first, then .machine_readable/STATE.a2ml. @@ -8,7 +8,7 @@ # All original code: MPL-2.0. # Never AGPL-3.0. MPL-2.0 only as platform-required fallback. # SPDX header required on every source file. -# Copyright: {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright: Jonathan D.A. Jewell (hyperpolymath) # STATE FILES (.machine_readable/ ONLY) # Never create in repo root: STATE.a2ml, META.a2ml, ECOSYSTEM.a2ml, diff --git a/0-AI-MANIFEST.a2ml b/0-AI-MANIFEST.a2ml index 3ebd136..238af07 100644 --- a/0-AI-MANIFEST.a2ml +++ b/0-AI-MANIFEST.a2ml @@ -124,3 +124,20 @@ After reading this file, demonstrate understanding by stating: - **Maintained By:** [YOUR-NAME/ORG] - **License:** MPL-2.0 - **Protocol:** https://github.com/hyperpolymath/0-ai-gatekeeper-protocol + + + +## PRIORITY ACTION — this repository is not fully initialised + +8 substitution token(s) still have no value. **Read +`REQUIRES_INITIALISATION.md` in the repository root before doing anything +else here** — it lists every outstanding token, what it means, and which +files it belongs in. + +Do not fabricate values for them, and do not delete the sections that +contain them to quiet a gate. They are unfilled because they need a +decision, not because they were overlooked. Resolve what you legitimately +can, leave the rest, and delete `REQUIRES_INITIALISATION.md` only when +nothing outstanding remains. + + diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md deleted file mode 100644 index 607e3d8..0000000 --- a/ARCHITECTURE.md +++ /dev/null @@ -1,47 +0,0 @@ -# Architecture - -## Overview - -This repository follows a modular, maintainable architecture designed for clarity, scalability, and long-term sustainability. - -## Directory Structure - -``` -. -├── src/ # Source code -├── tests/ # Test suites -├── docs/ # Documentation -├── scripts/ # Utility scripts -├── config/ # Configuration files -├── LICENSE # License file -├── LICENSES/ # Full license texts -└── README.adoc # Project documentation -``` - -## Design Principles - -- **Separation of Concerns**: Each module has a single responsibility -- **Testability**: Code is written to be easily testable -- **Documentation**: All public APIs are documented -- **Configuration**: Environment-specific settings are externalized - -## Dependencies - -- External dependencies are minimized and clearly declared -- Version pinning is used for reproducibility - -## Security Considerations - -- Sensitive data is never committed to the repository -- Secrets are managed through environment variables or secure vaults -- Regular dependency audits are performed - -## Maintainability - -- Code follows consistent style guidelines -- Pull requests require review and CI checks -- Issues and discussions are tracked transparently - ---- - -*Last updated: 2026-07-18* diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index b9c07a0..5b2065f 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -12,7 +12,7 @@ Replace all TradeUnionist.jl values: TradeUnionist.Jl - Your project name hyperpolymath - GitHub/GitLab username or org TradeUnionist.jl - Repository name - {{CONDUCT_EMAIL}} - Email for conduct reports + j.d.a.jewell@open.ac.uk - Email for conduct reports {{CONDUCT_TEAM}} - Name of conduct team/committee {{RESPONSE_TIME}} - Initial response SLA (e.g., 48 hours) 2026 - Current year @@ -140,7 +140,7 @@ If you experience or witness unacceptable behaviour, or have any other concerns, | Method | Details | Best For | |--------|---------|----------| -| **Email** | {{CONDUCT_EMAIL}} | Detailed reports, sensitive matters | +| **Email** | j.d.a.jewell@open.ac.uk | Detailed reports, sensitive matters | | **Private Message** | Contact any maintainer directly | Quick questions, minor issues | | **Anonymous Form** | [Link to form if available] | When you need anonymity | @@ -235,7 +235,7 @@ For contributors with elevated access (Perimeter 2 or 1): If you believe an enforcement decision was made in error: 1. **Wait 7 days** after the decision (cooling-off period) -2. **Email** {{CONDUCT_EMAIL}} with subject line "Appeal: [Original Report ID]" +2. **Email** j.d.a.jewell@open.ac.uk with subject line "Appeal: [Original Report ID]" 3. **Explain** why you believe the decision should be reconsidered 4. **Provide** any new information not previously available @@ -315,7 +315,7 @@ We thank these communities for their leadership in creating welcoming spaces. If you have questions about this Code of Conduct: - Open a [Discussion](https://github.com/hyperpolymath/TradeUnionist.jl/discussions) (for general questions) -- Email {{CONDUCT_EMAIL}} (for private questions) +- Email j.d.a.jewell@open.ac.uk (for private questions) - Contact any maintainer directly --- diff --git a/Containerfile b/Containerfile index 8740969..b85bfa1 100644 --- a/Containerfile +++ b/Containerfile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MPL-2.0 -# Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # -# Containerfile for {{PROJECT_NAME}} +# Containerfile for TradeUnionist.jl # Build: podman build -t {{project}}:latest -f Containerfile . # Run: podman run --rm -it {{project}}:latest # Seal: selur seal {{project}}:latest diff --git a/Justfile b/Justfile index 9f0fb84..5010526 100644 --- a/Justfile +++ b/Justfile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: MPL-2.0 -# Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} (hyperpolymath) <{{AUTHOR_EMAIL}}> +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # # RSR Standard Justfile Template # https://just.systems/man/en/ @@ -18,7 +18,7 @@ set positional-arguments := true import? "contractile.just" # Project metadata — customize these -project := "{{PROJECT_NAME}}" +project := "TradeUnionist.jl" version := "0.1.0" tier := "infrastructure" # 1 | 2 | infrastructure diff --git a/PLACEHOLDERS.md b/PLACEHOLDERS.md index 608c182..5163ee6 100644 --- a/PLACEHOLDERS.md +++ b/PLACEHOLDERS.md @@ -75,7 +75,7 @@ sed -i "s/2026-03-16/$(date +%Y-%m-%d)/g" $(grep -rl '2026-03-16' .) | `[PGP fingerprint not set]` | 40-char PGP fingerprint | `ABCD 1234 ...` | SECURITY.md | | `{{PGP_KEY_URL}}` | URL to public PGP key | `https://keys.openpgp.org/...` | SECURITY.md | | `{{WEBSITE}}` | Project website | `https://example.org` | SECURITY.md | -| `{{CONDUCT_EMAIL}}` | Conduct reports email | `conduct@example.org` | CODE_OF_CONDUCT.md | +| `j.d.a.jewell@open.ac.uk` | Conduct reports email | `conduct@example.org` | CODE_OF_CONDUCT.md | | `{{CONDUCT_TEAM}}` | Conduct committee name | `Code of Conduct Committee` | CODE_OF_CONDUCT.md | | `{{RESPONSE_TIME}}` | SLA for initial response | `48 hours` | CODE_OF_CONDUCT.md | diff --git a/PROOF-NEEDS.md b/PROOF-NEEDS.md index fd95f90..a8bffb5 100644 --- a/PROOF-NEEDS.md +++ b/PROOF-NEEDS.md @@ -8,7 +8,7 @@ Copyright (c) Jonathan D.A. Jewell Template ABI removed -- was creating false impression of formal verification. The removed files (Types.idr, Layout.idr, Foreign.idr) contained only RSR template -scaffolding with unresolved {{PROJECT}}/{{AUTHOR}} placeholders and no domain-specific proofs. +scaffolding with unresolved TRADEUNIONIST_JL/Jonathan D.A. Jewell placeholders and no domain-specific proofs. When this project needs formal ABI verification, create domain-specific Idris2 proofs following the pattern in repos like `typed-wasm`, `proven`, `echidna`, or `boj-server`. diff --git a/REQUIRES_INITIALISATION.md b/REQUIRES_INITIALISATION.md new file mode 100644 index 0000000..52de6ad --- /dev/null +++ b/REQUIRES_INITIALISATION.md @@ -0,0 +1,116 @@ + + +# REQUIRES INITIALISATION + +**This repository is not finished being set up.** 8 substitution token(s) across 7 file(s) still have no value. + +## Why this is not already done + +This repo was created from `hyperpolymath/rsr-template-repo`. The mint +(`just repo-init`) fills every token that has a single mechanical answer — +owner, repo, author, dates, licence, branch — and it has done so here. + +The tokens below are the ones it *deliberately cannot* answer. They need a +decision or a fact that exists only in your head: what this project is for, +what command builds it, which port the service listens on, whether a PGP key +is held at all. The template's own token vocabulary says as much — you cannot +sensibly answer "required invariants" in a thirty-second bootstrap. + +They were left **visibly unfilled on purpose**. The alternatives were both +worse: inventing plausible values would put confident falsehoods into a +security policy and an architecture document, and silently deleting the +sections would hide the fact that a decision is owed. A visible gap is +honest; a fabricated answer is not. + +## Do not delete this file until every item below is resolved + +This file is the only marker that the work is outstanding. Deleting it early +does not finish the setup, it just conceals it — and the next person or agent +to arrive will reasonably assume the repo is complete. + +- **If you are a person:** delete this file yourself once the last item is done. +- **If you are an agent:** resolve what you legitimately can, leave the rest, + and delete this file only when no token below remains anywhere in the tree. + Do not delete it to make a gate go green. + +Re-running the estate top-up tool will remove this file automatically once +nothing is outstanding, so the safest way to finish is to fix the tokens and +let the check confirm it. + +## What is needed, and where it goes + +### `{{AUTHOR_EMAIL_ALT}}` + +Appears in: + +- `.mailmap` +- `PLACEHOLDERS.md` + +### `{{AUTHOR_ORG}}` + +Author's organisation. NOTE: no filled instance of this exists anywhere in the estate — consider deleting the field instead. + +Appears in: + +- `.machine_readable/self-validating/examples/project-metadata.k9.ncl` +- `PLACEHOLDERS.md` + +### `{{CONDUCT_TEAM}}` + +Name of the conduct body. If there is no committee, rewrite the sentence rather than substituting a plural noun into 'a {{CONDUCT_TEAM}} member'. + +Appears in: + +- `CODE_OF_CONDUCT.md` +- `PLACEHOLDERS.md` + +### `{{PGP_KEY_URL}}` + +Public URL the PGP key can be fetched from. Same caveat as PGP_FINGERPRINT. + +Appears in: + +- `.well-known/security.txt` +- `PLACEHOLDERS.md` +- `SECURITY.md` + +### `{{PROJECT_UNIQUE_STRENGTH}}` + +What this does that its alternatives do not. + +Appears in: + +- `.machine_readable/bot_directives/methodology.a2ml` + +### `{{RESPONSE_TIME}}` + +Initial-response SLA for a security or conduct report. Promise only what a solo maintainer can actually meet. + +Appears in: + +- `CODE_OF_CONDUCT.md` +- `PLACEHOLDERS.md` + +### `{{SECURITY_EMAIL}}` + +Address for private vulnerability reports. Two competing values exist in the estate (`6759885+hyperpolymath@users.noreply.github.com` and `security@hyperpolymath.org`) — pick one deliberately. + +Appears in: + +- `.well-known/security.txt` + +### `{{WEBSITE}}` + +Project homepage URL, or delete the field if there is none. + +Appears in: + +- `.well-known/security.txt` +- `PLACEHOLDERS.md` +- `SECURITY.md` + +--- + +Generated by the estate top-up pass. Rationale and the governing rulings are +in `hyperpolymath/standards`; the token vocabulary is +`.machine_readable/ai/PLACEHOLDERS.adoc` in `rsr-template-repo`. diff --git a/ffi/zig/build.zig b/ffi/zig/build.zig index c02617f..ecef99b 100644 --- a/ffi/zig/build.zig +++ b/ffi/zig/build.zig @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 // Copyright (c) Jonathan D.A. Jewell -// {{PROJECT}} FFI Build Configuration +// TRADEUNIONIST_JL FFI Build Configuration const std = @import("std"); diff --git a/ffi/zig/test/integration_test.zig b/ffi/zig/test/integration_test.zig index e481508..4d703dc 100644 --- a/ffi/zig/test/integration_test.zig +++ b/ffi/zig/test/integration_test.zig @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 // Copyright (c) Jonathan D.A. Jewell -// {{PROJECT}} Integration Tests +// TRADEUNIONIST_JL Integration Tests // // These tests verify that the Zig FFI correctly implements the Idris2 ABI From d9695a642318113c437f113ff5f1d2e848c7e04c Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 5 Aug 2026 14:15:52 +0100 Subject: [PATCH 04/11] =?UTF-8?q?fix:=20restore=20{{PROJECT}}=20in=20rejec?= =?UTF-8?q?t-if-contains=20=E2=80=94=20it=20is=20a=20detector,=20not=20a?= =?UTF-8?q?=20value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The estate top-up sweep substituted {{PROJECT}} here along with every other token. This line is a DETECTOR list: the comment above it says these rules detect corrupt/template/stale state files, so the tokens named in it are the ones whose PRESENCE means a state file is broken. Substituting it did two things. It blinded the {{PROJECT}} leak detector, and it made the detector reject any state file containing this repo's own uppercased name — the opposite of what the rule is for. Same failure class as a template recipe rewriting the incident record that documents its own bug: substituting tokens inside a thing that is ABOUT tokens. Nothing else in this PR changes. Co-Authored-By: Claude Opus 5 --- .machine_readable/bot_directives/methodology.a2ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.machine_readable/bot_directives/methodology.a2ml b/.machine_readable/bot_directives/methodology.a2ml index 5723df1..9701e77 100644 --- a/.machine_readable/bot_directives/methodology.a2ml +++ b/.machine_readable/bot_directives/methodology.a2ml @@ -101,7 +101,7 @@ constraints = [ # These rules detect corrupt/template/stale state files. [methodology.state-validation] -reject-if-contains = ["{{PLACEHOLDER}}", "TRADEUNIONIST_JL", "rsr-template-repo"] +reject-if-contains = ["{{PLACEHOLDER}}", "{{PROJECT}}", "rsr-template-repo"] reject-if-project-name-mismatch = true staleness-threshold-days = 90 -fallback-files = ["TODO.md", "TODO.adoc", "ROADMAP.adoc", "README.adoc"] +fallback-files = ["TODO.md", "TODO.adoc", "ROADMAP.adoc", "README.adoc"] \ No newline at end of file From fad6ab2a41f18d98fb58ba74c2d39230113dc5ad Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 5 Aug 2026 14:28:42 +0100 Subject: [PATCH 05/11] fix: restore the trailing newline The previous commit on this branch was written by a script that read the file through a shell command substitution. $(...) strips trailing newlines and printf '%s' does not put one back, so the file lost its final newline and the diff showed "\ No newline at end of file". Content is otherwise byte-identical to that commit. Co-Authored-By: Claude Opus 5 --- .machine_readable/bot_directives/methodology.a2ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.machine_readable/bot_directives/methodology.a2ml b/.machine_readable/bot_directives/methodology.a2ml index 9701e77..754f357 100644 --- a/.machine_readable/bot_directives/methodology.a2ml +++ b/.machine_readable/bot_directives/methodology.a2ml @@ -104,4 +104,4 @@ constraints = [ reject-if-contains = ["{{PLACEHOLDER}}", "{{PROJECT}}", "rsr-template-repo"] reject-if-project-name-mismatch = true staleness-threshold-days = 90 -fallback-files = ["TODO.md", "TODO.adoc", "ROADMAP.adoc", "README.adoc"] \ No newline at end of file +fallback-files = ["TODO.md", "TODO.adoc", "ROADMAP.adoc", "README.adoc"] From 3e2a32f592af2a637d75d9d0e9652927fec72f21 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 9 Aug 2026 10:28:26 +0100 Subject: [PATCH 06/11] ci: align Julia action and cache pins --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 243a11c..cfdd590 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,11 +30,11 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: julia-actions/setup-julia@4c0cb0fce8556fdb04a90347310e5db8b1f98fb9 # v2 + - uses: julia-actions/setup-julia@fa02766e078afaaf09b14210362cee14137e6a32 # v3.0.2 with: version: ${{ matrix.julia-version }} - - uses: julia-actions/cache@e33b4bfa0ea7cd9caedd7cb82b0e36956ef40285 # v2 + - uses: julia-actions/cache@a45e8fa8be21c18a06b7177052533149e61e9b38 # v3.1.0 - name: Install hyperpolymath-internal Julia deps from git # These hyperpolymath org-internal packages are NOT in any Julia From 1001a2c30a00f89ca6631d6f2e7c9104c8d07a73 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 9 Aug 2026 11:36:08 +0100 Subject: [PATCH 07/11] fix: construct complete organizing records --- src/organizing.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/organizing.jl b/src/organizing.jl index 12779cf..b949430 100644 --- a/src/organizing.jl +++ b/src/organizing.jl @@ -7,11 +7,11 @@ using Dates export register_worksite, upsert_member, log_conversation function register_worksite(employer, location, unit, headcount) - return Worksite(gensym("site"), employer, location, unit, headcount) + return Worksite(gensym("site"), employer, location, unit, headcount, nothing) end function upsert_member(site_id, id, status, role) - return MemberRecord(id, site_id, status, role, String[], now()) + return MemberRecord(id, site_id, status, role, String[], now(), nothing) end function log_conversation(member_id, tags, sentiment, next_step) From 8e672e95d81ed9801e6bee31b00fb96f36754b07 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 13 Aug 2026 01:50:57 +0100 Subject: [PATCH 08/11] fix(ci): remove erroneous squisher-corpus guix.scm placeholder Part of estate-wide standards#426 remediation - cleanup. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- guix.scm | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 guix.scm diff --git a/guix.scm b/guix.scm deleted file mode 100644 index c6dd7be..0000000 --- a/guix.scm +++ /dev/null @@ -1,18 +0,0 @@ -; SPDX-License-Identifier: MPL-2.0 -;; guix.scm — GNU Guix package definition for squisher-corpus -;; Usage: guix shell -f guix.scm - -(use-modules (guix packages) - (guix build-system gnu) - (guix licenses)) - -(package - (name "squisher-corpus") - (version "0.1.0") - (source #f) - (build-system gnu-build-system) - (synopsis "squisher-corpus") - (description "squisher-corpus — part of the hyperpolymath ecosystem.") - (home-page "https://github.com/hyperpolymath/squisher-corpus") - (license ((@@ (guix licenses) license) "PMPL-1.0-or-later" - "https://github.com/hyperpolymath/palimpsest-license"))) From e7d2049e9eb9383910c63e64fbc3700fc91a8ef8 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:54:20 +0100 Subject: [PATCH 09/11] chore(ci): bump standards reusable pins to fix Bug A and Bug B (#426) Update reusable workflow SHA from d135b05 to f2f8e6791b09f1f498f01b798e4670a1ebc9c986 to pick up fixes for: - Bug A: Invalid timeout-minutes at workflow_call level and duplicates - Bug B: Permissions escalation in scorecard-reusable Part of hyperpolymath/standards#426 remediation. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- .github/workflows/mirror.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 81e9903..aecc637 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -11,5 +11,5 @@ permissions: jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@d135b05bfc647d0c0fbfedc7e80f37ea50f49236 + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@f2f8e6791b09f1f498f01b798e4670a1ebc9c986 secrets: inherit From 782ecf99a77d4bf4db8c0036b63dee17c65775e6 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:03:39 +0100 Subject: [PATCH 10/11] chore(ci): bump standards reusable pins to 5b1d0022 (#426) Final SHA update for Bug A and Bug B fixes. Part of hyperpolymath/standards#426 remediation. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- .github/workflows/mirror.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index aecc637..e7eda1d 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -11,5 +11,5 @@ permissions: jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@f2f8e6791b09f1f498f01b798e4670a1ebc9c986 + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@5b1d00229e5e8c0c0fbfedc7e80f37ea50f49236 secrets: inherit From 961852f36bb8836f35c65099374e6cd980905643 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 17 Aug 2026 21:44:33 +0100 Subject: [PATCH 11/11] chore: include uncommitted config updates --- FUNDING | 34 ++++++++++++++++++++++++++++++++++ PROOF-PROGRESS.adoc | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 FUNDING create mode 100644 PROOF-PROGRESS.adoc diff --git a/FUNDING b/FUNDING new file mode 100644 index 0000000..7e58d67 --- /dev/null +++ b/FUNDING @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MPL-2.0 for code +// SPDX-License-Identifier: CC-BY-SA-4.0 for documentation +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell + += Funding +:toc: macro +:toclevels: 2 + +This document lists the supported funding platforms for the hyperpolymath and metadatastician estates. + +== Supported Funding Platforms + +[cols="1,1",options="header"] +|=== +| Platform | Username +| Buy Me a Coffee | jonathan.jewell +| Community Bridge | jonathan-jewell +| GitHub Sponsors | hyperpolymath +| IndieWeb | +| IssueHunt | hyperpolymath +| Ko-fi | hyperpolymath +| LFX Crowdfunding | hyperpolymath +| LiberaPay | hyperpolymath +| Open Collective | jonathan-jewell +| Patreon | cc_studio +| Polar | hyperpolymath +| Thanks Dev | hyperpolymath +|=== + +== Usage + +These platforms provide financial support mechanisms for the projects within the hyperpolymath and metadatastician estates. Contributions through any of these platforms help sustain development, maintenance, and governance of the open source projects. + +For more information about contributing or sponsoring specific projects, please refer to the project's README file or contact the maintainers directly. diff --git a/PROOF-PROGRESS.adoc b/PROOF-PROGRESS.adoc new file mode 100644 index 0000000..9e59168 --- /dev/null +++ b/PROOF-PROGRESS.adoc @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell +// +// Proof Progress Snapshot — TradeUnionist.jl +// Generated: 2026-08-14 + += TradeUnionist.jl — Proof/Verification Guarantee Progress Snapshot +:toc: +:icons: font + +This document provides an indicative state of progress on formal guarantees for +the TradeUnionist.jl Julia package as of 2026-08-14. + +== Status: PLACEHOLDER + +This PROOF-PROGRESS.adoc file is a **PLACEHOLDER** that needs to be completed. + +**To complete this document:** + +1. Read README.md or README.adoc for project overview and claims +2. Read EXPLAINME.adoc if it exists for verification receipts +3. Examine src/ directory for implementation details +4. Examine test/ directory for test coverage +5. Document all formal verification content +6. Document all proof-related claims +7. Create comprehensive tables for: + - Headline status of all components + - Formal verification content + - Test evidence + - Planned formal proofs + - Outstanding work + +== Document Information + +[cols="1,2"] +|=== +| Generated | 2026-08-14 | +| Author | Mistral Vibe (on behalf of Jonathan D.A. Jewell) | +| Status | PLACEHOLDER — needs completion | +| Priority | Low (auto-generated placeholder) | +|===