Skip to content
Closed
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
17 changes: 3 additions & 14 deletions .machine_readable/contractiles/INDEX.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

---
id = "contractiles-registry"
version = "2.0.0" # 2.0.0 (2026-04-18): all 6 verbs on trident shape; verb set complete.
version = "2.1.0" # 2.1.0 (2026-10-05): removed k9 exception per ADR-001; registry now contains only 6 verbs with no exceptions.
spec = "docs/CONTRACTILE-SPEC.adoc"
last_updated = "2026-04-18"
last_updated = "2026-10-05"
base_schema = ".machine_readable/contractiles/_base.ncl"
meta_schema_status = "pending — see CONTRACTILE-SPEC §validator-meta-schema"

Expand Down Expand Up @@ -82,18 +82,7 @@ gating = "non-gating (continue)"
cardinality = "one per repo"
notes = "First trident instance in the estate (2026-04-18). Reports progress toward committed next-actions AND lists horizon aspirations. Absorbed the deprecated `lust` verb 2026-04-18. Never blocks. Remaining 5 verbs still on file_pair shape until tridents are built."

[[verbs]]
name = "k9"
semantics = "trust-tier templates (EXCEPTION to one-verbfile rule)"
file_pair = [
"k9/template-hunt.k9.ncl",
"k9/template-kennel.k9.ncl",
"k9/template-yard.k9.ncl",
]
status = "exception"
gating = "not applicable"
notes = "k9 is service-automation meta-infrastructure, not a verb contractile. Three trust-tier templates (Kennel/Yard/Hunt). Does not have a Verbfile.a2ml. See CONTRACTILE-SPEC §k9-exception."

# [[verbs]] k9 REMOVED 2026-10-05 — relocated by ADR-001 to .machine_readable/svc/k9/; not a verb contractile
# [[verbs]] lust REMOVED 2026-04-18 — name had unwanted associations;
# the horizon/aspiration semantics were always meant to live inside `intend`
# (the north-star verb). The [[wishes]] schema was absorbed into
Expand Down
60 changes: 11 additions & 49 deletions .machine_readable/contractiles/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ PascalCase in the A2ML (e.g. `intend.ncl` + `Intentfile.a2ml`,
All verb runners import `_base.ncl` (shared pedigree + run-defaults + probe-schema).
See `docs/CONTRACTILE-SPEC.adoc` for the normative specification.

== Verbs (6 + k9 exception)
== Verbs (6)

[cols="1,2,3", options="header"]
|===
Expand Down Expand Up @@ -60,55 +60,18 @@ associations). Its [[wishes]] semantics live inside `intend/Intentfile.a2ml`
as a second section alongside [[intents]]. Any `lust/` dir encountered in
an estate repo is drift and should be removed.

== k9 — Service-Automation Layer (EXCEPTION to the one-verbfile rule)
[[k9-relocation]]
== k9 Service-Automation Layer (Relocated)

IMPORTANT: `k9/` is **not a contractile verb** and does NOT follow the
`<Verb>file.a2ml` + `<verb>.ncl` pattern. This is an intentional, documented
exception. Do not apply the naming rule to k9.
IMPORTANT: k9 is **not a contractile verb**. As of ADR-001 (2026-04-18),
k9 has been relocated from this directory to `.machine_readable/svc/k9/`
estate-wide. The `k9/` directory entry in this location is a **signpost only**.

=== Why k9 is different

The seven verb contractiles each declare *one concern per repo* in a single
xfile. k9 is not a concern; it is the *graded automation surface* that
enforces or validates concern declarations. k9 provides three trust-tier
*templates* that repos copy and instantiate:

[cols="1,1,3", options="header"]
|===
| File | Trust tier | Description

| `k9/template-kennel.k9.ncl`
| Kennel
| Pure data. No subprocess, no filesystem write, no network. Safe for
metadata and declarative settings.

| `k9/template-yard.k9.ncl`
| Yard
| Nickel evaluation with contracts and validation. No side effects.

| `k9/template-hunt.k9.ncl`
| Hunt
| Full execution surface. Must declare side effects, support dry-run, and
be signed before the estate treats it as trustworthy automation.
|===

=== Why the naming rule does not apply

The one-verb-one-Verbfile rule exists to enforce clean concern separation.
k9 is meta-infrastructure: it does not have a `K9file.a2ml` because it is
not a declarative xfile — it is a template set that instantiates into
specific repos. Applying the rule would produce a meaningless `K9file.a2ml`
with nothing to declare.

=== Audit rule

If a repo claims `k9` enforcement, each k9 component in that repo MUST
declare a `paired_xfile` pointing to a specific contractile xfile (e.g.
`../must/Mustfile.a2ml`). Floating k9 components with no paired xfile are
non-conformant.

See `k9/README.adoc` for the full k9 security model and usage instructions.
See `docs/CONTRACTILE-SPEC.adoc §k9-exception` for the normative statement.
k9 provides three trust-tier templates (Kennel, Yard, Hunt) that repos copy
and instantiate. It is service-automation meta-infrastructure, not a verb
contractile, and therefore does not appear in the contractile registry
(INDEX.a2ml). See ADR-001 for the relocation rationale and
`.machine_readable/svc/k9/README.adoc` for the full k9 security model.

== Fill-In Instructions

Expand All @@ -125,7 +88,6 @@ When copying this set into a new repo:
6. `Bustfile` — declare real breakage / expiry / hard-stop conditions.
7. `Intentfile` — list tracked next-actions with observable probes
([[intents]] section) AND horizon aspirations ([[wishes]] section).
8. Pair any `k9/*.k9.ncl` with a specific contractile via `paired_xfile`.

== Intentfile: Commitments vs Aspirations — Two Sections, One File

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