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
18 changes: 15 additions & 3 deletions .github/workflows/k9-contractile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,19 +200,31 @@ jobs:
fi
exit $rc

- name: K9 corpus conformance (ratcheted)
- name: K9 corpus conformance (ratcheted, L2)
env:
# MIGRATION-1058 M7's first step. The hook's own default stays L1: a
# pre-commit hook that fails because a laptop lacks a toolchain
# teaches people to pass --no-verify, which is how a gate gets
# deleted. CI has the pinned binary, so here the corpus is checked at
# L2 as well. The six contractiles and the two axel config files that
# M1/M4 fixed had never been evaluated against K9.Component, and the
# closed record contracts in k9_contract.ncl rejected exactly the
# extension fields §5.5 permits. Ledger entries stay advisory, so the
# four svc templates and the rsr checklist are reported, not failed,
# until their own items land.
K9_VALIDATE_LAYER: all
run: |
set -uo pipefail
# The whole tracked corpus, through the same gate the pre-commit hook
# uses, so CI and the hook cannot disagree about what a K9 file is.
# .machine_readable/k9-contract-debt.txt grandfathers the 25 files
# .machine_readable/k9-contract-debt.txt grandfathers the files
# that predate the contract; it is shrink-only (a conforming file
# left in it fails), and it does not protect a file this PR touches.
set +e
out="$(bash .githooks/validate-k9.sh 2>&1)"; rc=$?
set -e
{
echo '## K9 corpus conformance'
echo '## K9 corpus conformance (L2)'
echo '```'
printf '%s\n' "$out"
echo '```'
Expand Down
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:19b4ac92f44aa5e5c133755e8e2e4c2d18383cb64cccd4f31d576ba14e020be5"
source_hash = "sha256:e35752dba0b50684e97c37a4634f6fe08e175ef80b2f44f754b5726cb6c2d157"
route = "the K9 specification, security analysis and adoption guidance (implementations live in hyperpolymath/k9-ecosystem)"

[[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:84005883477e12b0c748bc9e7d68cbb309c199e4509fbfaed27b0454e773a88d"
source_hash = "sha256:dbfe6d40af030e4dd23575d7f01dc86d1557b1d395534af73aa1ab0ac133c59c"
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:beea95b19ff9565abf30d34b758bfb669c5140fc5eef5046a494eafe20a7a91f"
source_hash = "sha256:9e3e5f7bc1469e0736359e3e85cba5311b8ed87056d137d86a98e81c4e3c4b5a"
route = "continuity / verify / handover protocols"

[[spec]]
Expand Down Expand Up @@ -288,7 +288,7 @@ name = "FFP — Form-Fill Provenance"
stream = "foundation"
home = "1-formats/sub-specs/form-fill-provenance/"
canonical_doc = "1-formats/sub-specs/form-fill-provenance/README.adoc"
source_hash = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
source_hash = "sha256:d6e979cdf67dc045e0cf7fefc77e72fa1f2bc4424dd142f68e2f772875449124"
route = "whether a PDF form was machine-filled or printed blank for hand completion, and what a print path must record"

[[spec]]
Expand Down
35 changes: 31 additions & 4 deletions .machine_readable/contractiles/adjust/adjust.k9.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,22 @@ K9!
# erosion causing gradual parameter drift). Where must flags "broken
# now", adjust flags "drifting toward broken".

let base_k9 = import "../k9/template-hunt.k9.ncl" in
let base = import "../_base.ncl" in
# §11.4/K9-S013 — `pedigree_schema` lives in ../_base.ncl. There is no k9/
# subdirectory under .machine_readable/contractiles/, so the old
# `import "../k9/template-hunt.k9.ncl"` never resolved — and the pedigree a
# reviewer read was not the pedigree a host would evaluate.
let base = import "../_base.ncl" in

{
pedigree = base_k9.pedigree_schema & {
pedigree = base.pedigree_schema & {
# §5.2/§6.2 — schema_version, and the reserved-prefix component_type. The
# `contractile:` prefix is the whole of the disambiguation between this
# family's verbs (must/trust/dust/intend/...) and K9's own execution triad
# (must/just/nickel): the K9 contract never names a contractile verb, it
# only ever sees this string.
schema_version = "1.0.0",
component_type = "contractile:adjust",
semantics = "drift-tolerance-and-corrective-action",
contractile_verb = "adjust",
paired_xfile = "../adjust/Adjustfile.a2ml",
paired_runner = "../adjust/adjust.ncl",
Expand All @@ -49,11 +60,27 @@ let base = import "../_base.ncl" in
allow_network = false,
allow_filesystem_write_conditional = true, # auto_fix_when_available may edit
allow_subprocess = 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). process.spawn pays for
# allow_subprocess; fs.write pays for the conditional write path, which
# K9 can only express as the whole capability. At 'Yard the leash is
# still the cap: §7.3 leaves a Yard component unable to write or spawn,
# so these entries describe the request, not a permission in force.
capabilities = [
"fs.write",
"process.spawn",
],
probe_scope = 'measurement_plus_declared_fix,
},
},

variance_schema = {
# A contract, not payload. The fields below are declarations with no
# definition, and Nickel's export refuses to serialize a record containing
# one ("missing field definition for `entry_id`"). `not_exported` says what
# is true: this block documents the variance shape and is not data to
# serialize. Reading `variance_schema` as a contract is unaffected.
variance_schema | not_exported = {
entry_id | String,
reason | String,
approved_by | String,
Expand Down
54 changes: 50 additions & 4 deletions .machine_readable/contractiles/bust/bust.k9.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,22 @@ K9!
# past their expiry), and the "it works, ship it" pattern where a
# caller silently starts using a must-not-run API.

let base_k9 = import "../k9/template-hunt.k9.ncl" in
let base = import "../_base.ncl" in
# §11.4/K9-S013 — `pedigree_schema` lives in ../_base.ncl. There is no k9/
# subdirectory under .machine_readable/contractiles/, so the old
# `import "../k9/template-hunt.k9.ncl"` never resolved — and the pedigree a
# reviewer read was not the pedigree a host would evaluate.
let base = import "../_base.ncl" in

{
pedigree = base_k9.pedigree_schema & {
pedigree = base.pedigree_schema & {
# §5.2/§6.2 — schema_version, and the reserved-prefix component_type. The
# `contractile:` prefix is the whole of the disambiguation between this
# family's verbs (must/trust/dust/intend/...) and K9's own execution triad
# (must/just/nickel): the K9 contract never names a contractile verb, it
# only ever sees this string.
schema_version = "1.0.0",
component_type = "contractile:bust",
semantics = "hard-stop-and-expiry-declaration",
contractile_verb = "bust",
paired_xfile = "../bust/Bustfile.a2ml",
paired_runner = "../bust/bust.ncl",
Expand All @@ -50,11 +61,46 @@ let base = import "../_base.ncl" in
allow_network = false,
allow_filesystem_write = false,
allow_subprocess = true,
signature_required = true,
# §8.3/§8.4 — the grant. allow_subprocess 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).
capabilities = [
"process.spawn",
],
probe_scope = 'read_only,
},

# §6.5/K9-S010 — mandatory at 'Hunt, and none of it may 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
# shells out while describing none of what it does.
side_effects = [
"spawns read-only expiry and state-check probes as child processes (probe_scope = 'read_only; no mutation, no network)",
"records trigger outcomes in the host's evidence sinks (contractile_executions, bust_triggers_history); the drift-log append is indirected by the host, not performed by this component",
"a triggered hard stop fails the gate and blocks the merge — the gate is this component's effect, and no filesystem write is performed by it",
],

# §10.1/K9-S009 — a 'Hunt component MUST carry a signature block. This is
# the claim the file-format requires, and it is not a verified signature:
# with no external verifier the verdict is 'Present_Unverified (§10.2),
# and 'Present_Unverified does not satisfy the Hunt `signature`
# precondition (§10.4). So the file is conforming and still NOT authorised
# to run until the signing ceremony replaces this block.
signature = {
algorithm = "Ed25519",
key_id = "bust-k9",
payload_hash = "sha256:0000000000000000000000000000000000000000000000000000000000000000",
signature = "NOT-A-REAL-SIGNATURE",
},
},

variance_schema = {
# A contract, not payload. The fields below are declarations with no
# definition, and Nickel's export refuses to serialize a record containing
# one ("missing field definition for `entry_id`"). `not_exported` says what
# is true: this block documents the variance shape and is not data to
# serialize. Reading `variance_schema` as a contract is unaffected.
variance_schema | not_exported = {
entry_id | String,
reason | String,
approved_by | String,
Expand Down
35 changes: 31 additions & 4 deletions .machine_readable/contractiles/dust/dust.k9.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,22 @@ K9!
# rollback path; anything retired must preserve the evidence of its
# previous existence).

let base_k9 = import "../k9/template-hunt.k9.ncl" in
let base = import "../_base.ncl" in
# §11.4/K9-S013 — `pedigree_schema` lives in ../_base.ncl. There is no k9/
# subdirectory under .machine_readable/contractiles/, so the old
# `import "../k9/template-hunt.k9.ncl"` never resolved — and the pedigree a
# reviewer read was not the pedigree a host would evaluate.
let base = import "../_base.ncl" in

{
pedigree = base_k9.pedigree_schema & {
pedigree = base.pedigree_schema & {
# §5.2/§6.2 — schema_version, and the reserved-prefix component_type. The
# `contractile:` prefix is the whole of the disambiguation between this
# family's verbs (must/trust/dust/intend/...) and K9's own execution triad
# (must/just/nickel): the K9 contract never names a contractile verb, it
# only ever sees this string.
schema_version = "1.0.0",
component_type = "contractile:dust",
semantics = "recovery-and-retirement",
contractile_verb = "dust",
paired_xfile = "../dust/Dustfile.a2ml",
paired_runner = "../dust/dust.ncl",
Expand All @@ -55,6 +66,17 @@ let base = import "../_base.ncl" in
# --apply flag + per-item approval. Default is dry-run.
allow_filesystem_write_conditional = true,
allow_subprocess = 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). process.spawn pays for
# allow_subprocess; fs.write pays for the conditional write path, which
# K9 can only express as the whole capability. At 'Yard the leash is
# still the cap: §7.3 leaves a Yard component unable to write or spawn,
# so these entries describe the request, not a permission in force.
capabilities = [
"fs.write",
"process.spawn",
],
destructive_action_gating = {
default_mode = 'dry_run,
requires_flag = "--apply",
Expand All @@ -64,7 +86,12 @@ let base = import "../_base.ncl" in
},
},

variance_schema = {
# A contract, not payload. The fields below are declarations with no
# definition, and Nickel's export refuses to serialize a record containing
# one ("missing field definition for `entry_id`"). `not_exported` says what
# is true: this block documents the variance shape and is not data to
# serialize. Reading `variance_schema` as a contract is unaffected.
variance_schema | not_exported = {
entry_id | String,
reason | String,
approved_by | String,
Expand Down
55 changes: 51 additions & 4 deletions .machine_readable/contractiles/intend/intend.k9.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,22 @@ K9!
# * Evidence sinks: VeriSimDB (queryable) + descriptiles/DRIFT.a2ml (repo-local).
# * Failure-mode defenses cross-referenced to the AI failure catalog.

let base_k9 = import "../k9/template-hunt.k9.ncl" in
let base = import "../_base.ncl" in
# §11.4/K9-S013 — `pedigree_schema` lives in ../_base.ncl. There is no k9/
# subdirectory under .machine_readable/contractiles/, so the old
# `import "../k9/template-hunt.k9.ncl"` never resolved — and the pedigree a
# reviewer read was not the pedigree a host would evaluate.
let base = import "../_base.ncl" in

{
pedigree = base_k9.pedigree_schema & {
pedigree = base.pedigree_schema & {
# §5.2/§6.2 — schema_version, and the reserved-prefix component_type. The
# `contractile:` prefix is the whole of the disambiguation between this
# family's verbs (must/trust/dust/intend/...) and K9's own execution triad
# (must/just/nickel): the K9 contract never names a contractile verb, it
# only ever sees this string.
schema_version = "1.0.0",
component_type = "contractile:intend",
semantics = "commitment-and-aspiration",
contractile_verb = "intend",
paired_xfile = "../intend/Intentfile.a2ml",
paired_runner = "../intend/intend.ncl",
Expand Down Expand Up @@ -64,6 +75,36 @@ let base = import "../_base.ncl" in
allow_network = false,
allow_filesystem_write = false, # evidence sinks are indirected
allow_subprocess = true,
signature_required = true,
# §8.3/§8.4 — the grant. allow_subprocess 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).
capabilities = [
"process.spawn",
],
},

# §6.5/K9-S010 — mandatory at 'Hunt, and none of it may 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
# shells out while describing none of what it does.
side_effects = [
"spawns read-only probes for tracked intents as child processes (no mutation, no network)",
"emits drift-log and receipt entries to the host's evidence sinks at session close; the sink writes are indirected by the host, not performed by this component",
"never blocks: an unmet intent or wish is reported as drift, not as a failed gate",
],

# §10.1/K9-S009 — a 'Hunt component MUST carry a signature block. This is
# the claim the file-format requires, and it is not a verified signature:
# with no external verifier the verdict is 'Present_Unverified (§10.2),
# and 'Present_Unverified does not satisfy the Hunt `signature`
# precondition (§10.4). So the file is conforming and still NOT authorised
# to run until the signing ceremony replaces this block.
signature = {
algorithm = "Ed25519",
key_id = "intend-k9",
payload_hash = "sha256:0000000000000000000000000000000000000000000000000000000000000000",
signature = "NOT-A-REAL-SIGNATURE",
},
},

Expand All @@ -75,8 +116,14 @@ let base = import "../_base.ncl" in
# drift, logged to the drift log.
# Per user 2026-04-18: variances are structural, not magic-comment
# markers — markers are gameable.
#
# A contract, not payload. The fields below are declarations with no
# definition, and Nickel's export refuses to serialize a record containing
# one ("missing field definition for `entry_id`"). `not_exported` says what
# is true: this block documents the variance shape and is not data to
# serialize. Reading `variance_schema` as a contract is unaffected.
# -------------------------------------------------------------------
variance_schema = {
variance_schema | not_exported = {
entry_id | String, # which intent/wish id the variance applies to
reason | String,
approved_by | String,
Expand Down
Loading
Loading