CLI verbs (import, diff, lint, doc), applier modes, packaging - #4
Merged
Conversation
guix build -f guix.scm; guix shell -f guix.scm -- hexol
…dd hexol lint for-each-into now binds a fold frame (prefix . outer-state) around each entry's resolve, and apply-op re-embeds traced after-states through the frames, so explain/show see (regions alpha5 …) paths instead of a bare sub-state that never matched. Flat paths are unaffected. Add an access log (resolve-with-access, note-read!): surface get/attr record the (prefixed) paths they read, and (hexol lint) walks one fold to warn on a path read before its last write — the stale-$ case model.md defers to a lint pass. New `hexol lint` verb, exit 1 on any warning. k8s: declare `rule` under #:replace, silencing the core-binding warning every inventory importing (hexol k8s) printed.
The CMDB subsystem was deleted in fc804d8 but docs/authoring.md still listed its layout and .gitignore its log. Remove both and add a README Documentation pointer to the cmdb branch where the prototype survives.
define-construct now registers each construct's schema (name, module, head, fields with required/default/flag/doc, construct doc) in (hexol construct) at definition time — one register-construct! call in the expansion, call semantics unchanged. New #:doc keyword at construct and field level. New (hexol doc) formats the registry; `hexol doc [CONSTRUCT] [-i INV]` lists every loaded construct or prints one's signature, fields table and a minimal example. k8s constructs get one-line docs. Test covers the registry.
…JSON Migration on-ramp: `hexol import -f manifests.yaml` (or `-` for stdin) emits an inventory with one `(resource '…)` per document; `--sugar` lifts Namespace/ConfigMap/Secret/Service/Deployment to the typed constructs when the candidate form, evaluated, rebuilds the object exactly. Server-populated fields of a `kubectl get` dump are stripped by default (`--no-clean` keeps). `--from terraform` reads *.tf.json into terraform-settings/-provider/ -resource/-data/-output forms (terraform-block for the rest); HCL text is out of scope. (hexol import) drives the (yaml libyaml) bindings directly because read-yaml-file reads one document from a file and drops scalar style — plain scalars get core-schema typing, quoted ones stay strings, so a ConfigMap's "8080" survives the trip. test/import.scm round-trips examples/kubernetes.scm (plain and --sugar) and examples/terraform.scm through import + render, comparing resolved state with maps order-insensitive.
…der --validate` Applier signature becomes (state mode -> effects), mode ∈ apply | plan | diff; the old dry? boolean still works (#t → plan, #f → apply, via `mode-of`). terraform: plan/diff → `plan -detailed-exitcode` (2 = drift); kubectl: plan → --dry-run=server, diff → `kubectl diff -f -` (1 = drift); talos config-apply accepts --diff as --dry-run. wait-for/check skip under plan/diff. New `hexol diff [--only SPEC] [--explain]`: same pipeline as apply in mode diff, exit 0 clean / 1 drift / 2 error. --explain binds current-diff-explainer over the resolve trace; the kubectl applier then fetches each live object (`kubectl get -o json`), structural-diffs it against the rendered alist (new hexol/diff.scm) and prints per changed path the value change and the op that set it (label + file:line). Terraform streams its plan as-is. `hexol render -o yaml --validate` pipes the stream through kubeconform -strict -summary when on PATH (report on stderr, exit with its status); `kubeconform-check` is the same as an appliers-pipeline check. Tests: test/apply-mode.scm (mode dispatch against PATH shims in test/fixtures/bin, structural differ) and test/diff-cli.sh (exit codes, --explain output); both wired into `make test`.
- (hexol version) exports %hexol-version = 0.1.0; `hexol --version` and `hexol version` print it. guix.scm carries a commented copy. - CHANGELOG.md (Keep a Changelog): 0.1.0 summarises today, Unreleased lists the verbs in flight. - Containerfile: Alpine + guile/guile-json/jq, guile-libyaml built from source with nyacc in a first stage (neither Alpine nor Debian packages it). ~80 MB. `make image` builds it; `make image-guix` is the guix pack alternative. - flake.nix: package + devShell; nixpkgs lacks nyacc and guile-libyaml too, so both are built in the flake. flake.lock committed. - README Install: source/Guix, container, Nix; Status line -> CHANGELOG. - CI: new image job builds the Containerfile and smoke-tests it (no push).
polyedre
force-pushed
the
main-updates
branch
from
September 5, 2026 11:40
0d5acdb to
4e64b5d
Compare
guile-libyaml 3.0.2 (what manifest.scm resolves to today, and what the Containerfile builds) generates its bindings with nyacc's cdata backend; (system ffi-help-rt) / (bytestructures guile) only existed in a stale personal profile. Rewrite read-yaml-documents / convert-tree on cdata. Containerfile: point the binding at libyaml-0.so.2 (Alpine's runtime package has no unversioned .so). CI: guix pull before guix shell, since the 1.4.0 binary ships the pre-cdata guile-libyaml.
…Savannah's redirect)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
hexol import: wrap existing k8s YAML / Terraform JSONhexol diff [--explain], applier mode (apply|plan|diff),render --validatehexol lint; kernel attributes nested-fold (hx-each) deltas to outer pathhexol doc: introspect define-construct schemas from the CLI🤖 Generated with Claude Code