Skip to content

feat: dogfood cl-prolog/cl-weave with option groups, perf, and hardening#2

Merged
takeokunn merged 3 commits into
mainfrom
feat/cl-prolog-cl-weave-integration
Jul 19, 2026
Merged

feat: dogfood cl-prolog/cl-weave with option groups, perf, and hardening#2
takeokunn merged 3 commits into
mainfrom
feat/cl-prolog-cl-weave-integration

Conversation

@takeokunn

Copy link
Copy Markdown
Collaborator

Summary

main carried a half-migrated cl-prolog/cl-weave integration: the test-side
changes had landed, but the corresponding src/ side (the public
parse-argv dispatcher and Prolog-backed option-relation validation) was
missing, leaving the library and test suite unbuildable. This restores the
complete integration and extends it:

  • Prolog rulebase dogfooding (src/option-relations.lisp) — :requires
    / :conflicts-with option relations are validated through a cl-prolog
    rulebase (transitive closure + conflicting-closure detection) instead of
    ad-hoc graph code.
  • exclusive-group / required-exclusive-group — declare an at-most-one
    or exactly-one set of options, validated through the same conflict
    machinery and rendered in help as a single "one of: --a | --b" choice
    instead of pairwise conflicts.
  • Performance — drop redundant per-parse relation validation (already
    done once at make-app), memoize transitive-closure Prolog queries, and
    early-out when no option declares a relation (~3.9ms → ~0.006ms per parse
    in the common case).
  • Security hardening — restrict app/command/option names to a safe
    identifier charset, closing shell-injection vectors in generated
    bash/zsh/fish completion scripts, and harden the derived completion
    function name.
  • Bug fixes — honor -- before a command token (POSIX literal
    separator), honor :stop-parsing-p on :flag/:boolean options (long and
    short forms), stop a bare - from raising an uncaught array-index error,
    replace a non-transitive option-relation sort comparator (undefined sort
    behaviour) with a valid strict weak ordering, and fix a Prolog atom
    package-instability bug plus an unbalanced paren in test helpers.
  • CI fix (this branch only, not upstream in the reference)
    flake.nix referenced cl-weave/cl-prolog as path:../cl-weave /
    path:../cl-prolog inputs. Those only resolve against a sibling checkout
    on the local filesystem; GitHub Actions only checks out cl-cli itself,
    so nix flake check had no way to fetch them. Repointed both inputs at
    github:takeokunn/cl-weave / github:takeokunn/cl-prolog (the pattern
    the earlier working feat/cl-prolog-cl-weave branch used) and regenerated
    flake.lock.

Test plan

  • sbcl --non-interactive --load tests/run-tests.lisp --eval '(cl-cli/tests:run-tests)' --quit (with CL_WEAVE_SOURCE_DIR /
    CL_PROLOG_SOURCE_DIR pointed at sibling checkouts) →
    172 passed, 0 failed, 0 errored.
  • nix flake lock regenerated cleanly against
    github:takeokunn/cl-weave / github:takeokunn/cl-prolog.
  • nix eval .#checks.x86_64-linux.sbcl.drvPath and
    .#devShells.x86_64-linux.default.drvPath resolve without error
    (full build of the x86_64-linux check couldn't be exercised on this
    darwin machine — no Linux builder available locally — but evaluation
    succeeding confirms the input-fetch fix; CI on ubuntu-latest builds
    it directly).

Restore the cl-prolog/cl-weave integration that main had half-migrated (the
public parse-argv dispatcher and Prolog-backed option-relation validation were
missing, leaving the library and test suite unbuildable), then extend and
harden it. 172 tests pass under SBCL.

Features (advanced usage / functional requirements):
- Prolog rulebase dogfooding for :requires/:conflicts option relations
  (transitive closure + conflicting-closure detection) in src/option-relations.
- exclusive-group / required-exclusive-group: at-most-one and exactly-one
  option sets, validated through the same conflict machinery and rendered in
  help as a single "one of: --a | --b" choice instead of pairwise conflicts.

Performance:
- Drop redundant per-parse declared-relation validation (already done at
  make-app), memoize transitive-closure Prolog queries, and early-out when no
  option declares a relation: ~3.9ms -> ~0.006ms per parse in the common case.

Security:
- Restrict app/command/option names to a safe identifier charset, closing
  shell-injection vectors in generated bash/zsh/fish completion scripts; also
  harden the derived completion function name.

Bug fixes:
- Honor `--` before a command token (POSIX literal separator).
- Honor :stop-parsing-p on :flag/:boolean options (long and short forms).
- Stop a bare `-` from raising an uncaught array-index error.
- Replace the non-transitive option-relation sort comparator (undefined
  sort behaviour) with a valid strict weak ordering.
- Fix LOOP &rest destructuring, prolog atom package instability, and an
  unbalanced paren in the test helpers.

Tests:
- cl-weave property-based parser tests (round-trips, `--`/stop-parsing,
  attached vs separated, multiple-p order, exclusive-group invariants).
- consumer-migration Prolog contracts via cl-prolog/weave deftest-queries.
path:../cl-weave and path:../cl-prolog only resolve against a sibling
checkout on the local filesystem, so nix flake check has no way to
fetch them on a GitHub Actions runner where only cl-cli itself is
checked out. Point the inputs at github:takeokunn/cl-weave and
github:takeokunn/cl-prolog (the pattern the proven feat/cl-prolog-cl-weave
reference branch used) so evaluation and CI actually work.
@takeokunn
takeokunn merged commit cc64a03 into main Jul 19, 2026
1 check passed
@takeokunn
takeokunn deleted the feat/cl-prolog-cl-weave-integration branch July 19, 2026 11:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant