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
66 changes: 66 additions & 0 deletions .github/hooks/validate-k9.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MPL-2.0
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
#
# validate-k9.sh — pre-push K9 check, through the canonical validator.
#
# One validator per family (hyperpolymath/standards,
# docs/CONTRACTILE-DESCRIPTILE-VALIDATION.adoc): the grep checks that used to
# live here were a second validator, and they accepted files that contract
# v1.0.0 (D173) rejects. This runs 1-formats/k9/tools/k9-validate.sh from a
# standards checkout over the tracked K9 files, strict, layers L0–L2 (L0–L1
# when nickel is not installed), as the k9-conformance lane does in CI (.github/workflows/dogfood-gate.yml). The lane
# is the gate; this is the early warning.
#
# Environment variables:
# INPUT_PATH — Repository to check (default: .)
# STANDARDS_DIR — A hyperpolymath/standards checkout
# (default: ../standards beside the repository)
#
# Exit codes:
# 0 — Every tracked K9 file passes, or no validator is available (skipped
# with a notice: CI still runs the lane)
# 1 — A file failed

set -euo pipefail

REPO="${INPUT_PATH:-.}"
STANDARDS_DIR="${STANDARDS_DIR:-$(cd "$REPO/.." && pwd)/standards}"
case "$STANDARDS_DIR" in
/*) ;;
*) STANDARDS_DIR="$PWD/$STANDARDS_DIR" ;;
esac
VALIDATOR="$STANDARDS_DIR/1-formats/k9/tools/k9-validate.sh"

if [ ! -f "$VALIDATOR" ]; then

Check failure on line 35 in .github/hooks/validate-k9.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_proof-burrower&issues=AaGpH1lA7Qe6HQ5UtPpp&open=AaGpH1lA7Qe6HQ5UtPpp&pullRequest=124
echo "::notice::K9: no standards checkout at $STANDARDS_DIR (set STANDARDS_DIR to run the validator locally); the k9-conformance lane validates in CI"
exit 0
fi

# L2 is the Nickel evaluation against the contract; without nickel the
# validator reports those checks as SKIPPED and refuses to call that a pass,
# so stop at L1 here and say so. The lane checks L2 in CI either way.
LAYER=L2
if ! command -v nickel >/dev/null 2>&1; then
echo "::notice::K9: nickel is not installed, so layer L2 (Nickel semantics) is left to the CI lane; checking L0–L1"
LAYER=L1
fi

cd "$REPO"
mapfile -t files < <(git ls-files -- '*.k9.ncl' '*.k9' '*.k9.lock' | sort)
if [ "${#files[@]}" -eq 0 ]; then

Check failure on line 51 in .github/hooks/validate-k9.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_proof-burrower&issues=AaGpH1lA7Qe6HQ5UtPpq&open=AaGpH1lA7Qe6HQ5UtPpq&pullRequest=124
echo "::notice::K9: no tracked K9 file"
exit 0
fi

errors=0
for f in "${files[@]}"; do
echo " Validating: $f"
if ! bash "$VALIDATOR" --strict --layer "$LAYER" "$f"; then
errors=$((errors + 1))
fi
done

echo "K9: ${#files[@]} file(s), ${errors} failing (validator: $VALIDATOR)"
[ "$errors" -eq 0 ] || { echo "::error::K9 validation failed for ${errors} file(s)"; exit 1; }

Check failure on line 65 in .github/hooks/validate-k9.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_proof-burrower&issues=AaGpH1lA7Qe6HQ5UtPpr&open=AaGpH1lA7Qe6HQ5UtPpr&pullRequest=124
echo "K9 validation passed."
64 changes: 32 additions & 32 deletions .github/workflows/actions.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ workflows:
'.github/workflows/dogfood-gate.yml':
- 'actions/checkout@v7.0.1'
- 'hyperpolymath/deed-ecosystem@main'
- 'hyperpolymath/k9-ecosystem@main'
'.github/workflows/governance.yml':
- 'metadatastician/standards@857ff096af11451841fb10488fed1438523973a1'
'.github/workflows/guix-nix-policy.yml':
Expand Down Expand Up @@ -95,6 +94,11 @@ dependencies:
commit: 'sha1-9000827ccba6bdab643e8b6fd33ac0654aef8333'
owner_id: 44036562
repo_id: 192626254
'actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08':
ref: 'v4.6.0'
commit: 'sha1-65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08'
owner_id: 44036562
repo_id: 192625955
'actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f':
ref: 'v7.0.0'
commit: 'sha1-bbbca2ddaa5d8feaa63e36b76fdaad77386f024f'
Expand Down Expand Up @@ -137,11 +141,6 @@ dependencies:
commit: 'sha1-51f63319f592f97930c73d9c46184d20bd206393'
owner_id: 26415196
repo_id: 297874902
'editorconfig-checker/action-editorconfig-checker@v3.0.0':
ref: 'v3.0.0'
commit: 'sha1-51f63319f592f97930c73d9c46184d20bd206393'
owner_id: 26415196
repo_id: 297874902
'erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124':
ref: 'v1.24.1'
commit: 'sha1-54075bcc5e249e4758d363f27d099f55d843f124'
Expand Down Expand Up @@ -190,11 +189,6 @@ dependencies:
commit: 'sha1-2155aa26a21758f2ba119f61bc7e0e1981c106fb'
owner_id: 6759885
repo_id: 1275650185
'hyperpolymath/k9-ecosystem@main':
ref: 'main'
commit: 'sha1-c1a34884054fabf0e9de81dbf68f4ba7874e85f1'
owner_id: 6759885
repo_id: 1275650185
'hyperpolymath/smtp-notify-action@v0.5.1':
ref: 'v0.5.1'
commit: 'sha1-e384daf6167a7a7567642d6a62060106244d2413'
Expand All @@ -209,16 +203,25 @@ dependencies:
- 'actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9'
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9'
- 'denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed'
- 'dtolnay/rust-toolchain@e2a55d2ffb04f378e9626c28d38b36d230d1e12f'
- 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393'
- 'erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124'
- 'github/codeql-action@b96794f015dfd88f77b49b1c93e0fa7110f94c63'
- 'goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406'
- 'ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc'
- 'oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6'
- 'swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6'
- 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555'
'metadatastician/standards@857ff096af11451841fb10488fed1438523973a1':
ref: '857ff096af11451841fb10488fed1438523973a1'
commit: 'sha1-857ff096af11451841fb10488fed1438523973a1'
owner_id: 297579217
repo_id: 1116521501
uses:
- 'actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9'
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- 'denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed'
- 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393'
- 'erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124'
- 'oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6'
'ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc':
ref: 'v2.4.4'
commit: 'sha1-2d1146689b8cda280b9bc96326124645441f03bc'
Expand All @@ -239,6 +242,20 @@ dependencies:
commit: 'sha1-f7dd8c54c2067bafc12ca7a55595d5ee9b75204a'
owner_id: 80431187
repo_id: 475074978
uses:
- 'actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08'
- 'slsa-framework/slsa-github-generator@v2.1.0'
- 'softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda'
'slsa-framework/slsa-github-generator@v2.1.0':
ref: 'v2.1.0'
commit: 'sha1-f7dd8c54c2067bafc12ca7a55595d5ee9b75204a'
owner_id: 80431187
repo_id: 475074978
'softprops/action-gh-release@c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda':
ref: 'v2.2.1'
commit: 'sha1-c95fe1489396fe8a9eb87c0abf8aa5b2ef267fda'
owner_id: 2242
repo_id: 204253808
'softprops/action-gh-release@v3.0.3':
ref: 'v3.0.3'
commit: 'sha1-efb35369e0ad2afab669f228072c1b0d510eae64'
Expand All @@ -249,7 +266,7 @@ dependencies:
commit: 'sha1-6323deb102c322ba6fcbdcafc7e3dddab59af2b6'
owner_id: 580492
repo_id: 298565987
'swatinem/rust-cache@v2.9.3':
'swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0':
ref: 'v2.9.3'
commit: 'sha1-d1527c8f67ef9af357290475d4af4b0fab8f12e0'
owner_id: 580492
Expand All @@ -259,20 +276,3 @@ dependencies:
commit: 'sha1-e83874834305fe9a4a2997156cb26c5de65a8555'
owner_id: 135788
repo_id: 208510314
'swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0':
ref: 'v2.9.3'
commit: 'sha1-d1527c8f67ef9af357290475d4af4b0fab8f12e0'
owner_id: 580492
repo_id: 298565987
'metadatastician/standards@857ff096af11451841fb10488fed1438523973a1':
ref: '857ff096af11451841fb10488fed1438523973a1'
commit: 'sha1-857ff096af11451841fb10488fed1438523973a1'
owner_id: 297579217
repo_id: 1116521501
uses:
- 'actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9'
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- 'denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed'
- 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393'
- 'erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124'
- 'oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6'
74 changes: 39 additions & 35 deletions .github/workflows/dogfood-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,54 +65,58 @@ jobs:
fi

# ---------------------------------------------------------------------------
# Job 2: K9 contract validation
# Job 2: K9 conformance through the canonical validator (contract v1.0.0,
# D173), the same lane rsr-template-repo runs. The validator and contract
# come from a pinned standards checkout; .github/hooks/validate-k9.sh is
# the local wrapper, so CI and a pre-push run check the same files.
# ---------------------------------------------------------------------------
k9-validate:
name: Validate K9 contracts
runs-on: ubuntu-latest
timeout-minutes: 15
env:
NICKEL_VERSION: '1.18.0'
NICKEL_SHA256: '9cba4dd65ae9915ec61f73033aafcff307a377665a83fd8f530df086763318cb'

steps:
- name: Checkout repository
uses: actions/checkout@v7.0.1

- name: Check for K9 files
id: detect
run: |
COUNT=$(find . \( -name '*.k9' -o -name '*.k9.ncl' \) -not -path './.git/*' | wc -l)
CONFIG_COUNT=$(find . \( -name '*.toml' -o -name '*.yaml' -o -name '*.yml' -o -name '*.json' \) \
-not -path './.git/*' -not -path './node_modules/*' -not -path './.deno/*' \
-not -name 'package-lock.json' -not -name 'Cargo.lock' -not -name 'deno.lock' | wc -l)
echo "k9_count=$COUNT" >> "$GITHUB_OUTPUT"
echo "config_count=$CONFIG_COUNT" >> "$GITHUB_OUTPUT"
if [ "$COUNT" -eq 0 ] && [ "$CONFIG_COUNT" -gt 0 ]; then
echo "::warning::Found $CONFIG_COUNT config files but no K9 contracts. Run k9iser to generate contracts."
fi

- name: Validate K9 contracts
if: steps.detect.outputs.k9_count > 0
uses: hyperpolymath/k9-ecosystem/validate-action@main
with:
path: '.'
strict: 'false'
persist-credentials: false

- name: Write summary
- name: Checkout canonical K9 validator and contract
uses: actions/checkout@v7.0.1
with:
repository: metadatastician/standards
ref: 8e48b1caade08a552646adeab66558ac43b4360d
path: .standards-k9
sparse-checkout: 1-formats/k9
sparse-checkout-cone-mode: true
persist-credentials: false

- name: Install sha256-verified Nickel CLI
run: |
K9_COUNT="${{ steps.detect.outputs.k9_count }}"
CFG_COUNT="${{ steps.detect.outputs.config_count }}"
if [ "$K9_COUNT" -eq 0 ]; then
cat <<'EOF' >> "$GITHUB_STEP_SUMMARY"
## K9 Contract Validation

:warning: **No K9 contract files found.** Repos with configuration files should have K9 contracts.

Generate contracts with: `k9iser generate .`
EOF
else
echo "## K9 Contract Validation" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "Validated **${K9_COUNT}** K9 contract(s) against **${CFG_COUNT}** config file(s)." >> "$GITHUB_STEP_SUMMARY"
set -euo pipefail
URL="https://github.com/tweag/nickel/releases/download/${NICKEL_VERSION}/nickel-x86_64-linux"
curl -sSfL --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 -o "$RUNNER_TEMP/nickel" "$URL"
echo "${NICKEL_SHA256} ${RUNNER_TEMP}/nickel" | sha256sum -c -
chmod +x "$RUNNER_TEMP/nickel"
echo "$RUNNER_TEMP" >> "$GITHUB_PATH"

- name: Validate K9 contracts (L0–L2)
run: |
set -euo pipefail
rm -rf "$RUNNER_TEMP/standards-k9"
mv "$PWD/.standards-k9" "$RUNNER_TEMP/standards-k9"
if [ ! -f "$RUNNER_TEMP/standards-k9/1-formats/k9/tools/k9-validate.sh" ]; then
echo "::error::K9 validator is missing from the standards checkout"
exit 1
fi
if ! command -v nickel >/dev/null 2>&1; then
echo "::error::nickel is required for K9 layer L2 validation"
exit 1
fi
STANDARDS_DIR="$RUNNER_TEMP/standards-k9" bash .github/hooks/validate-k9.sh

# ---------------------------------------------------------------------------
# Job 3: Empty-linter — invisible character detection
Expand Down
14 changes: 7 additions & 7 deletions .machine_readable/self-validating/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Configuration with Nickel contracts for runtime validation. Evaluated safely wit

=== Hunt Level (Full Execution)

**File:** `examples/setup-repo.k9.ncl`
**File:** `examples/setup-repo.k9.ncl.in`

Full execution with Just recipes. Can run shell commands and modify filesystem.

Expand All @@ -72,13 +72,13 @@ Choose the appropriate security level for your use case:
[source,bash]
----
# Kennel: Pure configuration
cp .machine_readable/contractiles/k9/examples/project-metadata.k9.ncl config/metadata.k9.ncl
cp .machine_readable/self-validating/examples/project-metadata.k9.ncl config/metadata.k9.ncl

# Yard: Validated configuration
cp .machine_readable/contractiles/k9/examples/ci-config.k9.ncl .github/ci.k9.ncl
cp .machine_readable/self-validating/examples/ci-config.k9.ncl .github/ci.k9.ncl

# Hunt: Full automation
cp .machine_readable/contractiles/k9/examples/setup-repo.k9.ncl scripts/setup.k9.ncl
cp .machine_readable/self-validating/examples/setup-repo.k9.ncl.in scripts/setup.k9.ncl # then fill its placeholders

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Provide a renderable Hunt example

Anyone following this new copy command gets a file that cannot pass the canonical validator: setup-repo.k9.ncl.in contains no placeholders to fill, still uses the Nickel 1.18 reserved field name recipes.default, and its Hunt pedigree has neither an explicit capability grant nor the required signature and side-effect declarations. Because the new hook deliberately excludes .k9.ncl.in, CI does not expose this until a user copies it to .k9.ncl; either make the example a conforming component or add real render/sign substitutions that produce one.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is real, but this PR didn't introduce it, so I'm not fixing it here. Before this PR the same file was setup-repo.k9.ncl, and the canonical validator already rejected it. This PR renames it to .in and corrects the copy path. The renamed file also matches rsr-template-repo's own setup-repo.k9.ncl.in, which is where the fix belongs.

The fix should land in rsr-template-repo first, then be copied here. It means turning the example into a conforming Hunt component: rename the reserved recipes.default field, and add the explicit capability grant, the side effects and the signature block. In this repo's copy it also means dropping the steps that write .a2ml files and fetch a PMPL licence. I'm leaving this thread open for the owner to schedule that follow-up.


Generated by Claude Code

----

=== 2. Validate Components
Expand Down Expand Up @@ -137,9 +137,9 @@ K9 contractiles integrate with other RSR standards:

Use these as starting points for your own K9 components:

- `template-kennel.k9.ncl` - Pure data template
- `template-yard.k9.ncl` - Validated config template
- `template-hunt.k9.ncl` - Full execution template
- `template-kennel.k9.ncl.in` - Pure data template
- `template-yard.k9.ncl.in` - Validated config template
- `template-hunt.k9.ncl.in` - Full execution template

== Dependencies

Expand Down
12 changes: 9 additions & 3 deletions .machine_readable/self-validating/methodology-guard.k9.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@ K9!

let methodology_guard = {
pedigree = {
name = "methodology-guard",
version = "1.0.0",
leash = 'Kennel,
schema_version = "1.0.0",
component_type = "validator:methodology-guard",
metadata = {
name = "methodology-guard",
version = "1.0.0",
},
security = {
leash = 'Yard,
},
},
name = "methodology-guard",
version = "1.0.0",
Expand Down
10 changes: 5 additions & 5 deletions container/0.1-AI-MANIFEST.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ canonical_locations:
build_pipeline: "container/ct-build.sh"
entrypoint: "container/entrypoint.sh"
monitoring: "container/vordr.toml"
deployment: "container/deploy.k9.ncl"
deployment: "container/deploy.k9.ncl.in"
example: "container/compose.example.toml"

---
Expand Down Expand Up @@ -90,12 +90,12 @@ files:
detection, resource thresholds, and structured log output.
depends_on: []

- name: "deploy.k9.ncl"
- name: "deploy.k9.ncl.in"
role: "Deployment Component"
description: |
k9-svc deployment specification at Hunt trust level. Full pedigree
(L1-L5), environment configs, container config, and rolling
deployment strategy.
k9-svc deployment template at Hunt trust level (contract v1.0.0),
rendered by hand to deploy.k9.ncl: environment configs, container
config, and rolling deployment strategy.
depends_on: ["compose.toml", "ct-build.sh"]

- name: "compose.example.toml"
Expand Down
8 changes: 5 additions & 3 deletions container/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ All files use `{{PLACEHOLDER}}` tokens that are replaced by `just container-init
| **vordr** runtime monitoring configuration. Defines health endpoints,
crash detection, resource thresholds, and log output.

| `deploy.k9.ncl`
| **k9-svc** deployment component at Hunt trust level. Full pedigree
| `deploy.k9.ncl.in`
| **k9-svc** deployment component at Hunt trust level, kept as a template
until its registry, service name and port are filled. Full pedigree
(L1--L5), environment configs (dev/staging/prod), container
configuration, and rolling deployment strategy.

Expand Down Expand Up @@ -150,7 +151,8 @@ just container-push
selur-compose up --detach
----

For k9-svc managed deployments:
For k9-svc managed deployments, render `deploy.k9.ncl.in` to `deploy.k9.ncl`
first, following its header: `just container-init` does not create it. Then:
Comment thread
hyperpolymath marked this conversation as resolved.
Resolved

[source,bash]
----
Expand Down
Loading
Loading