From f911392b9f6e75814f0c44fb38c78a2648accba9 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 20 Jun 2026 18:12:25 +0000 Subject: [PATCH 1/3] Add k9-ecosystem aggregator hub (staged for extraction) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scaffold the standalone k9-ecosystem hub for the K9 self-validating configuration format, staged under k9-ecosystem/ for delivery (intended end-state: its own top-level primary — see k9-ecosystem/BOOTSTRAP.md). The hub owns the canonical spec (spec/SPEC.adoc, v0.1 draft; k9-rs normative until ratified) and a language-agnostic conformance suite (conformance/fixtures/minimal), and aggregates the 11 K9 member repos as git submodules grouped by role: implementations k9-rs, k9_ex, k9_gleam, k9-deno, k9-haskell tooling tree-sitter-k9, vscode-k9, pandoc-k9 ci k9-validate-action, k9-pre-commit examples k9-showcase Members stay standalone (idiomatic to crates.io/Hex/Hackage/JSR and to the tree-sitter/vsce/pre-commit/Actions conventions); the hub provides a single spec source-of-truth, one conformance suite, and one front door. Includes Justfile + scripts/init-submodules.sh for submodule orchestration and .machine_readable/6a2 governance. developer-ecosystem ECOSYSTEM/STATE indexed to reference the staged hub. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_019i2e5ABGBKQmMdqk8puFWx --- .machine_readable/6a2/ECOSYSTEM.a2ml | 2 +- .machine_readable/6a2/STATE.a2ml | 4 + k9-ecosystem/.gitignore | 10 ++ k9-ecosystem/.gitmodules | 48 +++++++ .../.machine_readable/6a2/ECOSYSTEM.a2ml | 33 +++++ k9-ecosystem/.machine_readable/6a2/META.a2ml | 31 +++++ k9-ecosystem/.machine_readable/6a2/STATE.a2ml | 27 ++++ k9-ecosystem/BOOTSTRAP.md | 55 ++++++++ k9-ecosystem/Justfile | 34 +++++ k9-ecosystem/LICENSE | 14 ++ k9-ecosystem/README.adoc | 128 ++++++++++++++++++ k9-ecosystem/conformance/README.adoc | 44 ++++++ .../conformance/fixtures/minimal/component.k9 | 14 ++ .../fixtures/minimal/expected.json | 21 +++ k9-ecosystem/members/README.adoc | 36 +++++ k9-ecosystem/scripts/init-submodules.sh | 46 +++++++ k9-ecosystem/spec/README.adoc | 19 +++ k9-ecosystem/spec/SPEC.adoc | 120 ++++++++++++++++ 18 files changed, 685 insertions(+), 1 deletion(-) create mode 100644 k9-ecosystem/.gitignore create mode 100644 k9-ecosystem/.gitmodules create mode 100644 k9-ecosystem/.machine_readable/6a2/ECOSYSTEM.a2ml create mode 100644 k9-ecosystem/.machine_readable/6a2/META.a2ml create mode 100644 k9-ecosystem/.machine_readable/6a2/STATE.a2ml create mode 100644 k9-ecosystem/BOOTSTRAP.md create mode 100644 k9-ecosystem/Justfile create mode 100644 k9-ecosystem/LICENSE create mode 100644 k9-ecosystem/README.adoc create mode 100644 k9-ecosystem/conformance/README.adoc create mode 100644 k9-ecosystem/conformance/fixtures/minimal/component.k9 create mode 100644 k9-ecosystem/conformance/fixtures/minimal/expected.json create mode 100644 k9-ecosystem/members/README.adoc create mode 100755 k9-ecosystem/scripts/init-submodules.sh create mode 100644 k9-ecosystem/spec/README.adoc create mode 100644 k9-ecosystem/spec/SPEC.adoc diff --git a/.machine_readable/6a2/ECOSYSTEM.a2ml b/.machine_readable/6a2/ECOSYSTEM.a2ml index 28d8aaa8e..bf9cec5e0 100644 --- a/.machine_readable/6a2/ECOSYSTEM.a2ml +++ b/.machine_readable/6a2/ECOSYSTEM.a2ml @@ -18,7 +18,7 @@ git-tools = ["git-hud", "gitloom", "git-reunify", "git-seo", "polysafe-gitfixer" repo-management = ["oikos", "robot-repo-automaton", "grim-repo", "robot-vacuum-cleaner"] scaffolding = ["scaffoldia"] developer-ux = ["rescript-evangeliser (→ nextgen-languages-evangeliser)", "recon-silly-ation", "nickel-config-reporter"] -ecosystems = ["affinescript-ecosystem", "rescript-ecosystem", "zig-ecosystem", "v-ecosystem (legacy/community-handoff)", "deno-ecosystem", "julia-ecosystem", "coq-ecosystem", "idris2-ecosystem", "iser-tools"] +ecosystems = ["affinescript-ecosystem", "rescript-ecosystem", "zig-ecosystem", "v-ecosystem (legacy/community-handoff)", "deno-ecosystem", "julia-ecosystem", "coq-ecosystem", "idris2-ecosystem", "iser-tools", "k9-ecosystem (staged; pending extraction to standalone primary — see k9-ecosystem/BOOTSTRAP.md)"] cadre = ["cadre-router", "cadre-tea-router"] zig-api = ["zig-api (Phase 1+2 complete)"] diff --git a/.machine_readable/6a2/STATE.a2ml b/.machine_readable/6a2/STATE.a2ml index 9ec23e593..63d3e60ae 100644 --- a/.machine_readable/6a2/STATE.a2ml +++ b/.machine_readable/6a2/STATE.a2ml @@ -13,6 +13,10 @@ name = "developer-ecosystem" completion-percentage = 55 phase = "license-stamps-flipped-to-MPL-2.0; bot_directives-rename-done; contractiles-currency-pass-2026-06-05" +[session-2026-06-20-k9-ecosystem-scaffold] +summary = "Scaffolded the k9-ecosystem aggregator hub under k9-ecosystem/ (staged for extraction to a standalone primary). Owns the K9 spec (spec/SPEC.adoc v0.1 draft) + conformance suite; aggregates 11 members (k9-rs/k9_ex/k9_gleam/k9-deno/k9-haskell + tree-sitter-k9/vscode-k9/pandoc-k9 + k9-validate-action/k9-pre-commit + k9-showcase) as git submodules via k9-ecosystem/.gitmodules. Added Justfile, scripts/init-submodules.sh, BOOTSTRAP.md, and 6a2 governance. Reasoning: members must stay standalone for their registries/toolchains; hub gives one spec + conformance source-of-truth. Staged here because a new top-level repo was outside session scope." +files-changed = "18 (16 new under k9-ecosystem/, ECOSYSTEM.a2ml + STATE.a2ml indexed)" + [session-2026-06-05-currency-checkpoint] summary = "Currency checkpoint (claude/zen-knuth-6hoEt branch). Tasks completed: (1) agent_instructions→bot_directives rename already done at root; external references fixed in 8 files across affinescript-ecosystem and rescript-ecosystem satellite subdirs. (2) Contractiles: INDEX.a2ml + _base.ncl added; missing verb dirs created (adjust/, bust/, intend/) each with Xfile.a2ml + canonical .ncl runner; must/trust/dust runners (must.ncl/trust.ncl/dust.ncl) added alongside existing Xfile.a2ml. (3) svc/k9 templates already present. (4) 6a2 files refreshed. (5) README/EXPLAINME currency-only fixes. (6) License scan flagged." files-changed = "~20 (currency + contractile files)" diff --git a/k9-ecosystem/.gitignore b/k9-ecosystem/.gitignore new file mode 100644 index 000000000..5ae954b48 --- /dev/null +++ b/k9-ecosystem/.gitignore @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: MPL-2.0 +# Submodule build artifacts (members manage their own; never commit theirs here) +**/target/ +**/_build/ +**/build/ +**/node_modules/ +**/.deno/ +**/dist-newstyle/ +*.log +.DS_Store diff --git a/k9-ecosystem/.gitmodules b/k9-ecosystem/.gitmodules new file mode 100644 index 000000000..805d3502d --- /dev/null +++ b/k9-ecosystem/.gitmodules @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# K9 ecosystem members, grouped by role. +# Inert while staged inside developer-ecosystem (git only reads the root +# .gitmodules). Becomes active once this directory is extracted to its own +# repository — see BOOTSTRAP.md. + +# --- Implementations ------------------------------------------------------- +[submodule "members/implementations/k9-rs"] + path = members/implementations/k9-rs + url = git@github.com:hyperpolymath/k9-rs.git +[submodule "members/implementations/k9_ex"] + path = members/implementations/k9_ex + url = git@github.com:hyperpolymath/k9_ex.git +[submodule "members/implementations/k9_gleam"] + path = members/implementations/k9_gleam + url = git@github.com:hyperpolymath/k9_gleam.git +[submodule "members/implementations/k9-deno"] + path = members/implementations/k9-deno + url = git@github.com:hyperpolymath/k9-deno.git +[submodule "members/implementations/k9-haskell"] + path = members/implementations/k9-haskell + url = git@github.com:hyperpolymath/k9-haskell.git + +# --- Tooling --------------------------------------------------------------- +[submodule "members/tooling/tree-sitter-k9"] + path = members/tooling/tree-sitter-k9 + url = git@github.com:hyperpolymath/tree-sitter-k9.git +[submodule "members/tooling/vscode-k9"] + path = members/tooling/vscode-k9 + url = git@github.com:hyperpolymath/vscode-k9.git +[submodule "members/tooling/pandoc-k9"] + path = members/tooling/pandoc-k9 + url = git@github.com:hyperpolymath/pandoc-k9.git + +# --- CI / validation ------------------------------------------------------- +[submodule "members/ci/k9-validate-action"] + path = members/ci/k9-validate-action + url = git@github.com:hyperpolymath/k9-validate-action.git +[submodule "members/ci/k9-pre-commit"] + path = members/ci/k9-pre-commit + url = git@github.com:hyperpolymath/k9-pre-commit.git + +# --- Examples -------------------------------------------------------------- +[submodule "members/examples/k9-showcase"] + path = members/examples/k9-showcase + url = git@github.com:hyperpolymath/k9-showcase.git diff --git a/k9-ecosystem/.machine_readable/6a2/ECOSYSTEM.a2ml b/k9-ecosystem/.machine_readable/6a2/ECOSYSTEM.a2ml new file mode 100644 index 000000000..758de12ce --- /dev/null +++ b/k9-ecosystem/.machine_readable/6a2/ECOSYSTEM.a2ml @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +# ECOSYSTEM.a2ml — Ecosystem position + +[metadata] +project = "k9-ecosystem" +last-updated = "2026-06-20" +ecosystem = "hyperpolymath" + +[position] +type = "aggregator-hub" +role = "canonical home of the K9 self-validating configuration format — owns the spec + conformance suite, aggregates the implementations and tooling as submodules" +parent = "hyperpolymath estate" +staged-in = "developer-ecosystem/k9-ecosystem (pending extraction to standalone repo — see BOOTSTRAP.md)" + +[members] +# Aggregated as git submodules, grouped by role (see .gitmodules) +implementations = ["k9-rs (reference, Rust/crates.io)", "k9_ex (Elixir/Hex)", "k9_gleam (Gleam/Hex)", "k9-deno (Deno/JSR)", "k9-haskell (Haskell/Hackage)"] +tooling = ["tree-sitter-k9", "vscode-k9", "pandoc-k9"] +ci = ["k9-validate-action", "k9-pre-commit"] +examples = ["k9-showcase"] + +[owns] +spec = "spec/SPEC.adoc (v0.1 draft; k9-rs normative until ratified)" +conformance = "conformance/fixtures/ (canonical-projection golden tests, all implementations)" + +[related-projects] +# relationship types: sibling-standard, dependency, dependent, inspiration, potential-consumer +standards = { name = "hyperpolymath/standards", relationship = "dependent", note = "references k9-svc as a reusable standard" } +developer-ecosystem = { name = "developer-ecosystem", relationship = "dependent", note = "contractile tridents consume .k9.ncl (k9.ncl); also potential dev-ux home for vscode-k9" } + +[integration-points] +# Each implementation member is obligated to run conformance/fixtures/. diff --git a/k9-ecosystem/.machine_readable/6a2/META.a2ml b/k9-ecosystem/.machine_readable/6a2/META.a2ml new file mode 100644 index 000000000..a4f5d3f8d --- /dev/null +++ b/k9-ecosystem/.machine_readable/6a2/META.a2ml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +# META.a2ml — Architecture decisions and development practices + +[metadata] +project = "k9-ecosystem" +last-updated = "2026-06-20" + +[decision.hub-plus-submodules] +status = "accepted" +date = "2026-06-20" +decision = "Aggregate the K9 family as a hub repo with members as git submodules, rather than a single monorepo or scattered standalone repos." +rationale = "Several members cannot be subdirectories without breaking their toolchains: tree-sitter-k9 (tree-sitter CLI + bindings expect a repo named tree-sitter-* at root), k9-validate-action (consumed as owner/repo@ref; Marketplace needs its own repo), k9-pre-commit (consumers reference the repo URL; .pre-commit-hooks.yaml at root), vscode-k9 (vsce per-extension publishing). The five implementations each publish to a different registry (crates.io/Hex/Hackage/JSR) with independent versioning. A hub still gives one spec source-of-truth, one conformance suite, and one front door." +follows = "developer-ecosystem satellites + *-ecosystem submodule pattern" + +[decision.standalone-primary] +status = "accepted" +date = "2026-06-20" +decision = "k9-ecosystem is its own top-level primary, not nested under developer-ecosystem." +rationale = "developer-ecosystem's charter is developer workflow tooling; K9 is a configuration format/standard with a different audience. Nesting muddies both charters. Staged inside developer-ecosystem only as a delivery vehicle (session scope); end-state is standalone (BOOTSTRAP.md)." + +[decision.naming] +status = "accepted" +date = "2026-06-20" +decision = "Umbrella named 'k9-ecosystem', not 'k9-svc'." +rationale = "k9-svc is already the Rust crate lib name (k9_svc, 'self-validating configuration') and a referenced standard in hyperpolymath/standards; reusing it as the umbrella would collide. 'k9-ecosystem' matches the estate's *-ecosystem convention." + +[practices] +spec-first = "Format changes land in spec/ first, gated by conformance/ fixtures, then propagate to implementations." +spdx = "MPL-2.0 SPDX header on every file." +languages = "Docs in AsciiDoc/Markdown; machine-readable in .a2ml (TOML); orchestration in just + minimal Bash; configs in Nickel. No banned languages introduced." diff --git a/k9-ecosystem/.machine_readable/6a2/STATE.a2ml b/k9-ecosystem/.machine_readable/6a2/STATE.a2ml new file mode 100644 index 000000000..f220b8896 --- /dev/null +++ b/k9-ecosystem/.machine_readable/6a2/STATE.a2ml @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +# STATE.a2ml — Project state checkpoint + +[metadata] +project = "k9-ecosystem" +version = "0.1.0" +last-updated = "2026-06-20" +status = "scaffolded" + +[project-context] +name = "k9-ecosystem" +completion-percentage = 20 +phase = "hub scaffolded and staged inside developer-ecosystem; awaiting extraction to standalone repo and live submodule wiring" + +[session-2026-06-20-hub-scaffold] +summary = "Created the k9-ecosystem aggregator hub: README, .gitmodules (11 members grouped implementations/tooling/ci/examples), Justfile + scripts/init-submodules.sh, spec/SPEC.adoc (v0.1 draft) + spec/README, conformance/ suite with the 'minimal' fixture (component.k9 + expected.json), members/README, LICENSE, BOOTSTRAP.md, and 6a2 governance. Staged at developer-ecosystem/k9-ecosystem/ because the session scope did not permit creating a new top-level repo." +files-added = 16 + +[next-actions] +extract = "Promote to standalone hyperpolymath/k9-ecosystem (BOOTSTRAP.md option A)" +wire = "Run scripts/init-submodules.sh to populate the 11 member submodules" +cross-link = "Update each member's 6a2/ECOSYSTEM.a2ml to reference k9-ecosystem (bidirectional graph)" +spec = "Ratify SPEC.adoc; resolve the [OPEN] items via conformance fixtures" + +[blockers] +new-repo-scope = "Creating/pushing hyperpolymath/k9-ecosystem is outside this session's repo scope; needs scope grant or manual extraction" diff --git a/k9-ecosystem/BOOTSTRAP.md b/k9-ecosystem/BOOTSTRAP.md new file mode 100644 index 000000000..51b03cc02 --- /dev/null +++ b/k9-ecosystem/BOOTSTRAP.md @@ -0,0 +1,55 @@ + + + +# Bootstrapping `k9-ecosystem` into a standalone repository + +This directory was authored as the **standalone `k9-ecosystem` hub** but is +currently **staged inside `developer-ecosystem/`** because the delivering +session's scope did not permit creating a new top-level GitHub repository. +Everything here is defined as if `k9-ecosystem/` were a repository root (its own +`.gitmodules`, `README.adoc`, `LICENSE`, `.machine_readable/6a2/`), so promotion +is mechanical. + +## Option A — extract preserving history (recommended) + +```sh +# from the developer-ecosystem repo root +git subtree split -P k9-ecosystem -b k9-ecosystem-export + +# create the empty repo hyperpolymath/k9-ecosystem on GitHub first, then: +mkdir ../k9-ecosystem && cd ../k9-ecosystem +git init +git pull ../developer-ecosystem k9-ecosystem-export +git remote add origin git@github.com:hyperpolymath/k9-ecosystem.git +git push -u origin main + +# activate the members +just init # or: bash scripts/init-submodules.sh +``` + +## Option B — fresh start (no history) + +```sh +cp -r developer-ecosystem/k9-ecosystem /path/to/k9-ecosystem +cd /path/to/k9-ecosystem +git init && git add -A && git commit -m "Initialise k9-ecosystem hub" +git remote add origin git@github.com:hyperpolymath/k9-ecosystem.git +git push -u origin main +bash scripts/init-submodules.sh +``` + +## After extraction + +1. Copy the full MPL-2.0 text to `license/MPL-2.0.txt` (see `LICENSE`). +2. Remove the staging copy from `developer-ecosystem/` and, if desired, add the + new repo back as a submodule or cross-reference it from + `developer-ecosystem/.machine_readable/6a2/ECOSYSTEM.a2ml`. +3. Point each member repo's `.machine_readable/6a2/ECOSYSTEM.a2ml` at + `k9-ecosystem` (relationship `dependency` / `sibling-standard`) so the graph + is bidirectional. + +## Alternative: let the agent push it directly + +If you add `hyperpolymath/k9-ecosystem` to the session's repository scope (and +create the empty repo), the agent can push the hub and open its PR directly, +skipping the manual extraction above. diff --git a/k9-ecosystem/Justfile b/k9-ecosystem/Justfile new file mode 100644 index 000000000..2f1878dab --- /dev/null +++ b/k9-ecosystem/Justfile @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# k9-ecosystem hub — submodule orchestration. +# These recipes assume this directory is a repository root (post-extraction). + +# List available recipes +default: + @just --list + +# Populate every member submodule +init: + git submodule update --init --recursive + +# Add all members from scratch (first-time wiring; idempotent) +wire: + bash scripts/init-submodules.sh + +# Fast-forward every member to its tracked commit +update: + git submodule update --remote --merge + +# Show checkout state of every member +status: + git submodule status --recursive + +# Run a command in every member, e.g. `just foreach 'git status -s'` +foreach CMD: + git submodule foreach --recursive '{{CMD}}' + +# Verify the canonical spec and conformance fixtures are present +check-spec: + test -f spec/SPEC.adoc && echo "spec present" + test -d conformance/fixtures && echo "conformance fixtures present" diff --git a/k9-ecosystem/LICENSE b/k9-ecosystem/LICENSE new file mode 100644 index 000000000..e80368936 --- /dev/null +++ b/k9-ecosystem/LICENSE @@ -0,0 +1,14 @@ +SPDX-License-Identifier: MPL-2.0 +SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) + +This project is licensed under the Mozilla Public License, version 2.0 +(MPL-2.0-or-later), consistent with the hyperpolymath estate's Palimpsest +philosophy. + +The canonical MPL-2.0 text is provided by the estate at +`developer-ecosystem/license/` and by the upstream palimpsest-license +repository. When this directory is extracted into its own repository, copy the +full MPL-2.0 text to `license/MPL-2.0.txt` alongside this notice +(see BOOTSTRAP.md). + +Each source file additionally carries an SPDX `License-Identifier` header. diff --git a/k9-ecosystem/README.adoc b/k9-ecosystem/README.adoc new file mode 100644 index 000000000..b5e7d4bbe --- /dev/null +++ b/k9-ecosystem/README.adoc @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +image:https://img.shields.io/badge/License-MPL_2.0-blue.svg[MPL-2.0-or-later,link="https://opensource.org/licenses/MPL-2.0"] +image:https://img.shields.io/badge/Philosophy-Palimpsest-indigo.svg[Palimpsest,link="https://github.com/hyperpolymath/palimpsest-license"] + += K9 Ecosystem +Jonathan D.A. Jewell +:toc: left +:toclevels: 3 +:icons: font +:revnumber: 0.1.0 +:revdate: 2026-06-20 + +[NOTE] +==== +This directory is the *standalone `k9-ecosystem` hub*, staged inside +`developer-ecosystem/` for delivery. Its intended end-state is its own +top-level repository (`hyperpolymath/k9-ecosystem`). See +link:BOOTSTRAP.md[BOOTSTRAP.md] for the one-command extraction. +==== + +== What is K9? + +*K9* is a self-validating configuration format for software component +declarations. Each component carries its own provenance, security posture, +build recipe, and runtime contracts, so that a `.k9` file is both +*documentation* and an *executable check*. + +Each component declares: + +[cols="1,3", options="header"] +|=== +| Field | Meaning +| *Pedigree* | Provenance — origin URL, author, license, supply-chain hashes +| *SecurityLevel* | Three-tier model: `Kennel` / `Yard` / `Hunt` +| *Recipe* | Build or assembly instructions (tool + command) +| *Contracts* | Runtime invariants with check commands and severity levels +|=== + +Two surface formats are defined: + +* `.k9` — YAML-like plain-text format, parsed natively +* `.k9.ncl` — https://nickel-lang.org[Nickel] format (requires the Nickel evaluator) + +The canonical format definition lives in link:spec/SPEC.adoc[`spec/SPEC.adoc`]; +the shared cross-implementation test suite lives in link:conformance/[`conformance/`]. + +== Why this hub exists + +The K9 family spans five language implementations plus editor, CI, and +documentation tooling — eleven repositories in all. They are kept as +*independent repositories* (each idiomatic to its package registry and tooling) +and *aggregated here as git submodules*. This gives one source of truth for the +spec, one conformance suite every implementation tests against, and one front +door — without forcing a monorepo on toolchains that expect standalone repos +(crates.io, Hex, Hackage, JSR, the Tree-sitter CLI, the VS Code Marketplace, +pre-commit, and GitHub Actions). + +== Members + +Run `just init` (or `scripts/init-submodules.sh`) to populate the submodules. + +=== Implementations (parsers + renderers) + +[cols="1,1,2", options="header"] +|=== +| Repo | Language | Registry +| `k9-rs` | Rust | crates.io (reference implementation) +| `k9_ex` | Elixir | Hex +| `k9_gleam` | Gleam | Hex / Gleam +| `k9-deno` | Deno | JSR +| `k9-haskell` | Haskell | Hackage +|=== + +=== Tooling (format + editor) + +[cols="1,3", options="header"] +|=== +| Repo | Purpose +| `tree-sitter-k9` | Tree-sitter grammar + bindings +| `vscode-k9` | VS Code language extension +| `pandoc-k9` | Pandoc integration for `.k9.ncl` (Nickel) files +|=== + +=== CI / validation + +[cols="1,3", options="header"] +|=== +| Repo | Purpose +| `k9-validate-action` | GitHub Action — validates `.k9` files in CI +| `k9-pre-commit` | pre-commit hook — validates `.k9` files locally +|=== + +=== Examples + +[cols="1,3", options="header"] +|=== +| Repo | Purpose +| `k9-showcase` | Worked examples and demonstrations +|=== + +== Quick start + +[source,sh] +---- +# clone with all members +git clone --recurse-submodules +cd k9-ecosystem + +# or, after a plain clone +just init # = git submodule update --init --recursive + +just status # show member checkout state +just update # fast-forward every member to its tracked commit +---- + +== Relationship to the wider estate + +* `hyperpolymath/standards` references *k9-svc* (the Rust crate lib name, + `k9_svc`) as a reusable standard; the `.k9.ncl` form is woven into the + `developer-ecosystem` *contractile tridents* (`k9.ncl`). This hub is the + home of the *format* itself, distinct from those consumers. +* `vscode-k9` may also be cross-referenced as a `developer-ux` satellite of + `developer-ecosystem`; a submodule can be aggregated by more than one hub. + +== License + +MPL-2.0-or-later. SPDX headers are carried on every file. See link:LICENSE[LICENSE]. diff --git a/k9-ecosystem/conformance/README.adoc b/k9-ecosystem/conformance/README.adoc new file mode 100644 index 000000000..73ce25c88 --- /dev/null +++ b/k9-ecosystem/conformance/README.adoc @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) += K9 Conformance Suite + +Language-agnostic fixtures that *every* implementation must satisfy. This is the +contract that keeps five independent parsers (`k9-rs`, `k9_ex`, `k9_gleam`, +`k9-deno`, `k9-haskell`) behaving identically. + +== Layout + +---- +conformance/ +└── fixtures/ + └── / + ├── component.k9 # input (also /component.k9.ncl where relevant) + └── expected.json # canonical projection (see ../spec/SPEC.adoc §7) +---- + +== Contract + +For each fixture, an implementation parses `component.k9` and emits the canonical +JSON projection. The result MUST be *structurally equal* to `expected.json` +(key order per declaration order, `security` lower-cased). Whitespace and +insignificant formatting are ignored. + +== Wiring an implementation + +Each implementation member adds a thin test that walks `fixtures/`, parses each +input, and compares against `expected.json`. Suggested integration: + +* `k9-rs` — a `#[test]` iterating the fixtures directory +* `k9_ex` / `k9_gleam` — an ExUnit / gleeunit case +* `k9-deno` — a `Deno.test` over the fixtures +* `k9-haskell` — an HUnit/`tasty` golden test + +The fixtures are intentionally implementation-free so they can be vendored or +referenced (git submodule / sparse checkout) by each member. + +== Adding a fixture + +1. Create `fixtures//component.k9`. +2. Generate `expected.json` with the reference implementation (`k9-rs`) and + eyeball it against link:../spec/SPEC.adoc[the spec]. +3. Confirm every implementation passes before merging. diff --git a/k9-ecosystem/conformance/fixtures/minimal/component.k9 b/k9-ecosystem/conformance/fixtures/minimal/component.k9 new file mode 100644 index 000000000..261a89b37 --- /dev/null +++ b/k9-ecosystem/conformance/fixtures/minimal/component.k9 @@ -0,0 +1,14 @@ +component: hello-svc + version: 0.1.0 + pedigree: + origin: https://github.com/hyperpolymath/hello-svc + author: Jonathan D.A. Jewell + license: MPL-2.0 + security: kennel + recipe: + tool: cargo + command: build --release + contracts: + - name: binary-exists + check: test -x target/release/hello-svc + severity: error diff --git a/k9-ecosystem/conformance/fixtures/minimal/expected.json b/k9-ecosystem/conformance/fixtures/minimal/expected.json new file mode 100644 index 000000000..f1c01aef3 --- /dev/null +++ b/k9-ecosystem/conformance/fixtures/minimal/expected.json @@ -0,0 +1,21 @@ +{ + "component": "hello-svc", + "version": "0.1.0", + "pedigree": { + "origin": "https://github.com/hyperpolymath/hello-svc", + "author": "Jonathan D.A. Jewell", + "license": "MPL-2.0" + }, + "security": "kennel", + "recipe": { + "tool": "cargo", + "command": "build --release" + }, + "contracts": [ + { + "name": "binary-exists", + "check": "test -x target/release/hello-svc", + "severity": "error" + } + ] +} diff --git a/k9-ecosystem/members/README.adoc b/k9-ecosystem/members/README.adoc new file mode 100644 index 000000000..13c997b49 --- /dev/null +++ b/k9-ecosystem/members/README.adoc @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) += K9 Members + +Member repositories are aggregated here as *git submodules*, grouped by role. +They are empty until populated — run `just init` (or +`bash scripts/init-submodules.sh`) from the hub root. + +---- +members/ +├── implementations/ # parsers + renderers, one per language +│ ├── k9-rs # Rust (reference implementation, crates.io) +│ ├── k9_ex # Elixir (Hex) +│ ├── k9_gleam # Gleam (Hex / Gleam) +│ ├── k9-deno # Deno (JSR) +│ └── k9-haskell # Haskell (Hackage) +├── tooling/ # format + editor support +│ ├── tree-sitter-k9 # grammar + bindings +│ ├── vscode-k9 # VS Code extension +│ └── pandoc-k9 # Pandoc integration for .k9.ncl +├── ci/ # validation hooks +│ ├── k9-validate-action # GitHub Action +│ └── k9-pre-commit # pre-commit hook +└── examples/ + └── k9-showcase # worked examples +---- + +Each member stays idiomatic to its own ecosystem (its own build tool, version, +release cadence, and package registry). The hub pins each to a specific commit; +`just update` advances those pins. + +== Conformance obligation + +Every *implementation* member is expected to run the shared fixtures in +`../conformance/fixtures/` and match the documented expected output. This is the +contract that keeps five independent parsers behaving identically. diff --git a/k9-ecosystem/scripts/init-submodules.sh b/k9-ecosystem/scripts/init-submodules.sh new file mode 100755 index 000000000..04d2fa2a5 --- /dev/null +++ b/k9-ecosystem/scripts/init-submodules.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# Idempotently wire every K9 member as a git submodule. +# Safe to re-run: skips members already present. +# Run from the k9-ecosystem repository root (post-extraction — see BOOTSTRAP.md). + +set -euo pipefail + +GH="git@github.com:hyperpolymath" + +# path repo +members=( + "members/implementations/k9-rs k9-rs" + "members/implementations/k9_ex k9_ex" + "members/implementations/k9_gleam k9_gleam" + "members/implementations/k9-deno k9-deno" + "members/implementations/k9-haskell k9-haskell" + "members/tooling/tree-sitter-k9 tree-sitter-k9" + "members/tooling/vscode-k9 vscode-k9" + "members/tooling/pandoc-k9 pandoc-k9" + "members/ci/k9-validate-action k9-validate-action" + "members/ci/k9-pre-commit k9-pre-commit" + "members/examples/k9-showcase k9-showcase" +) + +if [ ! -f .gitmodules ] || [ ! -d .git ]; then + echo "error: run from the k9-ecosystem repository root" >&2 + exit 1 +fi + +for entry in "${members[@]}"; do + # shellcheck disable=SC2086 + set -- $entry + path="$1"; repo="$2" + if [ -e "$path/.git" ] || git config --file .gitmodules --get "submodule.$path.url" >/dev/null 2>&1; then + echo "skip $path (already configured)" + continue + fi + echo "add $path -> $GH/$repo.git" + git submodule add "$GH/$repo.git" "$path" +done + +git submodule update --init --recursive +echo "done: $(git submodule status --recursive | wc -l) members wired" diff --git a/k9-ecosystem/spec/README.adoc b/k9-ecosystem/spec/README.adoc new file mode 100644 index 000000000..442c6ce6b --- /dev/null +++ b/k9-ecosystem/spec/README.adoc @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) += K9 Specification + +* link:SPEC.adoc[*SPEC.adoc*] — the canonical K9 format specification (v0.1 draft). + +== Status + +The format is at *v0.1 draft*. `k9-rs` is the normative reference until the spec +is ratified. This `spec/` directory is the single source of truth: changes to +the format land here first, then propagate to the implementations, gated by the +link:../conformance/[conformance suite]. + +== Change process + +1. Propose the change as a PR against `SPEC.adoc`. +2. Add or amend fixtures in `../conformance/fixtures/` demonstrating it. +3. Update each implementation submodule to satisfy the new fixtures. +4. Bump the spec `:revnumber:` when merged. diff --git a/k9-ecosystem/spec/SPEC.adoc b/k9-ecosystem/spec/SPEC.adoc new file mode 100644 index 000000000..5895a879f --- /dev/null +++ b/k9-ecosystem/spec/SPEC.adoc @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) += K9 Format Specification +:revnumber: 0.1.0-draft +:revdate: 2026-06-20 +:toc: left +:icons: font + +[IMPORTANT] +==== +*Status: DRAFT (v0.1).* This document is the working canonical specification for +the K9 format. Until it is ratified, `k9-rs` is the *normative reference +implementation*: where this text and `k9-rs` disagree, `k9-rs` wins and this +text is the bug. Open questions are marked `[OPEN]`. +==== + +== 1. Overview + +K9 is a self-validating configuration format for *software component +declarations*. A K9 document describes one component and the checks that prove +it is what it claims to be. + +Two surface syntaxes are defined: + +* *`.k9`* — a YAML-like, indentation-structured plain-text format, parsed + natively by every implementation. +* *`.k9.ncl`* — a https://nickel-lang.org[Nickel] document. Implementations + without a Nickel evaluator MUST detect this form and report it distinctly + (e.g. `k9-rs` returns `K9Error::NickelFormat`); evaluation is delegated to a + Nickel-aware tool such as `pandoc-k9`. + +Both surfaces denote the same abstract model (sections 3–6) and MUST produce +the same canonical projection (section 7). + +== 2. Document structure + +A document declares exactly one `component` with a name, a `version`, and the +sections below. Indentation is significant; two spaces per level is the +canonical style. + +[source,yaml] +---- +component: + version: + pedigree: { ... } # section 3 + security: # section 4 + recipe: { ... } # section 5 + contracts: [ ... ] # section 6 +---- + +`component` and `version` are REQUIRED. `pedigree`, `security`, `recipe`, and +`contracts` are each OPTIONAL but RECOMMENDED. + +== 3. Pedigree — provenance + +[cols="1,1,3", options="header"] +|=== +| Key | Required | Meaning +| `origin` | yes | Source URL of the component (HTTPS) +| `author` | yes | Responsible author or maintainer +| `license` | no | SPDX license identifier +| `hashes` | no | Supply-chain hashes (SHA-256+). `[OPEN]` exact key shape TBD +|=== + +MD5 and SHA-1 MUST NOT be used for `hashes`. + +== 4. SecurityLevel + +A single enumerated value describing the trust tier (shared with the K9 Nickel +component model): + +[cols="1,3", options="header"] +|=== +| Level | Meaning +| `kennel` | Most restricted — trusted, sandboxed, minimal surface +| `yard` | Intermediate — controlled exposure +| `hunt` | Least restricted — operates in the open +|=== + +`[OPEN]` Whether levels are case-insensitive on input is reference-defined; the +canonical projection (section 7) lower-cases them. + +== 5. Recipe — build / assembly + +[cols="1,1,3", options="header"] +|=== +| Key | Required | Meaning +| `tool` | yes | Build tool (e.g. `cargo`, `mix`, `gleam`, `deno`, `cabal`) +| `command` | yes | Arguments passed to the tool +|=== + +== 6. Contracts — runtime invariants + +`contracts` is an ordered list. Each entry: + +[cols="1,1,3", options="header"] +|=== +| Key | Required | Meaning +| `name` | yes | Stable identifier for the invariant +| `check` | yes | Shell command; exit code 0 = satisfied +| `severity` | yes | `error` \| `warn` \| `info` +|=== + +A K9 validator runs each `check`; a failing `error` contract fails validation, +`warn` and `info` are reported without failing. `[OPEN]` ordering/short-circuit +semantics across multiple failures to be pinned by the conformance suite. + +== 7. Canonical projection + +For cross-implementation conformance, a parsed document projects to canonical +JSON: object keys in declaration order, `security` lower-cased, `contracts` as a +JSON array, no implementation-specific fields. See +`../conformance/fixtures/` for worked examples. Every implementation MUST emit a +projection that is structurally equal to the fixture's `expected.json`. + +== 8. Versioning + +This spec is versioned independently of any implementation. Implementations +declare the spec version they target. Breaking changes bump the minor version +while in `0.x`. From d2300b855a5b81ae0844753ce14eae5ce7b8f19a Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 20 Jun 2026 18:19:43 +0000 Subject: [PATCH 2/3] Fix Dogfood Gate: make minimal K9 fixture a valid contract The conformance fixture was a YAML-like sketch (from the k9-rs README) that lacked the required `K9!` magic line and a `pedigree = { }` block, so the repo's `Validate K9 contracts` gate (k9-validate-action) errored. Rewrite it as a valid Nickel K9 contract modelled on the live corpus: `K9!` magic, SPDX header, five-layer pedigree (Snout/Scent/Leash/Gut/ Muscle) with a `'Kennel` trust level, plus `schema_version` and `security_level` to clear the validator's warnings. Rename to component.k9.ncl (it is Nickel), realign expected.json, and rewrite spec/SPEC.adoc to document the actually-enforced format rather than the earlier guess. The PR's other red checks (workflow security linter, trufflehog, deno @cadre/router duplicate) are pre-existing on main and unrelated to this diff. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_019i2e5ABGBKQmMdqk8puFWx --- k9-ecosystem/.machine_readable/6a2/STATE.a2ml | 5 +- k9-ecosystem/conformance/README.adoc | 13 +- .../conformance/fixtures/minimal/component.k9 | 14 -- .../fixtures/minimal/component.k9.ncl | 33 +++++ .../fixtures/minimal/expected.json | 34 ++--- k9-ecosystem/spec/SPEC.adoc | 137 ++++++++---------- 6 files changed, 124 insertions(+), 112 deletions(-) delete mode 100644 k9-ecosystem/conformance/fixtures/minimal/component.k9 create mode 100644 k9-ecosystem/conformance/fixtures/minimal/component.k9.ncl diff --git a/k9-ecosystem/.machine_readable/6a2/STATE.a2ml b/k9-ecosystem/.machine_readable/6a2/STATE.a2ml index f220b8896..fb4d349e4 100644 --- a/k9-ecosystem/.machine_readable/6a2/STATE.a2ml +++ b/k9-ecosystem/.machine_readable/6a2/STATE.a2ml @@ -14,9 +14,12 @@ completion-percentage = 20 phase = "hub scaffolded and staged inside developer-ecosystem; awaiting extraction to standalone repo and live submodule wiring" [session-2026-06-20-hub-scaffold] -summary = "Created the k9-ecosystem aggregator hub: README, .gitmodules (11 members grouped implementations/tooling/ci/examples), Justfile + scripts/init-submodules.sh, spec/SPEC.adoc (v0.1 draft) + spec/README, conformance/ suite with the 'minimal' fixture (component.k9 + expected.json), members/README, LICENSE, BOOTSTRAP.md, and 6a2 governance. Staged at developer-ecosystem/k9-ecosystem/ because the session scope did not permit creating a new top-level repo." +summary = "Created the k9-ecosystem aggregator hub: README, .gitmodules (11 members grouped implementations/tooling/ci/examples), Justfile + scripts/init-submodules.sh, spec/SPEC.adoc (v0.1 draft) + spec/README, conformance/ suite with the 'minimal' fixture (component.k9.ncl + expected.json), members/README, LICENSE, BOOTSTRAP.md, and 6a2 governance. Staged at developer-ecosystem/k9-ecosystem/ because the session scope did not permit creating a new top-level repo." files-added = 16 +[session-2026-06-20-dogfood-fix] +summary = "Fixed the Dogfood Gate 'Validate K9 contracts' failure on PR #120. The minimal fixture was a YAML-like sketch from the k9-rs README and lacked the K9! magic line and a 'pedigree = { }' block, so k9-validate-action errored. Rewrote it as a valid Nickel K9 contract (component.k9.ncl) modelled on the live corpus (K9! magic, SPDX, five-layer pedigree, 'Kennel leash), realigned expected.json and rewrote spec/SPEC.adoc to the actually-enforced format. The other three red checks on the PR (workflow security linter, trufflehog, deno @cadre/router duplicate) are pre-existing on main and untouched by this diff." + [next-actions] extract = "Promote to standalone hyperpolymath/k9-ecosystem (BOOTSTRAP.md option A)" wire = "Run scripts/init-submodules.sh to populate the 11 member submodules" diff --git a/k9-ecosystem/conformance/README.adoc b/k9-ecosystem/conformance/README.adoc index 73ce25c88..134a5b420 100644 --- a/k9-ecosystem/conformance/README.adoc +++ b/k9-ecosystem/conformance/README.adoc @@ -12,16 +12,17 @@ contract that keeps five independent parsers (`k9-rs`, `k9_ex`, `k9_gleam`, conformance/ └── fixtures/ └── / - ├── component.k9 # input (also /component.k9.ncl where relevant) - └── expected.json # canonical projection (see ../spec/SPEC.adoc §7) + ├── component.k9.ncl # input (Nickel surface; or component.k9 for the plain surface) + └── expected.json # canonical projection (see ../spec/SPEC.adoc §6) ---- == Contract -For each fixture, an implementation parses `component.k9` and emits the canonical -JSON projection. The result MUST be *structurally equal* to `expected.json` -(key order per declaration order, `security` lower-cased). Whitespace and -insignificant formatting are ignored. +For each fixture, an implementation produces the canonical JSON projection from +the input — evaluating the Nickel surface (`.k9.ncl`) or parsing the plain +surface (`.k9`) — and the result MUST be *structurally equal* to `expected.json` +(records in declaration order; Nickel enum tags rendered as bare strings, e.g. +`'Kennel` -> `"Kennel"`). Whitespace and insignificant formatting are ignored. == Wiring an implementation diff --git a/k9-ecosystem/conformance/fixtures/minimal/component.k9 b/k9-ecosystem/conformance/fixtures/minimal/component.k9 deleted file mode 100644 index 261a89b37..000000000 --- a/k9-ecosystem/conformance/fixtures/minimal/component.k9 +++ /dev/null @@ -1,14 +0,0 @@ -component: hello-svc - version: 0.1.0 - pedigree: - origin: https://github.com/hyperpolymath/hello-svc - author: Jonathan D.A. Jewell - license: MPL-2.0 - security: kennel - recipe: - tool: cargo - command: build --release - contracts: - - name: binary-exists - check: test -x target/release/hello-svc - severity: error diff --git a/k9-ecosystem/conformance/fixtures/minimal/component.k9.ncl b/k9-ecosystem/conformance/fixtures/minimal/component.k9.ncl new file mode 100644 index 000000000..2b5e8413f --- /dev/null +++ b/k9-ecosystem/conformance/fixtures/minimal/component.k9.ncl @@ -0,0 +1,33 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) +# minimal — the smallest valid K9 contract. Conformance fixture: every +# implementation must evaluate this and project it to expected.json. + +{ + pedigree = { + schema_version = "1.0.0", + security_level = 'Kennel, + + # L1 — The Snout: identity + metadata = { + name = "hello-svc", + version = "0.1.0", + breed = "application/vnd.k9+nickel", + magic_number = "K9!", + license = "MPL-2.0", + }, + + # L3 — The Leash: security posture + security = { + trust_level = 'Kennel, + allow_network = false, + allow_subprocess = false, + }, + + # L5 — The Muscle: recipes + recipes = { + build = "cargo build --release", + }, + }, +} diff --git a/k9-ecosystem/conformance/fixtures/minimal/expected.json b/k9-ecosystem/conformance/fixtures/minimal/expected.json index f1c01aef3..2592c4ff8 100644 --- a/k9-ecosystem/conformance/fixtures/minimal/expected.json +++ b/k9-ecosystem/conformance/fixtures/minimal/expected.json @@ -1,21 +1,21 @@ { - "component": "hello-svc", - "version": "0.1.0", "pedigree": { - "origin": "https://github.com/hyperpolymath/hello-svc", - "author": "Jonathan D.A. Jewell", - "license": "MPL-2.0" - }, - "security": "kennel", - "recipe": { - "tool": "cargo", - "command": "build --release" - }, - "contracts": [ - { - "name": "binary-exists", - "check": "test -x target/release/hello-svc", - "severity": "error" + "schema_version": "1.0.0", + "security_level": "Kennel", + "metadata": { + "name": "hello-svc", + "version": "0.1.0", + "breed": "application/vnd.k9+nickel", + "magic_number": "K9!", + "license": "MPL-2.0" + }, + "security": { + "trust_level": "Kennel", + "allow_network": false, + "allow_subprocess": false + }, + "recipes": { + "build": "cargo build --release" } - ] + } } diff --git a/k9-ecosystem/spec/SPEC.adoc b/k9-ecosystem/spec/SPEC.adoc index 5895a879f..c312030a2 100644 --- a/k9-ecosystem/spec/SPEC.adoc +++ b/k9-ecosystem/spec/SPEC.adoc @@ -8,113 +8,102 @@ [IMPORTANT] ==== -*Status: DRAFT (v0.1).* This document is the working canonical specification for -the K9 format. Until it is ratified, `k9-rs` is the *normative reference -implementation*: where this text and `k9-rs` disagree, `k9-rs` wins and this -text is the bug. Open questions are marked `[OPEN]`. +*Status: DRAFT (v0.1).* This text is reconstructed from the living K9 corpus +(the `*.k9.ncl` deployment components across the estate), the +`hyperpolymath/k9-validate-action` validator, and `k9-rs`. Where they disagree, +the *validator + `k9-rs` are normative* and this text is the bug. Open questions +are marked `[OPEN]`. ==== == 1. Overview K9 is a self-validating configuration format for *software component -declarations*. A K9 document describes one component and the checks that prove -it is what it claims to be. +declarations*. A K9 document describes one component — its identity, target, +security posture, self-checks, and recipes — so the file is both documentation +and an executable, authorisable contract. -Two surface syntaxes are defined: +Two surfaces are defined: -* *`.k9`* — a YAML-like, indentation-structured plain-text format, parsed - natively by every implementation. -* *`.k9.ncl`* — a https://nickel-lang.org[Nickel] document. Implementations - without a Nickel evaluator MUST detect this form and report it distinctly - (e.g. `k9-rs` returns `K9Error::NickelFormat`); evaluation is delegated to a - Nickel-aware tool such as `pandoc-k9`. +* *`.k9`* — plain-text surface. +* *`.k9.ncl`* — https://nickel-lang.org[Nickel] surface (the form used across the + estate today). Evaluation is delegated to a Nickel-aware tool (e.g. + `pandoc-k9`); parsers without an evaluator detect it distinctly (`k9-rs` + returns `K9Error::NickelFormat`). -Both surfaces denote the same abstract model (sections 3–6) and MUST produce -the same canonical projection (section 7). +== 2. File preamble (required) -== 2. Document structure - -A document declares exactly one `component` with a name, a `version`, and the -sections below. Indentation is significant; two spaces per level is the -canonical style. +[cols="1,3", options="header"] +|=== +| Rule | Requirement +| Magic | The *first non-empty line MUST be exactly* `K9!` +| Licence | An SPDX `License-Identifier` SHOULD appear within the first 10 lines +|=== -[source,yaml] ----- -component: - version: - pedigree: { ... } # section 3 - security: # section 4 - recipe: { ... } # section 5 - contracts: [ ... ] # section 6 ----- +The validator treats a missing magic line or a missing `pedigree` block as +*errors*; a missing SPDX line, `version`/`schema_version`, or security level as +*warnings*. -`component` and `version` are REQUIRED. `pedigree`, `security`, `recipe`, and -`contracts` are each OPTIONAL but RECOMMENDED. +== 3. The Pedigree -== 3. Pedigree — provenance +Every document MUST contain a `pedigree = { … }` record — the component's +self-description. Canonically it is organised in *five layers*: [cols="1,1,3", options="header"] |=== -| Key | Required | Meaning -| `origin` | yes | Source URL of the component (HTTPS) -| `author` | yes | Responsible author or maintainer -| `license` | no | SPDX license identifier -| `hashes` | no | Supply-chain hashes (SHA-256+). `[OPEN]` exact key shape TBD +| Layer | Key | Holds +| L1 — The Snout | `metadata` | Identity: `name`, `version`, `breed` (a MIME-like type, e.g. `application/vnd.k9+nickel`), `magic_number`, `license`, `description` +| L2 — The Scent | `target` | Environment: `os`, `requires_*`, resource minimums +| L3 — The Leash | `security` | Trust tier + capability flags (section 4) +| L4 — The Gut | `validation` | `checksum`, `pedigree_version`, authorisation state +| L5 — The Muscle | `recipes` | Named build/deploy/verify commands |=== -MD5 and SHA-1 MUST NOT be used for `hashes`. +The pedigree SHOULD carry a top-level `schema_version` (or `version`) and a +`security_level`/`leash` so it validates without warnings. `[OPEN]` whether +`security_level` is required at pedigree top level or may be inferred from +`security.trust_level`. -== 4. SecurityLevel +== 4. The Leash — trust levels -A single enumerated value describing the trust tier (shared with the K9 Nickel -component model): +`security.trust_level` (and the top-level `security_level`) take one of three +tiers, given as Nickel enum tags: [cols="1,3", options="header"] |=== | Level | Meaning -| `kennel` | Most restricted — trusted, sandboxed, minimal surface -| `yard` | Intermediate — controlled exposure -| `hunt` | Least restricted — operates in the open +| `'Kennel` | Most restricted — sandboxed, minimal capabilities, no side effects +| `'Yard` | Intermediate — controlled exposure +| `'Hunt` | Least restricted — may execute shell commands; REQUIRES explicit +authorisation (a signature / handshake) before execution |=== -`[OPEN]` Whether levels are case-insensitive on input is reference-defined; the -canonical projection (section 7) lower-cases them. - -== 5. Recipe — build / assembly - -[cols="1,1,3", options="header"] -|=== -| Key | Required | Meaning -| `tool` | yes | Build tool (e.g. `cargo`, `mix`, `gleam`, `deno`, `cabal`) -| `command` | yes | Arguments passed to the tool -|=== +Capability flags (`allow_network`, `allow_subprocess`, `allow_filesystem_write`, +…) further constrain the component. A `'Hunt` component MUST NOT run until +authorised (`validation.hunt_authorized = true` after signature verification). +Signatures are Ed25519. `[OPEN]` exact signature envelope. -== 6. Contracts — runtime invariants +== 5. Recipes -`contracts` is an ordered list. Each entry: +`recipes` is a record of named commands (e.g. `build`, `validate`, `deploy`, +`migrate`, `rollback`). Multi-line scripts use Nickel string blocks (`m%"…"%`). -[cols="1,1,3", options="header"] -|=== -| Key | Required | Meaning -| `name` | yes | Stable identifier for the invariant -| `check` | yes | Shell command; exit code 0 = satisfied -| `severity` | yes | `error` \| `warn` \| `info` -|=== +== 6. Surfaces and canonical projection -A K9 validator runs each `check`; a failing `error` contract fails validation, -`warn` and `info` are reported without failing. `[OPEN]` ordering/short-circuit -semantics across multiple failures to be pinned by the conformance suite. +For cross-implementation conformance, a document projects to canonical JSON: +the `pedigree` record (and any sibling top-level keys) as JSON, Nickel enum tags +rendered as their bare string (`'Kennel` → `"Kennel"`), records in declaration +order. A `.k9.ncl` document is evaluated first, then projected; a `.k9` document +is parsed natively. Both surfaces MUST yield the same projection. See +`../conformance/fixtures/` for worked examples. -== 7. Canonical projection +== 7. Conformance -For cross-implementation conformance, a parsed document projects to canonical -JSON: object keys in declaration order, `security` lower-cased, `contracts` as a -JSON array, no implementation-specific fields. See -`../conformance/fixtures/` for worked examples. Every implementation MUST emit a -projection that is structurally equal to the fixture's `expected.json`. +Every implementation MUST reproduce each fixture's `expected.json` from its +input. The fixtures are the executable form of this spec; an `[OPEN]` item is +closed by adding a fixture that pins the behaviour. == 8. Versioning -This spec is versioned independently of any implementation. Implementations +This spec is versioned independently of any implementation; implementations declare the spec version they target. Breaking changes bump the minor version while in `0.x`. From 93dbe4c463bca6a2512fefe082334b93d1099c56 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 22:46:20 +0000 Subject: [PATCH 3/3] docs(session-close): record 2026-06-21 K9 fan-out + TS-parser triage Durable close-out for the K9 satellite/hub fan-out and TS-exemption parser threads (the container is ephemeral). Adds SESSION-CLOSE-2026-06-21 and a STATE.a2ml session block: verified situation, the corrected 2-file consumer-pin surface, machine/human doc drift, and the docs/wiki gap analysis. No code or policy changes. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_019i2e5ABGBKQmMdqk8puFWx --- .machine_readable/6a2/STATE.a2ml | 7 +- ...-CLOSE-2026-06-21-k9-fanout-ts-parser.adoc | 237 ++++++++++++++++++ 2 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 SESSION-CLOSE-2026-06-21-k9-fanout-ts-parser.adoc diff --git a/.machine_readable/6a2/STATE.a2ml b/.machine_readable/6a2/STATE.a2ml index 63d3e60ae..50d70a551 100644 --- a/.machine_readable/6a2/STATE.a2ml +++ b/.machine_readable/6a2/STATE.a2ml @@ -5,7 +5,7 @@ [metadata] project = "developer-ecosystem" version = "0.1.0" -last-updated = "2026-06-05" +last-updated = "2026-06-21" status = "active" [project-context] @@ -13,6 +13,11 @@ name = "developer-ecosystem" completion-percentage = 55 phase = "license-stamps-flipped-to-MPL-2.0; bot_directives-rename-done; contractiles-currency-pass-2026-06-05" +[session-2026-06-21-k9-fanout-ts-parser-close] +summary = "Planned session-close triage of the K9 satellite/hub fan-out + TS-exemption parser threads. Verified: hyperpolymath/k9-ecosystem now EXISTS (created 2026-06-21) — the hub staged on 2026-06-20 was extracted to a standalone repo externally; hub-creation blocker resolved. k9-ecosystem + standards are NOT in session scope and list_repos/add_repo are unavailable, so neither the member-side fan-out nor the parser fix is executable from here. Fan-out has not reached the member repos (k9-rs, k9-validate-action: 0 open PRs). TS parser bug traced to hyperpolymath/standards governance-reusable.yml (per-repo ts-blocker.yml deleted/folded in); unverifiable from here. Consumer-pin surface corrected: only 2 files frozen at governance-reusable.yml@861b5e9 (developer-ecosystem, k9-validate-action); all other consumers pin @main and auto-receive the fix on merge." +files-changed = "2 (SESSION-CLOSE-2026-06-21 + this block)" +note = "Full triage: SESSION-CLOSE-2026-06-21-k9-fanout-ts-parser.adoc. Drift: approved-ts-exemptions here (2) is canonical vs CLAUDE.md table (3) — aggregate-library extracted by #119, so the CLAUDE.md row is stale. Wiki (docs/wikis/Home.md) is stale for K9. k9-rs STATE.a2ml still carries META-TEMPLATE residue. No autonomous policy/out-of-scope/destructive edits at close." + [session-2026-06-20-k9-ecosystem-scaffold] summary = "Scaffolded the k9-ecosystem aggregator hub under k9-ecosystem/ (staged for extraction to a standalone primary). Owns the K9 spec (spec/SPEC.adoc v0.1 draft) + conformance suite; aggregates 11 members (k9-rs/k9_ex/k9_gleam/k9-deno/k9-haskell + tree-sitter-k9/vscode-k9/pandoc-k9 + k9-validate-action/k9-pre-commit + k9-showcase) as git submodules via k9-ecosystem/.gitmodules. Added Justfile, scripts/init-submodules.sh, BOOTSTRAP.md, and 6a2 governance. Reasoning: members must stay standalone for their registries/toolchains; hub gives one spec + conformance source-of-truth. Staged here because a new top-level repo was outside session scope." files-changed = "18 (16 new under k9-ecosystem/, ECOSYSTEM.a2ml + STATE.a2ml indexed)" diff --git a/SESSION-CLOSE-2026-06-21-k9-fanout-ts-parser.adoc b/SESSION-CLOSE-2026-06-21-k9-fanout-ts-parser.adoc new file mode 100644 index 000000000..62f3f4e93 --- /dev/null +++ b/SESSION-CLOSE-2026-06-21-k9-fanout-ts-parser.adoc @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) += SESSION-CLOSE 2026-06-21 — K9 satellite/hub fan-out + TS-exemption parser +:toc: +:protocol: continuity / planned-session-close +:session-id: 2026-06-21-k9-fanout-ts-parser + +== 1. Goal / scope + +Three intertwined threads on the K9 ecosystem: + +* the *satellite/hub fan-out* — extract a coordination hub, flip `k9-rs` + from source-of-truth to satellite, wire cross-repo drift enforcement and + tree-sitter/vscode generation across the 11 K9 member repos; +* the *TS-exemption parser bug* — the shared governance check flags the + approved `rrt.ts` exemption; and +* an explanatory thread on *why `rrt.ts` is TypeScript, not AffineScript*. + +== 2. Verified situation at close (2026-06-21) + +* *`hyperpolymath/k9-ecosystem` now EXISTS* (created 2026-06-21 01:16Z, + updated 14:16Z; public; Nickel; charter = "conformance, membership, + cross-repo drift enforcement; pins spec + governance from + hyperpolymath/standards"). The hub-creation blocker is *resolved*. +** The staged copy still lives here on `claude/nice-hopper-fzl2bl` at + `f911392b` ("Add k9-ecosystem aggregator hub (staged for extraction)") + plus `d2300b85` (dogfood-gate fix). Whether the live repo was populated + *from* this staging is unverified (k9-ecosystem is out of scope). +* *`k9-ecosystem` and `standards` are NOT in this session's scope* and are + not checked out. `list_repos`/`add_repo` tooling is *unavailable*, so + neither can be added from here. +* *Fan-out has not reached the member repos*: `k9-rs` and + `k9-validate-action` have 0 open PRs; `tree-sitter-k9` has only a stale + Dependabot bump. No satellite-anchor PRs, no `k9-rs` flip, no drift job, + no generation wiring. +* *TS parser fix not landed/observable*: the only repo where `rrt.ts` + trips the check is `developer-ecosystem`, pinned pre-fix. +* *All 12 in-scope repos clean* (0 uncommitted / 0 unpushed). + `developer-ecosystem` was on `claude/ci-hygiene`; moved to + `claude/nice-hopper-fzl2bl` for this close record. + +== 3. Parser bug — root location (for a standards-scoped fix) + +* Governance is centralized: every repo's `.github/workflows/governance.yml` + is a thin wrapper for + `hyperpolymath/standards/.github/workflows/governance-reusable.yml`. The + per-repo `ts-blocker.yml` was deleted and folded in. +* The TS-exemption parser lives in `standards` (`governance-reusable.yml` + plus its script). *Prime hypothesis (UNCONFIRMED — standards out of + scope):* exemption path cells are read from the `CLAUDE.md` markdown + table without stripping the surrounding backticks, so the literal + `+`…/rrt.ts`+` never equals the on-disk path; exact-path exemptions + silently never match. A complete hand-off brief for a standards-scoped + agent was produced this session (see §5.3 E-1). + +== 4. Consumer-pin surface (corrected) + +An earlier in-session claim ("bump pins across developer-ecosystem + the +k9 repos") was *wrong*. Verified by grep across all checkouts: + +* Only *2* files pin `governance-reusable.yml@861b5e9` (frozen): + `developer-ecosystem/.github/workflows/governance.yml` and + `k9-validate-action/.github/workflows/governance.yml`. These need a + manual SHA bump to receive the fix. +* All other consumers (the other 10 K9 repos + ~115 developer-ecosystem + sub-projects) pin `@main`, so they auto-receive the fix on merge. +* Aside (parked): the 2 frozen pins are the policy-*compliant* ones; the + `@main` majority is itself unpinned drift vs the "SHA-pinned + dependencies" rule — separate cleanup. + +== 5. Triage (response to the close-out request) + +=== 5.1 Completed in this quick run + +* This `SESSION-CLOSE` record + a `STATE.a2ml` session block — the durable + handoff (the container is ephemeral; nothing else here was committable). +* Tracking issue filed for the member-side fan-out (see E-3) on `k9-rs` + (clean tracker, in-scope). + +=== 5.2 Discard + +* The `.governance-allowlist` workaround — superseded by the decision to + fix the parser at source. Do not pursue. +* Re-litigating settled decisions (hub-first extraction; fan-out after + developer-ecosystem#124) — both resolved. + +=== 5.3 Allocate to issues + +* *E-1 — `standards` (CANNOT file from here, out of scope):* fix the + TS-exemption parser (strip backticks/whitespace on the path cell) + + regression test covering all 3 exemptions and a near-miss; record the + new `governance-reusable.yml` SHA. Hand-off brief ready. +* *E-2 — `developer-ecosystem` + `k9-validate-action`:* after E-1 merges, + bump the 2 frozen `governance-reusable.yml@861b5e9` pins to the fixed + SHA. Small, in-scope, ready. +* *E-3 — `k9-rs` / `k9-ecosystem`:* member-side fan-out — satellite + anchor, flip `k9-rs` source→satellite, drift job on `k9-validate-action`, + tree-sitter + vscode generation. Filed on `k9-rs`; true home is + `k9-ecosystem` when scoped. +* *E-4 — `developer-ecosystem`:* reconcile the exemption-list drift (§6.1). +* *E-5 — `developer-ecosystem`:* remove the staged `k9-ecosystem` hub copy + once the live repo is verified populated (reversible-move discipline). + +=== 5.4 Sketch areas + doc entries (recommended, NOT scaffolded blind) + +* In *k9-ecosystem* (when scoped): `membership.ncl` (member registry), + `drift/` (cross-repo drift rules), `conformance/` (K9 contract + conformance). These define the anchor schema members import — sketching + them in members now would guess the schema. Hold until the hub is scoped. +* In *k9-rs*: a `docs/satellite/` stub describing the satellite + relationship + anchor import — safe to add once the hub schema exists. +* Machine docs: each member's `.machine_readable/6a2/ECOSYSTEM.a2ml` should + gain `satellite-of = "k9-ecosystem"` as part of the flip. + +=== 5.5 Cleanup + +* *Branches:* `developer-ecosystem` carries `claude/ci-hygiene` + (trufflehog drop, aggregate-library extraction) and + `claude/nice-hopper-fzl2bl` (k9-ecosystem staging, dogfood gate). + Reconcile/merge and prune once their PRs land. NOTE: an explicit + `git fetch origin claude/nice-hopper-fzl2bl` returned "couldn't find + remote ref" — the remote branch may have been deleted post-merge; verify + before pruning the local branch. +* *Docs:* `k9-rs/.machine_readable/6a2/STATE.a2ml` still carries + META-TEMPLATE identity (`{{PLACEHOLDER}}`, "the TEMPLATE's evolution") — + de-template to k9-rs's real identity (Rust impl of the K9 format), + matching the `docs(state): replace rsr-template-repo residue` campaign in + sibling repos. +* *Config / contractiles 6a2:* `developer-ecosystem` contractile *tridents* + (`k9.ncl` + `manifest.a2ml`) remain deferred for all 6 verbs + (`trident-coverage = none`); `lust` absent. Pre-existing estate debt — + leave unless prioritized. +* *Policy:* drop or relocate the now-stale + `aggregate-library/src/test-runner.ts` row in `.claude/CLAUDE.md` + (extracted by #119). Left for the user — it is policy. + +== 6. Drift / findings (machine ↔ human doc mismatches) + +. *TS exemptions:* `.claude/CLAUDE.md` table = 3 rows; + `.machine_readable/6a2/STATE.a2ml` `approved-ts-exemptions` = 2 (omits + aggregate-library). `#119` extracted aggregate-library to its own repo, + so its path is stale in CLAUDE.md → *STATE is canonical; CLAUDE.md should + drop/relocate the row.* +. *Wiki stale for K9:* `docs/wikis/Home.md` describes developer-ecosystem + as a 30+ satellite hub (Git Tools / Repo Mgmt / Scaffolding / Developer + UX). It does *not* mention the K9 ecosystem, the `k9-ecosystem` hub, the + satellite/hub model, or the governance-reusable consolidation. +. *k9-rs identity residue:* its `STATE.a2ml` is still the template META + file rather than k9-rs's own state. + +== 7. Wiki & documentation assessment (dev / maintainer / user) + +Answer to "is the wiki up to date with the fullest representation, split by +audience": *partially — strong scaffolding, but not yet a complete +pedagogical body, and stale for K9.* + +*What exists and is good:* audience-split quickstarts already present +(`QUICKSTART-DEV/MAINTAINER/USER.adoc`) in both repos; an in-repo *signpost* +wiki (`docs/wikis/Home.md`) that correctly defers to canonical `docs/`; LLM +warmups (`llm-warmup-dev.md`, `llm-warmup-user.md`); deep governance / audit +/ decision scaffolding under `k9-rs/docs/`. + +*Gaps for "beyond setup / really engage":* + +* *End users:* no conceptual "what is a K9 self-validating component / + contractile, and why" narrative; quickstarts are run-throughs, not mental + models. No worked end-to-end example of authoring + validating a K9 + contract. +* *Developers:* no "how the pieces fit" map + (`k9-rs` ↔ `k9-ecosystem` ↔ `standards` ↔ tree-sitter/vscode); the + governance-reusable wrapper model is undocumented; contributing docs are + generic RSR, not K9-specific. +* *Maintainers:* the membership + drift-enforcement model (the entire point + of `k9-ecosystem`) is undocumented; the pin policy (`@main` vs SHA) is + undocumented; cross-member release/sync is undocumented. +* *Currency:* `Home.md` predates the K9 hub entirely. + +*Recommended structure* (lives in `docs/`, signposted from the wiki): + +* `docs/concepts/` (users): what K9 is, contractiles, the self-validation + model, a worked example. +* `docs/developer/` (devs): architecture map, the satellite/hub model, the + governance-reusable wrapper, the generation pipeline (tree-sitter→vscode), + the local dev loop. +* `docs/governance/` (maintainers): membership + drift enforcement, pin + policy, cross-member release/sync, the exemption process. + +This is a documentation *epic*, not a quick-run item — recommend an issue + +staged authoring. + +== 8. Blockers + +* *Scope:* `k9-ecosystem` and `standards` not in session scope; not + checked out. +* *Tooling:* `list_repos`/`add_repo` unavailable → cannot self-add repos; + `send_later` unavailable → no self-scheduled re-check. +* *Net:* nothing further on the fan-out or parser fix is executable from + this session. + +== 9. Decision log + +* Hub extracted first (`k9-ecosystem`) — done externally; live repo exists. +* Parser fixed at source in `standards`, not via a per-repo allowlist + workaround. +* Consumer-side delivery for the parser fix = *2 pin bumps only* + (corrected from "all k9 repos"). +* aggregate-library exemption is stale post-#119; STATE is canonical, + CLAUDE.md to be reconciled. +* No autonomous edits to policy (`CLAUDE.md`), to out-of-scope repos, or + destructive branch ops at close. + +== 10. Recommended next protocol + +. Scope `k9-ecosystem` → run the member-side fan-out (E-3), then sketch the + hub schema (§5.4). +. Scope `standards` (or run the hand-off brief elsewhere) → fix the parser + (E-1) → bump the 2 pins (E-2). +. Reconcile the exemption drift (E-4) + de-template `k9-rs` STATE. +. Schedule the documentation epic (§7). + +== 11. User invitations + +* Add `k9-ecosystem` and/or `standards` to this session's scope to unblock + the above. +* Confirm direction on the aggregate-library exemption (drop vs relocate to + the new repo's policy). +* Approve the docs epic + audience structure in §7, or adjust. + +== 12. Post-condition check + +|=== +| Post-condition | State +| Durable session record written (this file) + STATE.a2ml block | ✅ +| No work lost to the ephemeral container | ✅ +| In-scope repos clean; developer-ecosystem on designated branch | ✅ +| Fan-out / parser fix blocked on scope, fully documented for handoff | ✅ +|===