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
8 changes: 4 additions & 4 deletions .machine_readable/REGISTRY.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ name = "K9 Self-Validating Components"
stream = "foundation"
home = "1-formats/k9/"
canonical_doc = "1-formats/k9/README.adoc"
source_hash = "sha256:6115d0242f7ab14372d48ecd97452d7737ddc878dec8a00ffe24bc1d9da7dd03"
source_hash = "sha256:d10e71f64586a5c6faac5833d6a52225d22042170e63df0ad2076ee610be8831"
route = "the K9 specification, security analysis and adoption guidance (implementations live in hyperpolymath/k9-ecosystem)"

[[spec]]
Expand All @@ -54,7 +54,7 @@ name = "Contractiles (Must/Trust/Dust/Intend)"
stream = "foundation"
home = "1-formats/contractiles/"
canonical_doc = "1-formats/contractiles/README.adoc"
source_hash = "sha256:b3bedbed23c8c79a9a94b059e09ff5865f8bbf198a82d90384290e8f501504d5"
source_hash = "sha256:d82e0007277aeea794555bd2f0d2b83e8235def2771ff0d9c8dc23f9fdfc300e"
route = "policy-enforcement primitives the K9 layer is built from"

[[spec]]
Expand Down Expand Up @@ -153,7 +153,7 @@ name = "AXEL Protocol"
stream = "protocol"
home = "2-protocols/axel/"
canonical_doc = "2-protocols/axel/README.adoc"
source_hash = "sha256:dbfe6d40af030e4dd23575d7f01dc86d1557b1d395534af73aa1ab0ac133c59c"
source_hash = "sha256:c67b62c6dcbb730664318eb235b25c687493bf74cabbc20af5a71c0d7849acea"
route = "age-gating + explicit-content enforcement"

[[spec]]
Expand Down Expand Up @@ -216,7 +216,7 @@ name = "Session Management Standards"
stream = "governance"
home = "3-practice/session-management-standards/"
canonical_doc = "3-practice/session-management-standards/README.adoc"
source_hash = "sha256:9e3e5f7bc1469e0736359e3e85cba5311b8ed87056d137d86a98e81c4e3c4b5a"
source_hash = "sha256:beea95b19ff9565abf30d34b758bfb669c5140fc5eef5046a494eafe20a7a91f"
route = "continuity / verify / handover protocols"

[[spec]]
Expand Down
32 changes: 16 additions & 16 deletions .machine_readable/k9-contract-debt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@
# One repo-relative path per line. '#' comments and blanks ignored.
# Baseline 2026-10-03, produced by:
# 1-formats/k9/tools/k9-validate.sh --layer L1 --json <every tracked *.k9*>
# Count: 5 (25 non-conforming at the 2026-10-03 baseline; 20 entries removed
# since, and every one of the 20 now conforms on its own terms).
#
# Removed in two batches:
# * 8 β€” the six contractile components and the two axel config files β€” dropped
# when the K9! sentinel alone left them failing (a sentinel is not a
# pedigree). M1/#A gave the six a resolvable pedigree, a component_type and
# the Β§8.4 grant; M4/#D moved the axel pair's leash under
# pedigree.security. Both sets conform as of 2026-10-05.
# * 12 β€” the session-management PROTOCOL.k9 stubs, renamed to PROTOCOL.yaml
# by M2/#B: plain YAML off the reserved suffix, so they are no longer K9
# files at all.
.machine_readable/svc/k9/examples/setup-repo.k9.ncl
.machine_readable/svc/k9/template-hunt.k9.ncl
.machine_readable/svc/k9/template-kennel.k9.ncl
.machine_readable/svc/k9/template-yard.k9.ncl
# Count: 13 (12 removed: 6 contractiles + 2 axel config files with K9! sentinel
# added; 3 templates renamed off the reserved suffix as *.k9.ncl.in β€” a template
# is not a component and is never loaded; setup-repo.k9.ncl granted, described
# and given a signature block. MIGRATION-1058 M3 / standards#1058 #C)
3-practice/session-management-standards/continuity/checkpoint-before-major-change/PROTOCOL.k9
3-practice/session-management-standards/continuity/emergency-termination/PROTOCOL.k9
3-practice/session-management-standards/continuity/planned-session-close/PROTOCOL.k9
3-practice/session-management-standards/continuity/recovery-operation/PROTOCOL.k9
3-practice/session-management-standards/continuity/repo-intake/PROTOCOL.k9
3-practice/session-management-standards/handover/collaborative-transfer/PROTOCOL.k9
3-practice/session-management-standards/handover/full-transfer/PROTOCOL.k9
3-practice/session-management-standards/handover/human-transfer/PROTOCOL.k9
3-practice/session-management-standards/handover/model-transfer/PROTOCOL.k9
3-practice/session-management-standards/verify/maintenance-sweep/PROTOCOL.k9
3-practice/session-management-standards/verify/release-audit/PROTOCOL.k9
3-practice/session-management-standards/verify/substantial-completion/PROTOCOL.k9
rhodium-standard-repositories/rsr-compliance-checklist.k9.ncl
28 changes: 21 additions & 7 deletions .machine_readable/svc/k9/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,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/svc/k9/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/svc/k9/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/svc/k9/examples/setup-repo.k9.ncl scripts/setup.k9.ncl
----

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

== Template Files

Use these as starting points for your own K9 components:
Use these as starting points for your own K9 components. They are
`.k9.ncl.in` files on purpose: a *template* is not a component. It is never
loaded, it carries unfilled `TODO` placeholders, and a placeholder that passes
a presence check is indistinguishable from a field that was never written
(K9-S003/K9-S005, MIGRATION-1058 M3). Withholding the reserved `.k9.ncl`
suffix means no host leashes a template and no gate counts its placeholders as
a declaration. Copy one to a real component name, fill in every `TODO`, and it
becomes an ordinary K9 component:

- `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

[source,bash]
----
cp .machine_readable/svc/k9/template-kennel.k9.ncl.in config/metadata.k9.ncl
# ... fill in every TODO, then validate:
1-formats/k9/tools/k9-validate.sh config/metadata.k9.ncl
----

== Dependencies

Expand Down
38 changes: 38 additions & 0 deletions .machine_readable/svc/k9/examples/setup-repo.k9.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ K9!
allow_filesystem_write = true,
allow_subprocess = true,
signature_required = true,
# Β§8.3/Β§8.4 β€” the grant. Each flag above is a REQUEST for a capability,
# and a request the grant does not cover is a contradiction inside the
# pedigree, not a preference (K9-S007). Without this list the component
# asked for the network, the filesystem and subprocesses while granting
# itself nothing, so "default-deny" denied nothing. Keep it in step with
# the recipes below.
capabilities = [
"net.fetch", # add-license fetches the licence text over HTTPS
"fs.write", # create-structure and create-checkpoint-files write
"process.spawn", # git, just, nickel, curl and mkdir are child processes
],
},
metadata = {
name = "setup-repo",
Expand All @@ -28,6 +39,33 @@ K9!
"Review Just recipes before execution",
"Use dry-run mode first: ./must --dry-run run setup-repo.k9.ncl",
],
# Β§6.5/K9-S010 β€” mandatory at 'Hunt and may not be a placeholder: Β§9
# requires a dry_run precondition, i.e. a plan that was produced AND
# reviewed, and a reviewer cannot review a plan for a component that
# requests network, filesystem and subprocess access while describing none
# of it. Each entry names the recipe that causes it.
side_effects = [
"creates src/, docs/, tests/, scripts/, .github/workflows/ and .machine_readable/contractiles/k9/ under the current directory (create-structure)",
"writes STATE.a2ml, ECOSYSTEM.a2ml and META.a2ml in the repository root, overwriting any existing copies (create-checkpoint-files)",
"writes README.adoc in the repository root when add-readme is selected (add-readme)",
"downloads the licence text from https://raw.githubusercontent.com/hyperpolymath/pmpl/main/LICENSE to ./LICENSE when add-license is selected (add-license)",
"runs git init and sets repository-local user.name and user.email (init-git)",
"spawns git, just, nickel, curl, mkdir and the shell builtins as child processes (every recipe)",
"deletes STATE.a2ml, ECOSYSTEM.a2ml and META.a2ml from the current directory, after a 5-second pause, when clean is selected (clean)",
],
# Β§10.1/K9-S009 β€” a 'Hunt component MUST carry a signature block. This one
# is what an example can honestly carry: a CLAIM that a signature exists,
# not a verified signature. With no external verifier the verdict is
# 'Present_Unverified (Β§10.2), and 'Present_Unverified is not the Hunt
# `signature` precondition (Β§10.4) β€” so this file is conforming, and it is
# still NOT authorised to run. Replace the block before use:
# ./must sign setup-repo.k9.ncl
signature = {
algorithm = "Ed25519",
key_id = "setup-repo-example",
payload_hash = "sha256:0000000000000000000000000000000000000000000000000000000000000000",
signature = "EXAMPLE-NOT-A-REAL-SIGNATURE",
},
},

# Configuration with contracts
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
K9!
# SPDX-License-Identifier: MPL-2.0
#
# .k9.ncl.in β€” a TEMPLATE, not a component (standards#1058, MIGRATION-1058 M3).
# The `.in` suffix is deliberate: a template is never loaded, so it must not
# claim the reserved `.k9.ncl` component suffix. Nothing tries to leash it and
# no gate mistakes its TODOs for a component's declaration. The placeholders
# are the point. Instantiate them, and the copy becomes a real component:
#
# cp template-hunt.k9.ncl.in my-task.k9.ncl # then fill in every TODO
#
# The `K9!` line is kept so the INSTANTIATED file carries the envelope, which
# Β§11.2 makes the thing that makes a leash enforceable at all.
#
# K9 Hunt-level template: Full execution with Just recipes
# Security Level: Hunt (full system access)
# ⚠️ SIGNATURE REQUIRED - Review carefully before use
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
K9!
# SPDX-License-Identifier: MPL-2.0
#
# .k9.ncl.in β€” a TEMPLATE, not a component (standards#1058, MIGRATION-1058 M3).
# The `.in` suffix is deliberate: a template is never loaded, so it must not
# claim the reserved `.k9.ncl` component suffix. Nothing tries to leash it and
# no gate mistakes its TODOs for a component's declaration. The placeholders
# are the point. Instantiate them, and the copy becomes a real component:
#
# cp template-kennel.k9.ncl.in my-task.k9.ncl # then fill in every TODO
#
# The `K9!` line is kept so the INSTANTIATED file carries the envelope, which
# Β§11.2 makes the thing that makes a leash enforceable at all.
#
# K9 Kennel-level template: Pure data configuration
# Security Level: Kennel (data-only, no execution)
# No signature required - safe for any use
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
K9!
# SPDX-License-Identifier: MPL-2.0
#
# .k9.ncl.in β€” a TEMPLATE, not a component (standards#1058, MIGRATION-1058 M3).
# The `.in` suffix is deliberate: a template is never loaded, so it must not
# claim the reserved `.k9.ncl` component suffix. Nothing tries to leash it and
# no gate mistakes its TODOs for a component's declaration. The placeholders
# are the point. Instantiate them, and the copy becomes a real component:
#
# cp template-yard.k9.ncl.in my-task.k9.ncl # then fill in every TODO
#
# The `K9!` line is kept so the INSTANTIATED file carries the envelope, which
# Β§11.2 makes the thing that makes a leash enforceable at all.
#
# K9 Yard-level template: Configuration with validation
# Security Level: Yard (Nickel evaluation with contracts)
# Signature recommended but not required
Expand Down
17 changes: 14 additions & 3 deletions 1-formats/contractiles/CANONICAL-TEMPLATES.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -159,21 +159,32 @@ not be presented elsewhere as already-shipped work.
| Tier | Canonical Template | Capability | Audit Expectation

| Kennel
| `1-formats/contractiles/k9/template-kennel.k9.ncl`
| `.machine_readable/svc/k9/template-kennel.k9.ncl.in`
| Pure data. No subprocesses, no filesystem writes, no network access.
| Safe for metadata, declarative settings, and other read-only structured outputs.

| Yard
| `1-formats/contractiles/k9/template-yard.k9.ncl`
| `.machine_readable/svc/k9/template-yard.k9.ncl.in`
| Nickel evaluation with contracts and validation, but no side effects.
| Use for validated configuration, schemas, and policies that need machine-checked structure.

| Hunt
| `1-formats/contractiles/k9/template-hunt.k9.ncl`
| `.machine_readable/svc/k9/template-hunt.k9.ncl.in`
| Full execution surface with recipes and side effects.
| Must declare side effects clearly, support dry-run review, and be signed before the estate treats it as trustworthy automation.
|===

The `.in` suffix is the ruling of MIGRATION-1058 M3 (standards#1058): a
*template* is not a component. It is never loaded, its `TODO` fields are the
point, and a placeholder that satisfies a presence check is indistinguishable
from a field that was never written (K9-CONTRACT-SPEC Β§6.2). Keeping the
reserved `.k9.ncl` suffix on a file nothing loads is what made three templates
count as components with placeholder pedigrees. Instantiate a template by
copying it to `<name>.k9.ncl` and filling every `TODO`; the copy is then a real
component and must satisfy the K9 contract in full β€” including the capability
grant that pays for each security flag (Β§8.4) and, at `'Hunt`, a non-empty
`side_effects` list and a `signature` block (Β§6.5, Β§10.1).

== 4. How Contractiles And K9 Fit Together

The plain contractiles describe what must be true, what is trusted, how to
Expand Down
4 changes: 3 additions & 1 deletion 1-formats/k9/spec/K9-CONTRACT-SPEC.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,9 @@ it, `.machine_readable/svc/k9/template-hunt.k9.ncl` satisfied every field
check in the estate while declaring its own type as
`"TODO: describe component type"`. A field that exists and says nothing is
indistinguishable from a field that was never written, except that it passes
the gate.
the gate. (That file was a *template* claiming a component's suffix; it is now
`.machine_readable/svc/k9/template-hunt.k9.ncl.in` β€” a template is not a
component and is never loaded. MIGRATION-1058 M3, standards#1058.)

A contractile component MUST set `component_type` to `contractile:<verb>`
(for example `contractile:must`). This is the disambiguation promised in the
Expand Down
11 changes: 11 additions & 0 deletions 1-formats/k9/spec/MIGRATION-1058.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,17 @@ the clearest single illustration of why Β§8.4 exists. Fix it as a component:
grant `net.fetch`, `fs.write`, `process.spawn`, add a `signature` block, and
describe what it actually does.

*Resolution (standards#C, 2026-10-05):* done as ruled. The three templates are
now `template-{hunt,kennel,yard}.k9.ncl.in`: the `.in` suffix keeps them out of
every scope that reads `*.k9.ncl` as a loadable component, and the `TODO`
placeholders stay, because they are the point of a template. `setup-repo.k9.ncl`
kept the component suffix and was fixed as one: its grant pays for all three
flags (`net.fetch`, `fs.write`, `process.spawn`, Β§8.4), its `side_effects` name
what the recipes do (Β§6.5), and its `signature` block states in the file that
presence is not verification (Β§10.2). The four ledger entries are removed β€”
count 17 β†’ 13. L1 is clean for the example; L2/L3 remain CI-side, as for the
rest of this plan.

=== M4 β€” Two Axel config files declare a leash nothing reads

*Files:* `2-protocols/axel/config/{ci,metadata}.k9.ncl`
Expand Down
Loading
Loading