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
29 changes: 29 additions & 0 deletions .github/workflows/validate-action-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SPDX-License-Identifier: MPL-2.0
name: Validate K9 action

on:
pull_request:
paths:
- ".github/workflows/validate-action-tests.yml"
- "validate-action/**"
push:
branches: [main]
paths:
- ".github/workflows/validate-action-tests.yml"
- "validate-action/**"
workflow_dispatch:

permissions:
contents: read

jobs:
regression-tests:
name: K9 validator regression tests
runs-on: ubuntu-latest
steps:
- name: Check out source
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Check shell syntax
run: bash -n validate-action/validate-k9.sh validate-action/tests/test-validate-k9.sh
- name: Run regression and positive-control tests
run: validate-action/tests/test-validate-k9.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
(updated "2026-06-27"))
(intent "Agent-facing coordination surface for the k9 hub.")
(capabilities
(capability "resolve membership from .machine_readable/6a2/ECOSYSTEM.a2ml")
(capability "resolve membership from .machine_readable/descriptiles/ECOSYSTEM.a2ml")
(capability "resolve upstream pins from .machine_readable/anchors/ANCHOR.a2ml")
(capability "run K9 conformance gates over conformance/valid and conformance/invalid"))
(status "stub — to be expanded with agent playbooks"))
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
(add-member
(step "Create or identify the member repo under hyperpolymath/")
(step "git submodule add -b main https://github.com/hyperpolymath/<name>.git members/<group>/<name>")
(step "Add a (member ...) entry to .machine_readable/6a2/ECOSYSTEM.a2ml and a check_member line to scripts/check-membership.sh")
(step "Add a (member ...) entry to .machine_readable/descriptiles/ECOSYSTEM.a2ml and a check_member line to scripts/check-membership.sh")
(step "Run scripts/check-membership.sh until it passes"))
(add-conformance-case
(step "Add a .k9.ncl fixture under conformance/valid or conformance/invalid")
Expand All @@ -18,7 +18,7 @@
(bump-upstream-pin
(step "Cut or identify the target tag in hyperpolymath/standards")
(step "Replace pin = TODO-tag in .machine_readable/anchors/ANCHOR.a2ml under [upstream.spec] and [upstream.governance]")
(step "Mirror the pin in .machine_readable/6a2/ECOSYSTEM.a2ml (upstream ...)")
(step "Mirror the pin in .machine_readable/descriptiles/ECOSYSTEM.a2ml (upstream ...)")
(step "Make the upstream-pins CI gate enforcing")))
(open-threads
(thread "Resolve spec home: standards/CONTRACTILE-SPEC vs create k9-svc")
Expand Down
14 changes: 7 additions & 7 deletions 0-AI-MANIFEST.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
(upstream "hyperpolymath/standards")
(machine-readable
(anchor ".machine_readable/anchors/ANCHOR.a2ml")
(ecosystem ".machine_readable/6a2/ECOSYSTEM.a2ml")
(state ".machine_readable/6a2/STATE.a2ml")
(meta ".machine_readable/6a2/META.a2ml")
(playbook ".machine_readable/6a2/PLAYBOOK.a2ml")
(agentic ".machine_readable/6a2/AGENTIC.a2ml")
(neurosym ".machine_readable/6a2/NEUROSYM.a2ml"))
(ecosystem ".machine_readable/descriptiles/ECOSYSTEM.a2ml")
(state ".machine_readable/descriptiles/STATE.a2ml")
(meta ".machine_readable/descriptiles/META.a2ml")
(playbook ".machine_readable/descriptiles/PLAYBOOK.a2ml")
(agentic ".machine_readable/descriptiles/AGENTIC.a2ml")
(neurosym ".machine_readable/descriptiles/NEUROSYM.a2ml"))
(owned-here
(conformance "conformance/")
(membership ".machine_readable/6a2/ECOSYSTEM.a2ml")
(membership ".machine_readable/descriptiles/ECOSYSTEM.a2ml")
(drift-ci ".github/workflows/anchor-drift.yml"))
(not-owned-here
(spec (repo "hyperpolymath/standards") (path "docs/CONTRACTILE-SPEC.adoc") (pin "TODO-tag"))
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ We welcome contributions in many forms:
`+conformance/valid/+` and `+conformance/invalid/+` (keep
`+conformance/manifest.a2ml+` in sync).
* *Membership:* Propose member additions/removals via
`+.machine_readable/6a2/ECOSYSTEM.a2ml+`, kept in lockstep with
`+.machine_readable/descriptiles/ECOSYSTEM.a2ml+`, kept in lockstep with
`+.gitmodules+` and `+scripts/check-membership.sh+`.
* *Drift CI & tooling:* Improve `+.github/workflows/anchor-drift.yml+`
or the helper `+scripts/+`.
Expand Down
2 changes: 1 addition & 1 deletion QUICKSTART-DEV.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Clone the hub and initialise member submodules (or run `scripts/init-submodules.
Run `scripts/check-membership.sh` to align manifest, `.gitmodules`, and gitlinks.

== Add a member or conformance case
Follow the `add-member` / `add-conformance-case` steps in `.machine_readable/6a2/PLAYBOOK.a2ml`.
Follow the `add-member` / `add-conformance-case` steps in `.machine_readable/descriptiles/PLAYBOOK.a2ml`.

== Run conformance locally
Validate `conformance/valid` (0 errors) and `conformance/invalid` strict (every case errors).
2 changes: 1 addition & 1 deletion QUICKSTART-USER.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
The coordination hub and satellite for K9 self-validating components and Nickel contractiles.

== Find a member
Locate implementations, tooling, CI, and examples via `.machine_readable/6a2/ECOSYSTEM.a2ml`.
Locate implementations, tooling, CI, and examples via `.machine_readable/descriptiles/ECOSYSTEM.a2ml`.

== Use the specification
The K9 contractile spec lives upstream in `hyperpolymath/standards`, pinned by tag.
Expand Down
6 changes: 3 additions & 3 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ link:.machine_readable/anchors/ANCHOR.a2ml[ANCHOR.a2ml] by tag.

== Owned Here

* link:.machine_readable/6a2/ECOSYSTEM.a2ml[ECOSYSTEM.a2ml] records the member
* link:.machine_readable/descriptiles/ECOSYSTEM.a2ml[ECOSYSTEM.a2ml] records the member
repository manifest.
* link:conformance/manifest.a2ml[conformance/manifest.a2ml] indexes the local
positive and negative K9 fixtures.
Expand All @@ -38,8 +38,8 @@ member submodule. Whether the spec ultimately lives in `standards` or a new
Coordination metadata lives under `.machine_readable/` only:

* `anchors/ANCHOR.a2ml` — authority anchor and upstream pins.
* `6a2/ECOSYSTEM.a2ml` — membership manifest.
* `6a2/{STATE,META,PLAYBOOK,AGENTIC,NEUROSYM}.a2ml` — hub state, ADRs, playbook,
* `descriptiles/ECOSYSTEM.a2ml` — membership manifest.
* `descriptiles/{STATE,META,PLAYBOOK,AGENTIC,NEUROSYM}.a2ml` — hub state, ADRs, playbook,
and agentic / neuro-symbolic notes.

link:0-AI-MANIFEST.a2ml[0-AI-MANIFEST.a2ml] at the repository root is the entry
Expand Down
6 changes: 3 additions & 3 deletions SETUP.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ scripts/check-membership.sh
`+scripts/init-submodules.sh+` initializes from sibling local checkouts
when they are present and skips members that are not available in the
local scope. `+scripts/check-membership.sh+` reads
`+.machine_readable/6a2/ECOSYSTEM.a2ml+`.
`+.machine_readable/descriptiles/ECOSYSTEM.a2ml+`.

=== Machine-Readable Layout

Coordination metadata lives under `+.machine_readable/+` only:

* `+.machine_readable/anchors/ANCHOR.a2ml+` — authority anchor and
upstream pins.
* `+.machine_readable/6a2/ECOSYSTEM.a2ml+` — membership manifest.
* `+.machine_readable/6a2/{STATE,META,PLAYBOOK,AGENTIC,NEUROSYM}.a2ml+`
* `+.machine_readable/descriptiles/ECOSYSTEM.a2ml+` — membership manifest.
* `+.machine_readable/descriptiles/{STATE,META,PLAYBOOK,AGENTIC,NEUROSYM}.a2ml+`
— hub state, ADRs, playbook, and agentic / neuro-symbolic notes.

`+0-AI-MANIFEST.a2ml+` at the repository root indexes this surface.
Expand Down
6 changes: 3 additions & 3 deletions ex/0-AI-MANIFEST.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ format = "a2ml"

[canonical-locations]
machine-readable = ".machine_readable/"
state = ".machine_readable/6a2/STATE.a2ml"
meta = ".machine_readable/6a2/META.a2ml"
ecosystem = ".machine_readable/6a2/ECOSYSTEM.a2ml"
state = ".machine_readable/descriptiles/STATE.a2ml"
meta = ".machine_readable/descriptiles/META.a2ml"
ecosystem = ".machine_readable/descriptiles/ECOSYSTEM.a2ml"
contractiles = ".machine_readable/contractiles/"
bot-directives = ".machine_readable/bot_directives/"

Expand Down
6 changes: 3 additions & 3 deletions gleam/0-AI-MANIFEST.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ format = "a2ml"

[canonical-locations]
machine-readable = ".machine_readable/"
state = ".machine_readable/6a2/STATE.a2ml"
meta = ".machine_readable/6a2/META.a2ml"
ecosystem = ".machine_readable/6a2/ECOSYSTEM.a2ml"
state = ".machine_readable/descriptiles/STATE.a2ml"
meta = ".machine_readable/descriptiles/META.a2ml"
ecosystem = ".machine_readable/descriptiles/ECOSYSTEM.a2ml"
contractiles = ".machine_readable/contractiles/"
bot-directives = ".machine_readable/bot_directives/"

Expand Down
11 changes: 7 additions & 4 deletions scripts/check-membership.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ cd "$(dirname "${BASH_SOURCE[0]}")/.."

failures=0

# Report a membership validation error and increment the failure counter.
fail() {
printf 'membership error: %s\n' "$1" >&2
failures=$((failures + 1))
}

# Check that a member repository is correctly registered in ECOSYSTEM.a2ml
# and .gitmodules with proper URL, branch, and submodule mode.
check_member() {
local group="$1"
local name="$2"
Expand All @@ -21,8 +24,8 @@ check_member() {
local actual_branch
local mode

if ! grep -Fq "(member \"${name}\" (group \"${group}\")" .machine_readable/6a2/ECOSYSTEM.a2ml; then
fail ".machine_readable/6a2/ECOSYSTEM.a2ml missing ${group}/${name}"
if ! grep -Fq "(member \"${name}\" (group \"${group}\")" .machine_readable/descriptiles/ECOSYSTEM.a2ml; then
fail ".machine_readable/descriptiles/ECOSYSTEM.a2ml missing ${group}/${name}"
fi

actual_url="$(git config -f .gitmodules --get "${module}.url" || true)"
Expand Down Expand Up @@ -54,8 +57,8 @@ check_member ci k9-validate-action
check_member ci k9-pre-commit
check_member examples k9-showcase

if ! grep -Fq '(related "k9-svc"' .machine_readable/6a2/ECOSYSTEM.a2ml; then
fail ".machine_readable/6a2/ECOSYSTEM.a2ml missing future k9-svc related reference"
if ! grep -Fq '(related "k9-svc"' .machine_readable/descriptiles/ECOSYSTEM.a2ml; then
fail ".machine_readable/descriptiles/ECOSYSTEM.a2ml missing future k9-svc related reference"
fi

if [[ "${failures}" -gt 0 ]]; then
Expand Down
6 changes: 3 additions & 3 deletions showcase/0-AI-MANIFEST.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ format = "a2ml"

[canonical-locations]
machine-readable = ".machine_readable/"
state = ".machine_readable/6a2/STATE.a2ml"
meta = ".machine_readable/6a2/META.a2ml"
ecosystem = ".machine_readable/6a2/ECOSYSTEM.a2ml"
state = ".machine_readable/descriptiles/STATE.a2ml"
meta = ".machine_readable/descriptiles/META.a2ml"
ecosystem = ".machine_readable/descriptiles/ECOSYSTEM.a2ml"
contractiles = ".machine_readable/contractiles/"
bot-directives = ".machine_readable/bot_directives/"

Expand Down
30 changes: 24 additions & 6 deletions validate-action/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ compliance, pedigree completeness, and hunt-level signature requirements.

== What It Validates

The action performs five checks on every K9 file discovered:
The action performs five checks on every target K9 pedigree contract
discovered. Vendored/fixture paths and estate coordination/session files that
reuse the suffix without being pedigree contracts are excluded by default.
Other `.k9`-suffixed files are treated as targets only when they contain a
pedigree signal such as `K9!`, `magic_number`, a pedigree block, or a K9 schema
reference. Non-pedigree naming collisions are reported as notices and skipped.

[cols="1,1,3"]
|===
| Check | Severity | Description

| K9! magic number
| Error
| The first non-empty line must be exactly `K9!`.
| Plain `.k9` files must begin with `K9!`. Nickel `.k9.ncl` files may instead
carry `magic_number = "K9!"` or apply/import/merge the K9 pedigree schema.

| SPDX header
| Warning
Expand All @@ -34,8 +40,9 @@ The action performs five checks on every K9 file discovered:

| Security level
| Error
| The `leash` or `security_level` field must be one of: `kennel`, `yard`,
`hunt` (case-insensitive). Nickel enum tick syntax (`'Kennel`) is handled.
| The `leash`, `security_level`, or schema-v1 `trust_level` field must be one
of: `kennel`, `yard`, `hunt` (case-insensitive). Nickel enum tick syntax
(`'Kennel`) is handled.

| Hunt-level signature
| Error
Expand All @@ -60,7 +67,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hyperpolymath/standards/k9-svc/actions/validate@main
# Replace <full-commit-sha> with the reviewed immutable revision.
- uses: hyperpolymath/k9-ecosystem/validate-action@<full-commit-sha>
with:
path: '.' # Directory to scan (default: repo root)
strict: 'false' # Promote warnings to errors (default: false)
Expand All @@ -70,10 +78,11 @@ jobs:

[source,yaml]
----
- uses: hyperpolymath/standards/k9-svc/actions/validate@main
- uses: hyperpolymath/k9-ecosystem/validate-action@<full-commit-sha>
id: k9
- run: |
echo "Scanned: ${{ steps.k9.outputs.files-scanned }}"
echo "Skipped: ${{ steps.k9.outputs.files-skipped }}"
echo "Errors: ${{ steps.k9.outputs.errors }}"
echo "Warnings: ${{ steps.k9.outputs.warnings }}"
----
Expand All @@ -93,6 +102,11 @@ jobs:
| `false`
| When `true`, all warnings are promoted to errors and the action fails on any
validation issue.

| `paths-ignore`
| vendored, fixture, coordination/session defaults
| Newline-separated path fragments to exclude. A supplied value replaces the
defaults. Pass an explicit empty string to scan every `.k9`/`.k9.ncl` file.
|===

== Outputs
Expand All @@ -104,6 +118,10 @@ jobs:
| `files-scanned`
| Total number of K9 files discovered and processed.

| `files-skipped`
| Number of discovered K9-suffixed files excluded by path or because they do
not carry a pedigree-contract signal.

| `errors`
| Count of validation errors found. Non-zero causes exit code 1.

Expand Down
27 changes: 26 additions & 1 deletion validate-action/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ name: 'Validate K9 Configurations'
description: >-
Scan and validate K9 configuration files (.k9 and .k9.ncl) in your
repository. Checks for K9! magic number, pedigree block (name, version,
security_level), valid security levels (kennel/yard/hunt), and ensures
security_level, or schema-v1 trust_level), valid security levels
(kennel/yard/hunt), and ensures
hunt-level files include a signature field.
author: 'Jonathan D.A. Jewell'

Expand All @@ -30,11 +31,34 @@ inputs:
will fail on any validation issue. Defaults to false.
required: false
default: 'false'
paths-ignore:
description: >-
Newline-separated path fragments to skip. Each fragment is matched
against the discovered file path. The defaults exclude vendored and
fixture trees plus estate-standard coordination/session files that use
the K9 suffix but are not pedigree contracts. Pass an empty string to
scan every matching file.
required: false
default: |
vendor/
vendored/
verified-container-spec/
.audittraining/
integration/fixtures/
test/fixtures/
tests/fixtures/
absolute-zero/
coordination.k9
session/custom-checks.k9
self-validating/methodology-guard.k9.ncl

outputs:
files-scanned:
description: 'Number of K9 files scanned'
value: ${{ steps.validate.outputs.files_scanned }}
files-skipped:
description: 'Number of non-target K9 paths skipped'
value: ${{ steps.validate.outputs.files_skipped }}
errors:
description: 'Number of validation errors found'
value: ${{ steps.validate.outputs.errors }}
Expand All @@ -51,5 +75,6 @@ runs:
env:
INPUT_PATH: ${{ inputs.path }}
INPUT_STRICT: ${{ inputs.strict }}
INPUT_PATHS_IGNORE: ${{ inputs.paths-ignore }}
run: |
"${GITHUB_ACTION_PATH}/validate-k9.sh"
Loading
Loading