Commitments are run-dir-local declared dependencies: intentional commitments that scripts rely on when they need help that cannot be expressed purely inside the script.
- Declared in
<RUN_DIR>/commitments.json. - Validated by the meta-schema at
schema/commitments.json. - Enrolled at runtime via
commit_help_me <ensure|detect|emit> <commitment.id>(provided bylib/library.sh). - Recorded in boundary objects under
/context/commitmentsas(id, helps[])pairs.
This document explains what commitments.json commits to, how it is
validated, and what “extension” means for run-dir authors.
- The run dir’s
commitments.jsonis validated againstschema/commitments.json. - Runners preflight and require
commitments.json(missing/invalid is a hard error). - During script execution:
commit_help_merecords(commitment.id, help)enrollments for the current script run (returns0on success,1on error).emit-recordreads those enrollments viaFENCERUNNER_COMMITMENT_ENROLLMENTS_PATHand serializes them into/context/commitments.
commit_help_me does not validate enrollments against commitments.json at runtime; commitments.json is a structured dependency registry for run-dir authors and downstream consumers.
Top level:
schema_version— must be"commitments_v1".commitments[]— list of commitment definitions (may be empty).
Each commitment definition:
id— identifier (run-dir-local namespace; referenced by scripts).provider— one ofrunner,system,user.helps[]— one or more verbs from{ensure, detect, emit}(unique).is— short human description (max 100 chars).at— string location/handle (semantics vary byprovider).version— string version label.
- Keep it stable: it becomes the durable key recorded in
/context/commitments. - Must match
^[A-Za-z0-9_.-]+$(letters/digits plus_,.,-). - Uniqueness is required within a single run dir.
Why the tight alphabet: commitment ids are designed to be portable, queryable
tokens that work well in Bash, JSON, and downstream tools. Keeping ids free of
whitespace, slashes, and shell-significant punctuation avoids quoting
surprises, keeps enrollment recording simple (id|help lines), and reduces
“looks the same but isn’t” issues when agents are generating or editing run
dirs.
Runtime note: the runner and helpers enforce the same id contract at runtime.
If a script calls commit_help_me with an invalid id, enrollment fails and the
script should treat that as a hard error.
provider communicates where the run dir expects the dependency to come from:
runner— provided by the fencerunner runner (typically a helper binary built from this repo, e.g.emit-record).system— provided by the host system/runtime (for examplepython3on PATH).user— provided by the user/operator (for example a tool installed outside the repo).
The runner treats this as descriptive metadata today (it does not attempt to
prove a system or user dependency exists).
helps[] is the explicit list of supported verbs for the dependency description.
Scripts enroll by choosing a verb and id at the callsite (commit_help_me <verb> <id>).
The runner does not currently enforce that the requested verb appears in the
declared helps[]; commit_help_me only validates that <verb> is one of
ensure|detect|emit.
Keep is short and concrete. It should answer “what is this dependency?” in one
sentence fragment.
at is a string that points at what to use:
- For
provider=runner, it is intended to be a repo-relative path (schema rejects absolute paths); in practice this is often a helper name likeemit-record. - For
provider=system|user,atis currently treated as an opaque string (often a command name likepython3or a path).
version is a string you control. Use it to signal compatibility expectations
to humans and downstream tooling.
When a script enrolls in a commitment via commit_help_me, the enrollment is meant
to show up in the boundary object as a (id, helps[]) pair under
/context/commitments.
The runner does not persist separate enrollment logs: enrollment data lives in the boundary object stream.
Minimal (no declared commitments):
{
"schema_version": "commitments_v1",
"commitments": []
}A run dir that declares the record emitter plus one system runtime:
{
"schema_version": "commitments_v1",
"commitments": [
{
"id": "emit.record",
"provider": "runner",
"helps": ["emit"],
"is": "Boundary record emitter",
"at": "emit-record",
"version": "v1"
},
{
"id": "python3",
"provider": "system",
"helps": ["ensure"],
"is": "Python 3 interpreter",
"at": "python3",
"version": "v1"
}
]
}For run-dir authors today, “extension” means:
- adding new commitment entries under
commitments[], - adding additional verbs to
helps[](when your scripts actually use them), - versioning/changing
is/at/versionas your run dir evolves.
commitments_v1 is intentionally strict: commitment definitions cannot carry
extra keys. If you need additional fields, that requires a schema + validator
change.
- High level: Declared dependencies, not inferred reality — commitments are an authoring-time declaration (“this script expects help from X”) and a trustworthy signal from a willing author, not a security boundary or a detector of what the host actually provides.
Lower-level opinions:
- Dir-local registry: commitment ids must be unique within one run dir; the runner does not coalesce registries across run dirs.
- Minimal preflight: runners validate that
commitments.jsonis present and schema-valid;commit_help_mevalidates only its own inputs and duplicate pairs (no registry enforcement). - Simple verbs:
helps[]is constrained to{ensure, detect, emit}by schema;commit_help_meaccepts only those verbs. - Stable shape: each commitment has
{id, provider, helps, is, at, version}; extra keys are rejected by the schema. - Runner
atis relative:provider=runnerexpects a repo-relativeat(schema rejects absolute paths); other providers treatatas an opaque string for now. - Recording is in the record: enrollment data lives only in the boundary object stream (no separate logs).