Skip to content

Commit bcfc683

Browse files
hyperpolymathclaude
andcommitted
feat(contractiles): add six Nickel runners (must/intend/adjust/trust/dust/bust)
One <verb>.ncl runner per contractile dir, paired with the existing <Verb>file.a2ml. Verb is `intend`, not `intent`. All six typecheck under `nickel typecheck`. Each runner declares: - pedigree: schema version, semantics, security leash, paired xfile - schema: the shape the paired <Verb>file.a2ml must satisfy (so the `contractile` CLI can validate each Xfile via nickel) - run: dispatcher behaviour (pass/fail gating, report format, approval requirements for destructive verbs) Semantics per runner: - must: invariants — hard gate on any failure - intend: north-star — reports progress, never gates - adjust: accessibility (WCAG 2.1 AA) — warns by default, deterministic fixes allowed - trust: security + authorised safe-hacking probes — hard gate on verification or probe-finds-issue - dust: exnovation / removal — proposes deletions, --apply gated on approver - bust: error handling + failure recovery — hard gate on missing/broken recovery Unknown files in each <verb>/ dir are human-only archive; machines ignore per the contractile layout rule. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f535ef5 commit bcfc683

6 files changed

Lines changed: 361 additions & 0 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Adjust — accessibility runner
3+
#
4+
# Pairs with: Adjustfile.a2ml (same directory)
5+
# Verb: adjust
6+
# Semantics: accessibility compliance (WCAG 2.1 AA baseline). Gating where
7+
# a deterministic fix exists; advisory where human review needed.
8+
# CLI: `contractile adjust check` → run all probes, list violations
9+
# `contractile adjust fix` → apply deterministic fixes where defined
10+
#
11+
# Anything else in this directory is human-only notes/archive; machines ignore.
12+
13+
{
14+
pedigree = {
15+
schema_version = "1.0.0",
16+
contractile_verb = "adjust",
17+
semantics = "accessibility compliance",
18+
security = {
19+
leash = 'Kennel,
20+
trust_level = "fixes allowed where deterministic",
21+
allow_network = false,
22+
allow_filesystem_write = true, # `adjust fix` may write (deterministic patches only)
23+
allow_subprocess = true,
24+
},
25+
metadata = {
26+
name = "adjust-runner",
27+
version = "1.0.0",
28+
description = "Evaluates accessibility requirements from Adjustfile.a2ml. Fixes deterministic items; flags the rest for human review.",
29+
paired_xfile = "Adjustfile.a2ml",
30+
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>",
31+
},
32+
},
33+
34+
schema = {
35+
requirements
36+
| Array {
37+
id | String,
38+
description | String,
39+
probe | String,
40+
status | [| 'declared, 'partial, 'verified, 'failing |] | default = 'declared,
41+
compliance | String | optional, # e.g. "WCAG 2.1 AA"
42+
notes | String | optional,
43+
fix | String | optional, # deterministic fix command (optional)
44+
},
45+
},
46+
47+
run = {
48+
on_pass = "continue",
49+
on_any_fail = "continue-with-warnings", # accessibility is progress-tracked, not a hard gate by default
50+
report_format = "a2ml",
51+
emit_summary = true,
52+
auto_fix_when_available = true,
53+
},
54+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Bust — error-handling / failure-recovery runner
3+
#
4+
# Pairs with: Bustfile.a2ml (same directory)
5+
# Verb: bust
6+
# Semantics: every declared failure mode must have a recovery path that has
7+
# been exercised. Runner injects failures (via declared probes)
8+
# and verifies the recovery path works. Hard gate on any
9+
# failure-mode with missing or broken recovery.
10+
# CLI: `contractile bust check` → list failure modes + recovery status
11+
# `contractile bust drill` → inject declared failures, verify recovery
12+
#
13+
# Anything else in this directory is human-only notes/archive; machines ignore.
14+
15+
{
16+
pedigree = {
17+
schema_version = "1.0.0",
18+
contractile_verb = "bust",
19+
semantics = "error handling + failure recovery",
20+
security = {
21+
leash = 'Kennel,
22+
trust_level = "controlled failure injection; scoped to system-under-test",
23+
allow_network = false,
24+
allow_filesystem_write = true, # drills may write transient state (tmp dirs, test DBs)
25+
allow_subprocess = true,
26+
injection_scope = "system-under-test-only",
27+
},
28+
metadata = {
29+
name = "bust-runner",
30+
version = "1.0.0",
31+
description = "Exercises declared failure modes and verifies recovery paths. Hard-gates on any failure mode without working recovery.",
32+
paired_xfile = "Bustfile.a2ml",
33+
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>",
34+
},
35+
},
36+
37+
schema = {
38+
failure_modes
39+
| Array {
40+
id | String,
41+
description | String,
42+
class | [| 'network, 'disk_full, 'oom, 'timeout, 'partial_write, 'panic, 'crash, 'rollback, 'concurrency |],
43+
injection_probe | String, # command that deterministically causes this failure
44+
recovery_probe | String, # command that verifies recovery (exit 0 = recovered)
45+
expected_recovery_time_seconds | Number | default = 30,
46+
status | [| 'declared, 'drilled, 'verified, 'failing |] | default = 'declared,
47+
notes | String | optional,
48+
},
49+
},
50+
51+
run = {
52+
on_pass = "continue",
53+
on_any_fail = "exit-nonzero", # missing or broken recovery blocks merge
54+
report_format = "a2ml",
55+
emit_summary = true,
56+
record_recovery_times = true, # feeds the performance tier
57+
},
58+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Dust — exnovation / code-removal runner
3+
#
4+
# Pairs with: Dustfile.a2ml (same directory)
5+
# Verb: dust
6+
# Semantics: exnovation. Identifies code, docs, files, dependencies that are
7+
# candidates for REMOVAL. Advisory by default; can be flipped to
8+
# active delete via `contractile dust sweep --apply`.
9+
# CLI: `contractile dust find` → list removal candidates
10+
# `contractile dust sweep` → dry-run removals
11+
# `contractile dust sweep --apply` → actually delete (gated)
12+
#
13+
# Anything else in this directory is human-only notes/archive; machines ignore.
14+
15+
{
16+
pedigree = {
17+
schema_version = "1.0.0",
18+
contractile_verb = "dust",
19+
semantics = "exnovation / removal",
20+
security = {
21+
leash = 'Kennel,
22+
trust_level = "proposes deletion; --apply required to execute",
23+
allow_network = false,
24+
allow_filesystem_write = true, # --apply mode writes (deletes)
25+
allow_subprocess = true,
26+
destructive_mode_requires_flag = "--apply",
27+
},
28+
metadata = {
29+
name = "dust-runner",
30+
version = "1.0.0",
31+
description = "Identifies and optionally removes exnovation targets listed in Dustfile.a2ml. Destructive mode gated behind --apply.",
32+
paired_xfile = "Dustfile.a2ml",
33+
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>",
34+
},
35+
},
36+
37+
schema = {
38+
removal_candidates
39+
| Array {
40+
id | String,
41+
description | String,
42+
target | String, # file / path / symbol / dep name
43+
reason | String, # why it's a removal candidate
44+
probe | String | optional, # command that confirms it's still removable
45+
status | [| 'declared, 'proposed, 'approved, 'removed |] | default = 'declared,
46+
approver | String | optional, # who signed off (for 'approved / 'removed)
47+
notes | String | optional,
48+
},
49+
},
50+
51+
run = {
52+
on_pass = "continue",
53+
on_any_fail = "continue-with-warnings",
54+
report_format = "a2ml",
55+
emit_summary = true,
56+
apply_requires_approval = true, # only 'approved items get swept, even with --apply
57+
},
58+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Intend — north-star runner (verb is `intend`, not `intent`)
3+
#
4+
# Pairs with: Intentfile.a2ml (same directory)
5+
# Verb: intend
6+
# Semantics: declarative aspirations. Not a gate — reports progress toward
7+
# target state. Items can be declared / in-progress / done /
8+
# deferred / retired.
9+
# CLI: `contractile intend run` → print status table
10+
# `contractile intend progress` → diff declared-vs-observed
11+
#
12+
# Anything else in this directory is human-only notes/archive; machines ignore.
13+
14+
{
15+
pedigree = {
16+
schema_version = "1.0.0",
17+
contractile_verb = "intend",
18+
semantics = "north-star / aspirational",
19+
security = {
20+
leash = 'Kennel,
21+
trust_level = "read-only reporting",
22+
allow_network = false,
23+
allow_filesystem_write = false,
24+
allow_subprocess = true, # probe commands may shell out
25+
},
26+
metadata = {
27+
name = "intend-runner",
28+
version = "1.0.0",
29+
description = "Reports progress toward declared future-state intents. Non-gating.",
30+
paired_xfile = "Intentfile.a2ml",
31+
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>",
32+
},
33+
},
34+
35+
schema = {
36+
intents
37+
| Array {
38+
id | String,
39+
description | String,
40+
probe | String | optional, # shell command that indicates done-ness
41+
status | [| 'declared, 'in_progress, 'done, 'deferred, 'retired |] | default = 'declared,
42+
notes | String | optional,
43+
target_date | String | optional,
44+
},
45+
},
46+
47+
run = {
48+
on_pass = "continue",
49+
on_any_fail = "continue", # never blocks; it's a report
50+
report_format = "a2ml",
51+
emit_summary = true,
52+
emit_diff = true, # declared vs observed
53+
},
54+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Must — invariants runner
3+
#
4+
# Pairs with: Mustfile.a2ml (same directory)
5+
# Verb: must (invariant assertion)
6+
# Semantics: every check is a hard gate. A single failure blocks merge.
7+
# CLI: `contractile must run` → reads Mustfile.a2ml, evaluates each check,
8+
# emits pass/fail verdict per item, exits non-zero if any failed.
9+
#
10+
# This file is the *schema + runner* that the `contractile` CLI (at
11+
# /var/mnt/eclipse/repos/reposystem/contractiles/cli/) loads alongside
12+
# Mustfile.a2ml. Anything else in this directory is human-only notes/archive
13+
# and MUST be ignored by machines.
14+
15+
{
16+
pedigree = {
17+
schema_version = "1.0.0",
18+
contractile_verb = "must",
19+
semantics = "invariant",
20+
security = {
21+
leash = 'Kennel,
22+
trust_level = "read-only verification",
23+
allow_network = false,
24+
allow_filesystem_write = false,
25+
allow_subprocess = true, # verification probes may shell out (e.g. grep, test -f)
26+
},
27+
metadata = {
28+
name = "must-runner",
29+
version = "1.0.0",
30+
description = "Evaluates every invariant in the adjacent Mustfile.a2ml as a hard gate.",
31+
paired_xfile = "Mustfile.a2ml",
32+
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>",
33+
},
34+
},
35+
36+
# Contract schema — the shape every Mustfile.a2ml must satisfy.
37+
# Used by `contractile must typecheck Mustfile.a2ml`.
38+
schema = {
39+
invariants
40+
| Array {
41+
id | String,
42+
description | String,
43+
probe | String, # shell command; exit 0 = pass
44+
status | [| 'declared, 'verified, 'failing |] | default = 'declared,
45+
severity | [| 'critical, 'high, 'medium |] | default = 'critical,
46+
notes | String | optional,
47+
fix | String | optional,
48+
},
49+
},
50+
51+
# Runner behaviour — consumed by the contractile CLI dispatcher.
52+
run = {
53+
on_pass = "continue",
54+
on_any_fail = "exit-nonzero", # hard gate
55+
report_format = "a2ml", # emit a2ml report, not json
56+
emit_summary = true,
57+
},
58+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Trust — security + safe-hacking runner
3+
#
4+
# Pairs with: Trustfile.a2ml (same directory)
5+
# Verb: trust
6+
# Semantics: integrity / provenance / security verification PLUS a declared
7+
# "safe hacking + testing" section — authorised offensive probes
8+
# (pen-test harness runs, chaos-engineering probes) scoped to the
9+
# repo under test, NEVER touching external systems.
10+
# CLI: `contractile trust verify` → run all verifications (read-only)
11+
# `contractile trust probe` → run declared safe-hacking probes
12+
#
13+
# Anything else in this directory is human-only notes/archive; machines ignore.
14+
15+
{
16+
pedigree = {
17+
schema_version = "1.0.0",
18+
contractile_verb = "trust",
19+
semantics = "security + provenance + safe-hacking",
20+
security = {
21+
leash = 'Kennel,
22+
trust_level = "verification + authorised-probe",
23+
allow_network = false, # verifications are offline by default
24+
allow_filesystem_write = false, # trust writes NOTHING
25+
allow_subprocess = true,
26+
authorised_probes_only = true, # probe section must explicitly list allowed targets
27+
},
28+
metadata = {
29+
name = "trust-runner",
30+
version = "1.0.0",
31+
description = "Security + provenance verifications plus authorised safe-hacking probes. All probes are scoped to the repo under test; never hits external systems.",
32+
paired_xfile = "Trustfile.a2ml",
33+
author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>",
34+
},
35+
},
36+
37+
schema = {
38+
verifications
39+
| Array {
40+
id | String,
41+
description | String,
42+
probe | String, # read-only; exit 0 = pass
43+
status | [| 'declared, 'verified, 'failing |] | default = 'declared,
44+
severity | [| 'critical, 'high, 'medium, 'low |] | default = 'high,
45+
notes | String | optional,
46+
},
47+
48+
# Safe-hacking + testing section (added 2026-04-17 per user direction).
49+
# Each probe here is an ACTIVELY EXECUTED test — fuzz runs, chaos probes,
50+
# auth-bypass attempts, injection tests. All scoped to the current repo.
51+
safe_hacking
52+
| {
53+
scope | String, # e.g. "this-repo-only" / "localhost"
54+
allowed_probe_classes
55+
| Array [| 'fuzz, 'property_test, 'chaos, 'auth_bypass, 'injection, 'timing |]
56+
| default = [],
57+
probes
58+
| Array {
59+
id | String,
60+
class | [| 'fuzz, 'property_test, 'chaos, 'auth_bypass, 'injection, 'timing |],
61+
description | String,
62+
probe | String, # command to run the probe
63+
expected_outcome | [| 'probe_blocks_attempt, 'probe_finds_no_issue |],
64+
timeout_seconds | Number | default = 300,
65+
notes | String | optional,
66+
}
67+
| default = [],
68+
}
69+
| default = { scope = "this-repo-only", allowed_probe_classes = [], probes = [] },
70+
},
71+
72+
run = {
73+
on_pass = "continue",
74+
on_any_fail = "exit-nonzero", # hard gate on verifications
75+
safe_hacking_on_unexpected_outcome = "exit-nonzero", # probe found what it shouldn't = block
76+
report_format = "a2ml",
77+
emit_summary = true,
78+
},
79+
}

0 commit comments

Comments
 (0)