From 49765b4330099d721d04a8de209e22c2c1c9b316 Mon Sep 17 00:00:00 2001 From: takeokunn Date: Mon, 17 Aug 2026 17:11:12 +0900 Subject: [PATCH 1/4] refactor: follow the cl-prolog-kit / cl-dataflow-kit rename nerima-lisp/cl-prolog was renamed to cl-prolog-kit (v1.5.0) and cl-dataflow to cl-dataflow-kit (v1.2.0). The ASDF system names and CL package names moved with the repositories, so `cl-prolog:` no longer resolves and `:depends-on "cl-prolog"` no longer finds a system. Updated here: the flake input's Nix variable name and URL, the ASDF :depends-on entries, every package-qualified symbol reference, and the prose that names either package. flake.lock was regenerated with `nix flake lock`, not hand-edited. This also moves the pin forward to the current release rather than carrying the old one, since the tag the old pin named no longer contains a system under the old name. --- docs/notes/cl-weave-advanced-usage-audit.md | 8 +-- docs/notes/coverage-analysis.md | 2 +- docs/notes/nerima-lisp-package-audit.md | 8 +-- docs/src/guide/concepts.md | 2 +- docs/src/guide/recipes.md | 2 +- docs/src/project/contributing.md | 2 +- docs/src/project/public-readiness.md | 2 +- docs/src/reference/architecture.md | 8 +-- flake.lock | 61 ++++++++++--------- flake.nix | 32 +++++----- nshell.asd | 8 +-- run-tests.lisp | 2 +- scripts/coverage.lisp | 2 +- scripts/verify-release-bundle.pl | 4 +- scripts/weave.lisp | 4 +- src/application/pipeline-diagram.lisp | 42 ++++++------- src/domain/completion/knowledge-base.lisp | 14 ++--- src/domain/completion/rule-data.lisp | 26 ++++---- src/package-domain.lisp | 6 +- t/e2e/test-smoke.lisp | 4 +- ...est-completion-rule-prover-boundaries.lisp | 4 +- t/unit/test-pipeline-diagram.lisp | 20 +++--- t/weave/completion-advanced.lisp | 4 +- t/weave/completion-logic.lisp | 2 +- t/weave/logic-crosscheck.lisp | 4 +- t/weave/package.lisp | 14 ++--- t/weave/support.lisp | 2 +- 27 files changed, 145 insertions(+), 144 deletions(-) diff --git a/docs/notes/cl-weave-advanced-usage-audit.md b/docs/notes/cl-weave-advanced-usage-audit.md index 412f81e..361957c 100644 --- a/docs/notes/cl-weave-advanced-usage-audit.md +++ b/docs/notes/cl-weave-advanced-usage-audit.md @@ -28,12 +28,12 @@ and a dedicated `test-completion-properties.lisp` with 12), four separate input-state property files (core, navigation, kill-yank, search, completion), autosuggest, prompt rendering, and CPS. -## cl-prolog-query integration — a second suite dedicated to it +## cl-prolog-kit-query integration — a second suite dedicated to it `nshell/weave` (`nshell.asd`, `t/weave/`) is a whole second ASDF system, separate from `nshell/test`, whose own description is "property-based, -fixture, benchmark, and cl-prolog-query coverage of the completion engine". -It depends on `cl-prolog/weave` specifically for this. The weave tests use +fixture, benchmark, and cl-prolog-kit-query coverage of the completion engine". +It depends on `cl-prolog-kit/weave` specifically for this. The weave tests use `prove`/`assert-fact!`/prolog querying against the completion rulebase exported by `nshell.domain.completion` (`#:completes #:describes #:has-flag #:command-is ...` -- see `nerima-lisp-package-audit.md`), letting tests write @@ -60,6 +60,6 @@ test. "cl-weave を利用して高度な使い方をしてほしい" is satisfied by breadth, not one showcase: mutation testing (the framework's own stated "most advanced facility"), property-based trials with custom generators and shrinkers, -a second whole ASDF system dedicated to cl-prolog-query integration, and +a second whole ASDF system dedicated to cl-prolog-kit-query integration, and table-driven consolidation, all exercised by the existing suite rather than being demonstrated once and left unused elsewhere. diff --git a/docs/notes/coverage-analysis.md b/docs/notes/coverage-analysis.md index e772da2..2497787 100644 --- a/docs/notes/coverage-analysis.md +++ b/docs/notes/coverage-analysis.md @@ -30,7 +30,7 @@ minimum and target fields have been inspected. A passing minimum with - Unit and integration tests cover parsing, expansion, completion, environment, process, timeout, redirection, command dispatch, and job management. - The weave suite exercises the completion knowledge base through property - cases, fixtures, benchmarks, direct Prolog queries, and the `cl-prolog/weave` + cases, fixtures, benchmarks, direct Prolog queries, and the `cl-prolog-kit/weave` bridge. - PTY, terminal, and external-binary paths are verified by the PTY-capable runner. The Nix sandbox may skip those environment-dependent cases, so the diff --git a/docs/notes/nerima-lisp-package-audit.md b/docs/notes/nerima-lisp-package-audit.md index 1e562f8..cfd8999 100644 --- a/docs/notes/nerima-lisp-package-audit.md +++ b/docs/notes/nerima-lisp-package-audit.md @@ -14,9 +14,9 @@ appear unqualified): | package | role in nshell | evidence | |---|---|---| -| `cl-prolog` | completion knowledge base — facts/rules, `map-prolog-solutions` | `domain/completion/rule-data.lisp` (8 refs) | +| `cl-prolog-kit` | completion knowledge base — facts/rules, `map-prolog-solutions` | `domain/completion/rule-data.lisp` (8 refs) | | `cl-parser-kit` | `$((…))` arithmetic tokenizer + Pratt parser | `:import-from` in `package.lisp`; `domain/expansion/arithmetic.lisp` | -| `cl-dataflow` | reactive dataflow wiring | 12 refs | +| `cl-dataflow-kit` | reactive dataflow wiring | 12 refs | | `cl-host-kit` | host environment, pathname, and process boundaries | `presentation/repl-environment.lisp`, `infrastructure/terminal/ansi.lisp`, `application/builtin-runtime.lisp` | | `cl-boundary-kit` | clock/sleeper boundaries (also under cl-process-kit) | 14 refs | | `cl-cli` | argument-vector parsing for `main` | 13 refs | @@ -32,7 +32,7 @@ The test systems are kept separate from the runtime dependency audit: | package | role in nshell's test systems | evidence | |---|---|---| | `cl-weave` | the test framework for the weave suite | `nshell/weave` | -| `cl-prolog/weave` | cl-prolog-query coverage of the completion engine | `nshell/weave` | +| `cl-prolog-kit/weave` | cl-prolog-kit-query coverage of the completion engine | `nshell/weave` | ## Transitive, not adopted directly @@ -62,6 +62,6 @@ nshell never handles (`cl-json-kit`), or a build-time tool (`paredit-cli`). Re-run the usage half of this audit with: ``` -rg -o '\b(cl-prolog|cl-dataflow|cl-boundary-kit|cl-cli|cl-tty-kit|process-kit|history-kit|cl-concurrent-kit)::?[a-z]' src/ \ +rg -o '\b(cl-prolog-kit|cl-dataflow-kit|cl-boundary-kit|cl-cli|cl-tty-kit|process-kit|history-kit|cl-concurrent-kit)::?[a-z]' src/ \ | perl -pe 's/:.*$//' | sort | uniq -c | sort -rn ``` diff --git a/docs/src/guide/concepts.md b/docs/src/guide/concepts.md index dbcbab9..82c518a 100644 --- a/docs/src/guide/concepts.md +++ b/docs/src/guide/concepts.md @@ -19,7 +19,7 @@ which keeps the interactive core deterministic and unit-testable. ## Completion is a knowledge base, not a table Completion candidates come from a logic knowledge base compiled into a -[cl-prolog](https://github.com/nerima-lisp/cl-prolog) rulebase, queried through +[cl-prolog-kit](https://github.com/nerima-lisp/cl-prolog-kit) rulebase, queried through predicates such as `completes`, `describes`, `has-flag`, `command-is`, `suggests-dir`, and `suggests-file`. diff --git a/docs/src/guide/recipes.md b/docs/src/guide/recipes.md index c4f973d..b7d973d 100644 --- a/docs/src/guide/recipes.md +++ b/docs/src/guide/recipes.md @@ -12,7 +12,7 @@ pipeline-graph --mermaid 'cat access.log | grep 404 | wc -l' ``` It is a diagnostic built on the -[cl-dataflow](https://github.com/nerima-lisp/cl-dataflow) computation-graph +[cl-dataflow-kit](https://github.com/nerima-lisp/cl-dataflow-kit) computation-graph toolkit, and it validates the pipeline as it builds the graph, so a malformed redirect shows up as an error rather than a picture. diff --git a/docs/src/project/contributing.md b/docs/src/project/contributing.md index 10feab7..4d0fcbc 100644 --- a/docs/src/project/contributing.md +++ b/docs/src/project/contributing.md @@ -45,7 +45,7 @@ Iterate with the smallest relevant suite, then run the full gate before review. |---|---| | Anything | `nix flake check --print-build-logs` before review; the full gate runs on `x86_64-linux` CI | | Domain logic, builtins, parser, expansion | `nix run .#test` | -| Completion engine or cl-prolog knowledge base | `sbcl --script scripts/weave.lisp` | +| Completion engine or cl-prolog-kit knowledge base | `sbcl --script scripts/weave.lisp` | | PTY, subprocess, terminal, signal, job control | the non-sandboxed run below | | Coverage-oriented validation | `nix develop -c sbcl --script scripts/coverage.lisp` | diff --git a/docs/src/project/public-readiness.md b/docs/src/project/public-readiness.md index e2ae609..a9cc582 100644 --- a/docs/src/project/public-readiness.md +++ b/docs/src/project/public-readiness.md @@ -50,7 +50,7 @@ What is actually checkable on a plain `aarch64-darwin` development machine `nix build --no-link .#checks.aarch64-darwin.formatting` both exit 0 -- the mkdocs `--strict` build and the treefmt gate pass on this platform. - The Darwin `build`, `default`, and `smoke-test` check attributes can remain - unavailable when the pinned `cl-prolog` package has no Darwin build. The + unavailable when the pinned `cl-prolog-kit` package has no Darwin build. The complete `nix flake check` and release-bundle gate are therefore verified on `x86_64-linux` CI; run available Darwin checks directly rather than treating a missing attribute as a feature failure. diff --git a/docs/src/reference/architecture.md b/docs/src/reference/architecture.md index fac1962..4400592 100644 --- a/docs/src/reference/architecture.md +++ b/docs/src/reference/architecture.md @@ -59,7 +59,7 @@ layer where it fits the domain-driven design: rule-based tokenizer and Pratt (operator-precedence) parser drive `$((...))` arithmetic, which parses to an AST and then evaluates, adding `**`, bitwise `& | ^ ~`, shifts `<< >>`, and the ternary `?:`. -- **[cl-dataflow](https://github.com/nerima-lisp/cl-dataflow)** — renders +- **[cl-dataflow-kit](https://github.com/nerima-lisp/cl-dataflow-kit)** — renders pipelines as validated computation graphs (`pipeline-graph`) and models the job lifecycle as an analyzable state machine. - **[cl-boundary-kit](https://github.com/nerima-lisp/cl-boundary-kit)** — makes @@ -83,7 +83,7 @@ layer where it fits the domain-driven design: timeout-guarded process launch, escalating SIGTERM to SIGKILL across a child's whole process group so a timed-out command substitution leaves no orphaned descendants. -- **[cl-prolog](https://github.com/nerima-lisp/cl-prolog)** — the logic engine +- **[cl-prolog-kit](https://github.com/nerima-lisp/cl-prolog-kit)** — the logic engine behind the completion knowledge base. ## Test suites @@ -93,9 +93,9 @@ exposed as Nix checks: - **`nshell/test`** — the primary regression suite, in `t/`. - **`nshell/weave`** — a focused suite exercising the completion engine's - cl-prolog knowledge base with property-based tests, fixtures, benchmarks, and + cl-prolog-kit knowledge base with property-based tests, fixtures, benchmarks, and direct Prolog queries (`findall`, negation-as-failure, foreign predicates) - plus the `cl-prolog/weave` query bridge. + plus the `cl-prolog-kit/weave` query bridge. Cases that need a real PTY, `stty`, or external binaries cannot run in the Nix sandbox and are covered by CI's separate `integration` job; see diff --git a/flake.lock b/flake.lock index daad126..35deb6c 100644 --- a/flake.lock +++ b/flake.lock @@ -68,20 +68,20 @@ "type": "github" } }, - "cl-dataflow": { + "cl-dataflow-kit": { "flake": false, "locked": { - "lastModified": 1785657612, - "narHash": "sha256-uvbaAJ6Q3f9VSRfe71ASckDfLWobpD8VdPsmSeIkWO0=", + "lastModified": 1786949793, + "narHash": "sha256-26KT1QL7KJ2soRppDDoYwgXyzLKOZjPu0Un0eJBL5M4=", "owner": "nerima-lisp", - "repo": "cl-dataflow", - "rev": "e3297e6c0ee5812de73bb71d19763140dcd39356", + "repo": "cl-dataflow-kit", + "rev": "c4770c3b757bc40a9d5ecfc5de53871ec5da26c8", "type": "github" }, "original": { "owner": "nerima-lisp", - "ref": "v1.1.1", - "repo": "cl-dataflow", + "ref": "v1.2.0", + "repo": "cl-dataflow-kit", "type": "github" } }, @@ -178,7 +178,7 @@ "cl-nix-forge_2": { "inputs": { "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "nixpkgs" ], "treefmt-nix": "treefmt-nix_2" @@ -201,7 +201,7 @@ "cl-nix-forge_3": { "inputs": { "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "cl-weave", "nixpkgs" ], @@ -279,7 +279,7 @@ "type": "github" } }, - "cl-prolog": { + "cl-prolog-kit": { "inputs": { "cl-nix-forge": "cl-nix-forge_2", "cl-weave": "cl-weave", @@ -290,17 +290,17 @@ "treefmt-nix": "treefmt-nix_6" }, "locked": { - "lastModified": 1785918678, - "narHash": "sha256-Xr2Ga1qzz08MApO5N4v+bs/wmCC4FdJlYyjsC8TnXxU=", + "lastModified": 1786948477, + "narHash": "sha256-3qn9W1Jmbxnr0Si77J7Klo26oX/zjgBVwb5ye74NsTY=", "owner": "nerima-lisp", - "repo": "cl-prolog", - "rev": "7581f72c7d080afd4c863e1d44010ccb5d7258ad", + "repo": "cl-prolog-kit", + "rev": "239368e1001bc3a8576d45770c9e91da11515d09", "type": "github" }, "original": { "owner": "nerima-lisp", - "ref": "v1.4.3", - "repo": "cl-prolog", + "ref": "v1.5.0", + "repo": "cl-prolog-kit", "type": "github" } }, @@ -325,11 +325,11 @@ "inputs": { "cl-nix-forge": "cl-nix-forge_3", "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "nixpkgs" ], "paredit-cli": [ - "cl-prolog", + "cl-prolog-kit", "paredit-cli" ], "treefmt-nix": "treefmt-nix_4" @@ -423,7 +423,7 @@ "inputs": { "crane": "crane", "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "nixpkgs" ], "rust-overlay": "rust-overlay", @@ -475,7 +475,7 @@ "cl-cli": "cl-cli", "cl-codec-kit": "cl-codec-kit", "cl-concurrent-kit": "cl-concurrent-kit", - "cl-dataflow": "cl-dataflow", + "cl-dataflow-kit": "cl-dataflow-kit", "cl-date-kit": "cl-date-kit", "cl-history-kit": "cl-history-kit", "cl-host-kit": "cl-host-kit", @@ -483,7 +483,7 @@ "cl-nix-forge": "cl-nix-forge", "cl-parser-kit": "cl-parser-kit", "cl-process-kit": "cl-process-kit", - "cl-prolog": "cl-prolog", + "cl-prolog-kit": "cl-prolog-kit", "cl-tty-kit": "cl-tty-kit", "cl-weave": "cl-weave_2", "nixpkgs": "nixpkgs", @@ -493,7 +493,7 @@ "rust-overlay": { "inputs": { "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "paredit-cli", "nixpkgs" ] @@ -578,7 +578,7 @@ "treefmt-nix_2": { "inputs": { "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "cl-nix-forge", "nixpkgs" ] @@ -600,17 +600,18 @@ "treefmt-nix_3": { "inputs": { "nixpkgs": [ + "cl-prolog-kit", "cl-weave", - "paredit-cli", + "cl-nix-forge", "nixpkgs" ] }, "locked": { - "lastModified": 1780220602, - "narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=", + "lastModified": 1784369104, + "narHash": "sha256-47cxbcZODibHv3rELFQ9vZly0vUNkND/atn/U7HLeb0=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "db947814a175b7ca6ded66e21383d938df01c227", + "rev": "df3c0640565d04a0261253cdd89fce78ec50168a", "type": "github" }, "original": { @@ -622,7 +623,7 @@ "treefmt-nix_4": { "inputs": { "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "cl-weave", "nixpkgs" ] @@ -644,7 +645,7 @@ "treefmt-nix_5": { "inputs": { "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "paredit-cli", "nixpkgs" ] @@ -666,7 +667,7 @@ "treefmt-nix_6": { "inputs": { "nixpkgs": [ - "cl-prolog", + "cl-prolog-kit", "nixpkgs" ] }, diff --git a/flake.nix b/flake.nix index c2a828d..98be884 100644 --- a/flake.nix +++ b/flake.nix @@ -20,16 +20,16 @@ }; # Sibling packages are ALWAYS pinned to a release tag. A bare - # `github:nerima-lisp/cl-prolog` follows that repo's default branch, which + # `github:nerima-lisp/cl-prolog-kit` follows that repo's default branch, which # means an upstream push to main breaks this repo's CI without warning. # - # cl-prolog and cl-weave are consumed as flakes, because nshell wants + # cl-prolog-kit and cl-weave are consumed as flakes, because nshell wants # cl-weave's built CLI for the dev shell and not only its source; both # therefore carry the mandatory `inputs.nixpkgs.follows`, without which # each would drag in its own nixpkgs, inflating flake.lock and rebuilding # the same derivations. - cl-prolog = { - url = "github:nerima-lisp/cl-prolog/v1.4.3"; + cl-prolog-kit = { + url = "github:nerima-lisp/cl-prolog-kit/v1.5.0"; inputs.nixpkgs.follows = "nixpkgs"; }; @@ -50,8 +50,8 @@ url = "github:nerima-lisp/cl-parser-kit/v1.1.1"; flake = false; }; - cl-dataflow = { - url = "github:nerima-lisp/cl-dataflow/v1.1.1"; + cl-dataflow-kit = { + url = "github:nerima-lisp/cl-dataflow-kit/v1.2.0"; flake = false; }; cl-boundary-kit = { @@ -116,10 +116,10 @@ self, nixpkgs, cl-nix-forge, - cl-prolog, + cl-prolog-kit, cl-weave, cl-parser-kit, - cl-dataflow, + cl-dataflow-kit, cl-host-kit, cl-boundary-kit, cl-cli, @@ -196,8 +196,8 @@ in rec { clProlog = sibling { - name = "cl-prolog"; - source = cl-prolog; + name = "cl-prolog-kit"; + source = cl-prolog-kit; }; clWeave = sibling { name = "cl-weave"; @@ -208,8 +208,8 @@ source = cl-parser-kit; }; clDataflow = sibling { - name = "cl-dataflow"; - source = cl-dataflow; + name = "cl-dataflow-kit"; + source = cl-dataflow-kit; dependencies = [ clProlog clConcurrentKit @@ -303,9 +303,9 @@ cp ${./LICENSE} "$out/LICENSE" cp ${ctx.pkgs.sbcl}/share/doc/sbcl/COPYING "$out/LICENSES/SBCL-COPYING" cp ${ctx.pkgs.zstd.src}/LICENSE "$out/LICENSES/ZSTD-LICENSE" - cp ${cl-prolog}/LICENSE "$out/LICENSES/CL-PROLOG-LICENSE" + cp ${cl-prolog-kit}/LICENSE "$out/LICENSES/CL-PROLOG-KIT-LICENSE" cp ${cl-parser-kit}/LICENSE "$out/LICENSES/CL-PARSER-KIT-LICENSE" - cp ${cl-dataflow}/LICENSE "$out/LICENSES/CL-DATAFLOW-LICENSE" + cp ${cl-dataflow-kit}/LICENSE "$out/LICENSES/CL-DATAFLOW-KIT-LICENSE" cp ${cl-host-kit}/LICENSE "$out/LICENSES/CL-HOST-KIT-LICENSE" cp ${cl-boundary-kit}/LICENSE "$out/LICENSES/CL-BOUNDARY-KIT-LICENSE" cp ${cl-cli}/LICENSE "$out/LICENSES/CL-CLI-LICENSE" @@ -361,9 +361,9 @@ # cl-weave is a dependency of `nshell/test` and `nshell/weave` only (see # nshell.asd), so it is a CHECK dependency: it must not enter the - # delivered binary's closure. cl-prolog/weave, which the nshell/weave + # delivered binary's closure. cl-prolog-kit/weave, which the nshell/weave # suite also loads, needs nothing extra -- it is a secondary system of - # cl-prolog, whose whole source tree is already on the registry above. + # cl-prolog-kit, whose whole source tree is already on the registry above. lispCheckDependencies = ctx: [ (siblingsFor ctx).clWeave ]; # Drives `checks.default`, `checks.weave` and `apps.test` from this one diff --git a/nshell.asd b/nshell.asd index ab38822..2775636 100644 --- a/nshell.asd +++ b/nshell.asd @@ -23,9 +23,9 @@ :homepage "https://github.com/nerima-lisp/nshell" :bug-tracker "https://github.com/nerima-lisp/nshell/issues" :source-control (:git "https://github.com/nerima-lisp/nshell.git") - :depends-on ("cl-prolog" + :depends-on ("cl-prolog-kit" "cl-parser-kit" - "cl-dataflow" + "cl-dataflow-kit" "cl-host-kit" "cl-boundary-kit" "cl-cli" @@ -422,9 +422,9 @@ :source-control (:git "https://github.com/nerima-lisp/nshell.git") :description "cl-weave regression suite for nshell: property-based, fixture, benchmark, -and cl-prolog-query coverage of the completion engine, complementing the +and cl-prolog-kit-query coverage of the completion engine, complementing the primary suite in nshell/test." - :depends-on ("nshell" "cl-weave" "cl-prolog" "cl-prolog/weave") + :depends-on ("nshell" "cl-weave" "cl-prolog-kit" "cl-prolog-kit/weave") :pathname "t" :serial t :components diff --git a/run-tests.lisp b/run-tests.lisp index f46d56c..51df9de 100644 --- a/run-tests.lisp +++ b/run-tests.lisp @@ -10,7 +10,7 @@ ;;;; Dependency resolution mirrors scripts/weave.lisp: inside `nix develop` or ;;;; the Nix sandbox the systems are already on CL_SOURCE_REGISTRY, and for a ;;;; plain ghq checkout the parent directory tree is registered so sibling -;;;; checkouts (../cl-weave, ../cl-prolog, ...) are found automatically. An +;;;; checkouts (../cl-weave, ../cl-prolog-kit, ...) are found automatically. An ;;;; explicit CL_SOURCE_REGISTRY still wins, because the existing configuration ;;;; is inherited rather than replaced. diff --git a/scripts/coverage.lisp b/scripts/coverage.lisp index 6646ae1..417d2dc 100644 --- a/scripts/coverage.lisp +++ b/scripts/coverage.lisp @@ -2,7 +2,7 @@ ;;;; ;;;; Usage: sbcl --script scripts/coverage.lisp ;;;; -;;;; nshell/test depends on sibling nerima-lisp toolkit checkouts (cl-prolog, +;;;; nshell/test depends on sibling nerima-lisp toolkit checkouts (cl-prolog-kit, ;;;; cl-parser-kit, ...). Inside `nix develop` those systems are already on the ;;;; ASDF source registry. For a plain local checkout we also register the ;;;; parent directory tree, so sibling ghq checkouts are discovered diff --git a/scripts/verify-release-bundle.pl b/scripts/verify-release-bundle.pl index a067137..a36b2be 100644 --- a/scripts/verify-release-bundle.pl +++ b/scripts/verify-release-bundle.pl @@ -15,9 +15,9 @@ LICENSE LICENSES/SBCL-COPYING LICENSES/ZSTD-LICENSE - LICENSES/CL-PROLOG-LICENSE + LICENSES/CL-PROLOG-KIT-LICENSE LICENSES/CL-PARSER-KIT-LICENSE - LICENSES/CL-DATAFLOW-LICENSE + LICENSES/CL-DATAFLOW-KIT-LICENSE LICENSES/CL-HOST-KIT-LICENSE LICENSES/CL-BOUNDARY-KIT-LICENSE LICENSES/CL-CLI-LICENSE diff --git a/scripts/weave.lisp b/scripts/weave.lisp index 4b72e99..05da621 100644 --- a/scripts/weave.lisp +++ b/scripts/weave.lisp @@ -2,10 +2,10 @@ ;;;; ;;;; Usage: sbcl --script scripts/weave.lisp ;;;; -;;;; Beyond cl-weave and cl-prolog, this suite also depends on cl-prolog/weave. +;;;; Beyond cl-weave and cl-prolog-kit, this suite also depends on cl-prolog-kit/weave. ;;;; Inside `nix develop` those systems are already on the ;;;; ASDF source registry. For a plain local checkout we also register the -;;;; parent directory tree, so sibling ghq checkouts (../cl-weave, ../cl-prolog) +;;;; parent directory tree, so sibling ghq checkouts (../cl-weave, ../cl-prolog-kit) ;;;; are discovered automatically. An explicit CL_SOURCE_REGISTRY still wins ;;;; because we inherit the existing configuration. diff --git a/src/application/pipeline-diagram.lisp b/src/application/pipeline-diagram.lisp index 25a3da1..027bf7a 100644 --- a/src/application/pipeline-diagram.lisp +++ b/src/application/pipeline-diagram.lisp @@ -1,20 +1,20 @@ ;;; Dataflow diagnostics: render shell pipelines and the job lifecycle through -;;; cl-dataflow. +;;; cl-dataflow-kit. ;;; ;;; nshell already models a pipeline as a linear PIPELINE-PLAN and a job as a -;;; small state machine embedded in the monitor. cl-dataflow provides a +;;; small state machine embedded in the monitor. cl-dataflow-kit provides a ;;; general computation-graph and state-machine toolkit with structural ;;; validation and deterministic DOT/Mermaid export. This module bridges the -;;; two: it translates a pipeline plan into a cl-dataflow graph (gaining free +;;; two: it translates a pipeline plan into a cl-dataflow-kit graph (gaining free ;;; acyclicity/wiring validation and visualization) and describes the job -;;; lifecycle as a cl-dataflow state machine for analysis and diagrams. +;;; lifecycle as a cl-dataflow-kit state machine for analysis and diagrams. ;;; ;;; Everything here is additive and read-only — no existing execution or job ;;; path is altered. The job-lifecycle machine is a *specification*, not a ;;; runtime enforcer: nshell's own JOB-STATE-TRANSITION remains authoritative. (in-package #:nshell.application) -;;; --- Pipeline plan -> cl-dataflow graph -------------------------------- +;;; --- Pipeline plan -> cl-dataflow-kit graph -------------------------------- (defun %pipeline-stage-node-name (index command) "Unique, human-readable node name for the stage at INDEX running COMMAND. @@ -22,19 +22,19 @@ The index prefix keeps duplicate command names (e.g. `a | a`) distinct." (format nil "~D:~A" index (nshell.domain.execution:command-name command))) (defun pipeline-plan->dataflow-graph (plan) - "Translate a nshell PIPELINE-PLAN into a cl-dataflow graph: one node per + "Translate a nshell PIPELINE-PLAN into a cl-dataflow-kit graph: one node per stage, one edge per producer->consumer pipe. Each node carries the stage's full command as :command metadata." - (let* ((graph (cl-dataflow:make-graph)) + (let* ((graph (cl-dataflow-kit:make-graph)) (commands (nshell.domain.execution:pipeline-plan-commands plan)) (names (loop for command in commands for index from 0 collect (%pipeline-stage-node-name index command)))) (loop for command in commands for name in names - do (cl-dataflow:add-node + do (cl-dataflow-kit:add-node graph - (cl-dataflow:make-node + (cl-dataflow-kit:make-node name :inputs '("value") :outputs '("value") @@ -42,19 +42,19 @@ full command as :command metadata." (nshell.domain.execution:command-to-list command))))) (loop for (from to) on names while to - do (cl-dataflow:add-edge graph from to + do (cl-dataflow-kit:add-edge graph from to :from-port "value" :to-port "value")) graph)) (defun pipeline-plan->dot (plan &key (name "pipeline")) "Render PLAN as a Graphviz DOT digraph string, validating its wiring first." (let ((graph (pipeline-plan->dataflow-graph plan))) - (cl-dataflow:validate-graph graph) - (cl-dataflow:graph->dot graph :name name))) + (cl-dataflow-kit:validate-graph graph) + (cl-dataflow-kit:graph->dot graph :name name))) (defun pipeline-plan->mermaid (plan &key (direction "LR")) "Render PLAN as a Mermaid flowchart string." - (cl-dataflow:graph->mermaid (pipeline-plan->dataflow-graph plan) + (cl-dataflow-kit:graph->mermaid (pipeline-plan->dataflow-graph plan) :direction direction)) ;;; --- Command line -> pipeline plan ------------------------------------- @@ -84,17 +84,17 @@ Returns NIL for input that is not a plain command or `|`-pipeline." (:error nil) (:empty nil))) -;;; --- Job lifecycle -> cl-dataflow state machine ------------------------ +;;; --- Job lifecycle -> cl-dataflow-kit state machine ------------------------ ;;; ;;; States and events mirror nshell's job model (job.lisp / monitor.lisp). -;;; cl-dataflow normalizes keyword states/events to upcased strings and matches +;;; cl-dataflow-kit normalizes keyword states/events to upcased strings and matches ;;; case-insensitively, so nshell's own keywords pass straight through. (defun job-lifecycle-machine () - "A cl-dataflow state machine describing the nshell job lifecycle. + "A cl-dataflow-kit state machine describing the nshell job lifecycle. Transitions correspond to the monitor's real state changes plus the terminal reap step (:completed -> :done)." - (cl-dataflow:define-state-machine (:initial-state :created) + (cl-dataflow-kit:define-state-machine (:initial-state :created) (:created :start :running) (:running :stop :stopped) (:stopped :continue :running) @@ -109,10 +109,10 @@ reap step (:completed -> :done)." (defun job-lifecycle-analysis () "Return a plist summarizing the job lifecycle machine's structure." (let ((machine (job-lifecycle-machine))) - (list :states (cl-dataflow:state-machine-states machine) - :terminal (cl-dataflow:state-machine-terminal-states machine) - :unreachable (cl-dataflow:state-machine-unreachable-states machine) - :deterministic (cl-dataflow:state-machine-deterministic-p machine)))) + (list :states (cl-dataflow-kit:state-machine-states machine) + :terminal (cl-dataflow-kit:state-machine-terminal-states machine) + :unreachable (cl-dataflow-kit:state-machine-unreachable-states machine) + :deterministic (cl-dataflow-kit:state-machine-deterministic-p machine)))) ;;; --- `pipeline-graph` builtin ------------------------------------------ diff --git a/src/domain/completion/knowledge-base.lisp b/src/domain/completion/knowledge-base.lisp index 563ec09..f4a1c85 100644 --- a/src/domain/completion/knowledge-base.lisp +++ b/src/domain/completion/knowledge-base.lisp @@ -1,6 +1,6 @@ (in-package #:nshell.domain.completion) -;;; Command completion data lives in a CL-PROLOG rulebase: KB-ADD-COMMAND and +;;; Command completion data lives in a CL-PROLOG-KIT rulebase: KB-ADD-COMMAND and ;;; friends assert COMMAND-REGISTERED/SUBCOMMAND-OF/HAS-FLAG/OPTION-VALUE/ ;;; EXCLUSIVE-GROUP/DESCRIBES facts, and three small rules derive COMPLETES ;;; from them so COMPLETE (engine.lisp) answers command, subcommand, and flag @@ -8,7 +8,7 @@ ;;; KNOWLEDGE-BASE is a RULE-KNOWLEDGE-BASE subtype so %COMPLETION-CANDIDATES ;;; (engine.lisp) can TYPECASE it ahead of the plain RULE-KNOWLEDGE-BASE that -;;; *BUILT-IN-RULE-KNOWLEDGE-BASE* uses -- both are CL-PROLOG rulebases under +;;; *BUILT-IN-RULE-KNOWLEDGE-BASE* uses -- both are CL-PROLOG-KIT rulebases under ;;; the hood, but they answer completion queries through different rule sets. (defstruct (knowledge-base (:include rule-knowledge-base))) @@ -23,7 +23,7 @@ kb)) (defun %kb-solution-values (kb goal variable) - (mapcar (lambda (solution) (cl-prolog:solution-binding variable solution)) + (mapcar (lambda (solution) (cl-prolog-kit:solution-binding variable solution)) (prove-all kb goal))) (defun %unique-string-values (values) @@ -89,8 +89,8 @@ (let ((values-by-option (make-hash-table :test #'equal)) (options nil)) (dolist (solution (prove-all kb (list 'option-value cmd-name '?option '?value))) - (let ((option (cl-prolog:solution-binding '?option solution)) - (value (cl-prolog:solution-binding '?value solution))) + (let ((option (cl-prolog-kit:solution-binding '?option solution)) + (value (cl-prolog-kit:solution-binding '?value solution))) (unless (nth-value 1 (gethash option values-by-option)) (push option options)) (push value (gethash option values-by-option)))) @@ -106,8 +106,8 @@ (remove-duplicates (loop for solution in (prove-all kb (list 'option-value-kind cmd-name '?option '?kind)) - for option = (cl-prolog:solution-binding '?option solution) - for kind = (cl-prolog:solution-binding '?kind solution) + for option = (cl-prolog-kit:solution-binding '?option solution) + for kind = (cl-prolog-kit:solution-binding '?kind solution) when (and (stringp option) (member kind '(:file :directory) :test #'eq)) collect (list option kind)) diff --git a/src/domain/completion/rule-data.lisp b/src/domain/completion/rule-data.lisp index ca9b132..49d7a0c 100644 --- a/src/domain/completion/rule-data.lisp +++ b/src/domain/completion/rule-data.lisp @@ -18,7 +18,7 @@ (&key (facts nil) (rules nil)))) (facts nil :type list) (rules nil :type list) - ;; Compiling FACTS/RULES into a CL-PROLOG:RULEBASE is O(count) -- cheap once, + ;; Compiling FACTS/RULES into a CL-PROLOG-KIT:RULEBASE is O(count) -- cheap once, ;; but COMPLETION-RULEBASE used to pay it on every PROVE call. A knowledge ;; base backing live completion accumulates hundreds of catalog facts and is ;; queried on every keystroke, so ASSERT-FACT!/ASSERT-RULE! invalidate this @@ -62,44 +62,44 @@ kb) (defun %make-prolog-fact (fact) - (cl-prolog:make-clause (list* (fact-predicate fact) (fact-args fact)))) + (cl-prolog-kit:make-clause (list* (fact-predicate fact) (fact-args fact)))) (defun %make-prolog-rule (rule) - (cl-prolog:make-clause + (cl-prolog-kit:make-clause (copy-tree (rule-head rule)) (copy-tree (rule-body rule)))) (defun completion-rulebase (kb) - "Compile the completion KB into a first-class CL-PROLOG:RULEBASE. + "Compile the completion KB into a first-class CL-PROLOG-KIT:RULEBASE. Every completion fact and rule becomes a Prolog clause, so the resulting -rulebase answers the full cl-prolog query API (QUERY-PROLOG, FINDALL, +rulebase answers the full cl-prolog-kit query API (QUERY-PROLOG, FINDALL, negation-as-failure, ...) over nshell's completion knowledge, not just the depth-bounded PROVE search used on the interactive path. Facts and rules are inserted in definition order (the KB accumulates them reversed via PUSH) so solution order stays stable for callers that depend on it." (or (rule-knowledge-base-%rulebase-cache kb) (setf (rule-knowledge-base-%rulebase-cache kb) - (let ((rulebase (cl-prolog:make-rulebase))) + (let ((rulebase (cl-prolog-kit:make-rulebase))) (dolist (fact (reverse (rule-knowledge-base-facts kb)) rulebase) - (cl-prolog:rulebase-insert-clause! rulebase (%make-prolog-fact fact))) + (cl-prolog-kit:rulebase-insert-clause! rulebase (%make-prolog-fact fact))) (dolist (rule (reverse (rule-knowledge-base-rules kb)) rulebase) - (cl-prolog:rulebase-insert-clause! rulebase (%make-prolog-rule rule))))))) + (cl-prolog-kit:rulebase-insert-clause! rulebase (%make-prolog-rule rule))))))) (defun %prove-rulebase (rulebase goal &optional (bindings '()) (max-depth *max-proof-depth*)) (declare (ignore bindings)) ;; Completion treats undefined predicates and depth limits as an empty path. (let ((solutions '())) (handler-case - (cl-prolog:map-prolog-solutions + (cl-prolog-kit:map-prolog-solutions (lambda (solution) (push solution solutions)) rulebase (copy-tree goal) :max-depth max-depth) - (cl-prolog:prolog-runtime-error () nil)) + (cl-prolog-kit:prolog-runtime-error () nil)) (nreverse solutions))) (defun prove (kb goal &optional (bindings '()) (max-depth *max-proof-depth*)) (declare (ignore bindings)) - ;; cl-prolog signals an ISO PROLOG-RUNTIME-ERROR (existence_error for a + ;; cl-prolog-kit signals an ISO PROLOG-RUNTIME-ERROR (existence_error for a ;; goal naming an undefined predicate, resource_error/PROLOG-DEPTH-LIMIT- ;; EXCEEDED past MAX-DEPTH, and so on) and unwinds QUERY-PROLOG's whole ;; search, discarding solutions already found on other branches. Standard @@ -112,10 +112,10 @@ solution order stays stable for callers that depend on it." (let ((rulebase (completion-rulebase kb)) (solutions '())) (handler-case - (cl-prolog:map-prolog-solutions + (cl-prolog-kit:map-prolog-solutions (lambda (solution) (push solution solutions)) rulebase (copy-tree goal) :max-depth max-depth) - (cl-prolog:prolog-runtime-error () nil)) + (cl-prolog-kit:prolog-runtime-error () nil)) (nreverse solutions))) (defun prove-all (kb goal &key (max-depth *max-proof-depth*)) diff --git a/src/package-domain.lisp b/src/package-domain.lisp index d1e6636..585fe8c 100644 --- a/src/package-domain.lisp +++ b/src/package-domain.lisp @@ -224,7 +224,7 @@ that is what keeps expansion testable without a disk.") (:documentation "Domain: the completion engine. Reads the cursor context out of a command line, consults a knowledge base of commands, subcommands, and flags, and answers -with ranked candidates. The interesting half is the cl-prolog rulebase: the +with ranked candidates. The interesting half is the cl-prolog-kit rulebase: the exported predicates below are goals callers may query directly.") (:use #:cl) (:import-from #:nshell.util #:define-value-struct #:string-prefix-p) @@ -242,8 +242,8 @@ exported predicates below are goals callers may query directly.") #:assert-fact! #:assert-rule! #:prove #:prove-all #:completion-rulebase ;; Completion logic predicates: the public vocabulary of the - ;; cl-prolog rulebase produced by COMPLETION-RULEBASE. Exporting - ;; the predicate symbols lets callers (and the cl-weave/cl-prolog + ;; cl-prolog-kit rulebase produced by COMPLETION-RULEBASE. Exporting + ;; the predicate symbols lets callers (and the cl-weave/cl-prolog-kit ;; query suites) write goals such as (completes "git" ?c) that ;; unify against the same interned symbols the rulebase stores. #:completes #:describes #:has-flag diff --git a/t/e2e/test-smoke.lisp b/t/e2e/test-smoke.lisp index ac904fb..9f2e0b1 100644 --- a/t/e2e/test-smoke.lisp +++ b/t/e2e/test-smoke.lisp @@ -35,14 +35,14 @@ merely been read. FIND-SYMBOL-by-string sidesteps this exactly as (cons "nshell" arguments))) (defparameter +nshell-runtime-dependencies+ - '(:cl-prolog :cl-parser-kit :cl-dataflow :cl-boundary-kit :cl-cli :cl-tty-kit + '(:cl-prolog-kit :cl-parser-kit :cl-dataflow-kit :cl-boundary-kit :cl-cli :cl-tty-kit :cl-process-kit :cl-history-kit :cl-host-kit ;; cl-log-kit is not an nshell dependency (see docs/nerima-lisp-package-audit.md) ;; but cl-boundary-kit and cl-process-kit both depend on it, and the ;; subprocess's central-registry holds only these explicit directories with ;; no :tree fallback, so it must be listed here to resolve transitively. :cl-log-kit - ;; Likewise not a direct nshell dependency: cl-dataflow depends on it. + ;; Likewise not a direct nshell dependency: cl-dataflow-kit depends on it. :cl-concurrent-kit) "Every external ASDF system nshell depends on at runtime, plus any transitive dependency needed to resolve them under an explicit :central-registry. The diff --git a/t/unit/test-completion-rule-prover-boundaries.lisp b/t/unit/test-completion-rule-prover-boundaries.lisp index d203b90..adc6d35 100644 --- a/t/unit/test-completion-rule-prover-boundaries.lisp +++ b/t/unit/test-completion-rule-prover-boundaries.lisp @@ -1,11 +1,11 @@ (in-package #:nshell/test) -(cl-prolog:define-foreign-predicate (test-builtin-true) +(cl-prolog-kit:define-foreign-predicate (test-builtin-true) (rulebase environment depth emit) (declare (ignore rulebase depth)) (funcall emit environment)) -(cl-prolog:define-foreign-predicate (test-builtin-string= a b) +(cl-prolog-kit:define-foreign-predicate (test-builtin-string= a b) (rulebase environment depth emit) (declare (ignore rulebase depth)) (when (and (stringp a) (stringp b) (string= a b)) diff --git a/t/unit/test-pipeline-diagram.lisp b/t/unit/test-pipeline-diagram.lisp index ef737ae..580d807 100644 --- a/t/unit/test-pipeline-diagram.lisp +++ b/t/unit/test-pipeline-diagram.lisp @@ -1,17 +1,17 @@ (in-package #:nshell/test) -;;; Tests for the cl-dataflow diagnostics module (src/application/pipeline-diagram): -;;; pipeline plans translated into cl-dataflow graphs, and the job lifecycle -;;; described as a cl-dataflow state machine. +;;; Tests for the cl-dataflow-kit diagnostics module (src/application/pipeline-diagram): +;;; pipeline plans translated into cl-dataflow-kit graphs, and the job lifecycle +;;; described as a cl-dataflow-kit state machine. (defun %diagram-node-names (graph) - (cl-dataflow:graph-node-names graph)) + (cl-dataflow-kit:graph-node-names graph)) (defun %diagram-source-names (graph) - (mapcar #'cl-dataflow:node-name (cl-dataflow:graph-source-nodes graph))) + (mapcar #'cl-dataflow-kit:node-name (cl-dataflow-kit:graph-source-nodes graph))) (defun %diagram-sink-names (graph) - (mapcar #'cl-dataflow:node-name (cl-dataflow:graph-sink-nodes graph))) + (mapcar #'cl-dataflow-kit:node-name (cl-dataflow-kit:graph-sink-nodes graph))) (describe "pipeline-diagram-tests" (it "pipeline-plan-translates-to-linear-dataflow-graph" @@ -22,21 +22,21 @@ (expect '("0:a") :to-equal (%diagram-source-names graph)) (expect '("2:c") :to-equal (%diagram-sink-names graph)) ;; A well-wired linear pipeline is a valid, acyclic dataflow graph. - (expect (cl-dataflow:validate-graph graph) :to-be-truthy))) + (expect (cl-dataflow-kit:validate-graph graph) :to-be-truthy))) (it "pipeline-plan-keeps-duplicate-commands-distinct" "Repeated command names stay separate nodes via the stage-index prefix." (let* ((plan (nshell.application::%command-line->pipeline-plan "a | a | a")) (graph (nshell.application::pipeline-plan->dataflow-graph plan))) (expect '("0:a" "1:a" "2:a") :to-equal (%diagram-node-names graph)) - (expect (cl-dataflow:validate-graph graph) :to-be-truthy))) + (expect (cl-dataflow-kit:validate-graph graph) :to-be-truthy))) (it "single-command-pipeline-has-one-node-and-no-edges" "A bare command produces a one-node graph." (let* ((plan (nshell.application::%command-line->pipeline-plan "ls -la")) (graph (nshell.application::pipeline-plan->dataflow-graph plan))) (expect '("0:ls") :to-equal (%diagram-node-names graph)) - (expect (null (cl-dataflow:graph-edges graph)) :to-be-truthy))) + (expect (null (cl-dataflow-kit:graph-edges graph)) :to-be-truthy))) (it "pipeline-graph-builtin-renders-dot" "The pipeline-graph builtin returns exit 0 and DOT naming every stage." @@ -91,5 +91,5 @@ guarding the spec against runtime drift." ("BACKGROUND" "FOREGROUND") ("RUNNING" "EXIT"))) (destructuring-bind (state event) transition - (expect (cl-dataflow:state-machine-transition-for machine state event) + (expect (cl-dataflow-kit:state-machine-transition-for machine state event) :to-be-truthy)))))) diff --git a/t/weave/completion-advanced.lisp b/t/weave/completion-advanced.lisp index 9b9f98e..b85b06d 100644 --- a/t/weave/completion-advanced.lisp +++ b/t/weave/completion-advanced.lisp @@ -1,4 +1,4 @@ -;;;; Advanced cl-prolog usage over nshell's real completion knowledge. +;;;; Advanced cl-prolog-kit usage over nshell's real completion knowledge. ;;;; ;;;; These cases go past yes/no proof search: aggregation with findall, ;;;; negation-as-failure, solution ordering, and a Lisp foreign predicate @@ -6,7 +6,7 @@ (in-package #:nshell/weave) -(describe "completion knowledge via advanced cl-prolog" +(describe "completion knowledge via advanced cl-prolog-kit" (it "aggregates every completes/2 solution into one list with findall" (let* ((rulebase (built-in-rulebase)) diff --git a/t/weave/completion-logic.lisp b/t/weave/completion-logic.lisp index 0eaebe5..f2fcbb6 100644 --- a/t/weave/completion-logic.lisp +++ b/t/weave/completion-logic.lisp @@ -1,4 +1,4 @@ -;;;; The cl-prolog/weave bridge: nshell's completion rules asserted as +;;;; The cl-prolog-kit/weave bridge: nshell's completion rules asserted as ;;;; declarative query cases. deftest-queries expands each spec into an ;;;; independent cl-weave `it`, rebuilding the rulebase per case so no test ;;;; leaks state into the next. diff --git a/t/weave/logic-crosscheck.lisp b/t/weave/logic-crosscheck.lisp index 3419f53..046d48c 100644 --- a/t/weave/logic-crosscheck.lisp +++ b/t/weave/logic-crosscheck.lisp @@ -1,6 +1,6 @@ ;;;; cl-weave ships its own small logic engine (logic-program / logic-run). ;;;; Here we model a slice of nshell's completion rules in *that* engine and -;;;; confirm it derives the same answers cl-prolog does for the production +;;;; confirm it derives the same answers cl-prolog-kit does for the production ;;;; rulebase -- a cross-check of two independent solvers against one intent. (in-package #:nshell/weave) @@ -19,7 +19,7 @@ (it "resolves a rule the way suggests-dir does in the rulebase" ;; Mirror ((suggests-dir ?input) (command-is ?input "cd")) as a cl-weave - ;; logic rule and confirm the derived binding matches cl-prolog's answer. + ;; logic rule and confirm the derived binding matches cl-prolog-kit's answer. (let* ((program (logic-program (:command-is "cd" "cd") (:- (:suggests-dir ?input) (:command-is ?input "cd")))) diff --git a/t/weave/package.lisp b/t/weave/package.lisp index 46edbaa..76060e6 100644 --- a/t/weave/package.lisp +++ b/t/weave/package.lisp @@ -5,10 +5,10 @@ ;;;; ;;;; * cl-weave -- describe/it/expect, property-based testing, fixtures, ;;;; benchmarks, and cl-weave's own embedded logic engine. -;;;; * cl-prolog -- nshell's completion knowledge base compiled into a -;;;; first-class cl-prolog:rulebase and queried with the +;;;; * cl-prolog-kit -- nshell's completion knowledge base compiled into a +;;;; first-class cl-prolog-kit:rulebase and queried with the ;;;; full engine API (query-prolog, findall, negation-as- -;;;; failure, foreign predicates), plus the cl-prolog/weave +;;;; failure, foreign predicates), plus the cl-prolog-kit/weave ;;;; bridge (deftest-queries / assert-query). ;;;; ;;;; Predicate symbols such as COMPLETES are imported from @@ -29,11 +29,11 @@ #:gen-such-that #:gen-list #:logic-program #:logic-run #:run-all) - ;; The cl-prolog/weave bridge: declarative query cases as cl-weave tests. - (:import-from #:cl-prolog/weave + ;; The cl-prolog-kit/weave bridge: declarative query cases as cl-weave tests. + (:import-from #:cl-prolog-kit/weave #:deftest-queries #:assert-query) - ;; Raw cl-prolog engine surface for the advanced query tests. - (:import-from #:cl-prolog + ;; Raw cl-prolog-kit engine surface for the advanced query tests. + (:import-from #:cl-prolog-kit #:query-prolog #:query-prolog-first #:prolog-succeeds-p #:solution-binding #:make-rulebase #:make-clause #:rulebase-insert-clause! diff --git a/t/weave/support.lisp b/t/weave/support.lisp index 8377b24..97d8af3 100644 --- a/t/weave/support.lisp +++ b/t/weave/support.lisp @@ -11,7 +11,7 @@ Referenced through the internal symbol on purpose: the suite verifies the nshell.domain.completion::*built-in-rule-knowledge-base*) (defun built-in-rulebase () - "Compile the built-in completion KB into a fresh cl-prolog:rulebase." + "Compile the built-in completion KB into a fresh cl-prolog-kit:rulebase." (completion-rulebase (built-in-rule-kb))) (defun query-values (rulebase goal variable &key (max-depth 64)) From 840cb0861306e784caa15b64ec2baa088fd7ca11 Mon Sep 17 00:00:00 2001 From: takeokunn Date: Mon, 17 Aug 2026 22:27:12 +0900 Subject: [PATCH 2/4] fix(nix): point mkExecutable at src/nshell The nshell-0.4.0 derivation failed with "ASDF program-op did not create executable nshell" even though the build itself succeeded. cl-nix-forge's mkExecutable defaults to looking for the dumped image at $out/, i.e. $out/nshell, but ASDF's :build-pathname "nshell" resolves relative to this system's own :pathname "src", so program-op writes it to $out/src/nshell -- confirmed by the fixupPhase RPATH-shrink log naming that exact path. Setting programPath explicitly is what mkExecutable's own docstring says to do at this boundary. This failure predates the rename: main's CI has been red on the same derivation since 2026-08-10. --- flake.nix | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/flake.nix b/flake.nix index 98be884..3edba5b 100644 --- a/flake.nix +++ b/flake.nix @@ -384,8 +384,20 @@ # image -- its `source` builtin reads shell scripts, and no code path # loads an ASDF system at run time -- so shipping the source closure # beside the binary would buy nothing and cost the whole closure. + # + # `programPath = "src/nshell"`: cl-nix-forge's `mkExecutable` defaults + # to checking `$out/` (i.e. `$out/nshell`) for the dumped + # image, but ASDF's `:build-pathname "nshell"` resolves relative to + # this system's own `:pathname "src"`, so `program-op` actually writes + # it to `$out/src/nshell` -- confirmed by the `fixupPhase` RPATH-shrink + # log naming that exact path. Left at the default, `mkExecutable` + # looks in the wrong place and fails with "ASDF program-op did not + # create executable nshell" even though the build succeeded; this is + # exactly the ASDF-specific detail `programPath`'s own docstring in + # cl-nix-forge says to make explicit at this boundary. executable = { installSource = false; + programPath = "src/nshell"; }; # docs/mkdocs.yml + docs/src/, built with `--strict` so a broken link or From 1177b17d9c8fe365718442023253037fe1092942 Mon Sep 17 00:00:00 2001 From: takeokunn Date: Mon, 17 Aug 2026 23:04:49 +0900 Subject: [PATCH 3/4] fix(test): resolve process-substitution and command -v test fixtures via PATH Two e2e tests hardcoded host-only absolute paths (/usr/bin/printf, /bin/echo) to force nshell to spawn a genuine external process instead of dispatching to its own builtin of the same name (echo and printf are both nshell builtins, and a bare name always resolves to the builtin ahead of PATH -- see resolve-command-path). Darwin's sandbox-exec profile and the non-sandboxed integration-test dev shell both expose /usr/bin and /bin, so this worked there, but the fully-sandboxed x86_64-linux Nix build used by the "nix flake check" CI job grants no host filesystem visibility beyond declared build inputs, so those paths do not exist and command resolution correctly reported exit 127 / "not found". These tests could not run against a real build until today, since the nshell-0.4.0 derivation itself failed to build until the mkExecutable output-path fix landed, so this is now-exposed rather than newly broken. Resolve the target binary through nshell.domain.completion:command-path-candidates against the real PATH the spawned nshell subprocess inherits, the same mechanism nshell itself uses to resolve external commands, instead of guessing a host path. --- t/e2e/test-smoke-script.lisp | 21 +++++++++++++-------- t/e2e/test-smoke.lisp | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/t/e2e/test-smoke-script.lisp b/t/e2e/test-smoke-script.lisp index 89d065d..4e73e3e 100644 --- a/t/e2e/test-smoke-script.lisp +++ b/t/e2e/test-smoke-script.lisp @@ -115,9 +115,11 @@ (it "e2e-main-command-expands-process-substitution" "The -c command path materializes input process substitutions." - (%assert-nshell-main-result '("-c" "cat <(/usr/bin/printf process-ok)") - "process-ok" - 0)) + (%assert-nshell-main-result + (list "-c" (format nil "cat <(~a process-ok)" + (%resolve-real-external-executable "printf"))) + "process-ok" + 0)) (it "e2e-main-command-expands-output-process-substitution" "The -c command path materializes output process substitutions." @@ -301,11 +303,14 @@ (it "e2e-main-command-resolves-builtin-function-and-path" "The command builtin reports builtin, function, and external resolutions." - (%assert-nshell-main-result - '("-c" - "function greet; echo function-body; end; command -v echo; command -v greet; command -V greet; command -v /bin/echo; command greet") - '("echo" "greet" "greet is a function" "/bin/echo" "function-body") - 0)) + (let ((real-echo (%resolve-real-external-executable "echo"))) + (%assert-nshell-main-result + (list "-c" + (format nil + "function greet; echo function-body; end; command -v echo; command -v greet; command -V greet; command -v ~a; command greet" + real-echo)) + (list "echo" "greet" "greet is a function" real-echo "function-body") + 0))) (it "e2e-main-eval-runs-in-the-current-context" "The eval builtin parses one command string and keeps its environment changes." diff --git a/t/e2e/test-smoke.lisp b/t/e2e/test-smoke.lisp index 9f2e0b1..1cbff51 100644 --- a/t/e2e/test-smoke.lisp +++ b/t/e2e/test-smoke.lisp @@ -65,6 +65,27 @@ central registry, exactly as the parent process resolved them.") collect (format nil "(pushnew (truename ~S) asdf:*central-registry* :test #'equal)" dependency-root))))) +(defun %executable-on-path-p (path) + (ignore-errors + (not (zerop (logand (sb-posix:stat-mode (sb-posix:stat path)) #o111))))) + +(defun %resolve-real-external-executable (name) + "Resolve NAME to an absolute path on the real host PATH, for e2e tests that +must invoke a genuine external binary rather than nshell's own builtin of the +same name -- a bare NAME always dispatches to the builtin (builtins take +priority over PATH; see NSHELL.APPLICATION:RESOLVE-COMMAND-PATH), so only an +absolute path, which bypasses builtin lookup entirely, can force the +external one. A path hardcoded to a host location such as /usr/bin or /bin +assumes filesystem visibility that a fully-sandboxed Nix Linux build does not +grant, unlike Darwin's sandbox-exec profile or a non-sandboxed dev shell; +searching the same PATH the spawned nshell subprocess inherits works in +every environment CI actually builds in." + (or (first (nshell.domain.completion:command-path-candidates + name + (or (sb-ext:posix-getenv "PATH") "") + #'%executable-on-path-p)) + (error "e2e test setup: ~a not found on PATH" name))) + (defun %run-nshell-main (arguments &key input) (let* ((root (asdf:system-source-directory :nshell)) (program (append (list (current-sbcl-executable) From 3cb1263bbef997d6e531a1a04e1a1a1979ed6321 Mon Sep 17 00:00:00 2001 From: takeokunn Date: Tue, 18 Aug 2026 04:04:31 +0900 Subject: [PATCH 4/4] fix(nix): restore the portable Linux release bundle 3252dfb dropped `packages.releaseBundle` has pointed at `deliveryFor`'s thin `ctx.executable.overrideAttrs` wrapper since the "Merge public readiness tooling" merge commit 3252dfb (2026-08-08). That merge kept parent 2's (e014d9b) `scripts/verify-release-bundle.pl` verbatim but discarded that same commit's ~130-line `releaseBundle` derivation -- the one that actually produced the `libexec/nshell` + relocated `lib/*.so` + glibc-interpreter layout the checker asserts -- in favour of parent 1's simpler `deliveryFor`. `deliveryFor`'s `$out/bin/nshell` is a `makeWrapper` script that execs a Lisp core through this machine's own Nix store and cannot run anywhere else, so `build release binary` (ci.yml, ubuntu-latest) has failed with "missing Linux release file: libexec/nshell" on every run since, masked until today by two earlier, unrelated breaks in the same job (a stale flake.lock dependency and `mkExecutable`'s `programPath` default, fixed on this branch by 840cb08). Restores e014d9b's derivation as `releaseBundleFor`, adapted to read the dumped image from `${ctx.executable}/bin/nshell.cl-nix-forge-unwrapped` (cl-nix-forge v0.5.0's own internal path for the `program-op` output, since `ctx.package` predates that dump) instead of the old bespoke `mkNshell` derivation, and reusing `deliveryFor`'s README/LICENSE/man-page installation instead of repeating it a second time. Linux only: SBCL on Darwin takes `mkExecutable`'s documented `.core`-plus-wrapper fallback, which has no Mach-O binary to relocate, and `build release binary` has never run on Darwin (ci.yml deleted its macos-14 leg outright, not merely disabled it) -- so `releaseBundleFor` falls back to `deliveryFor` there, matching what already built successfully pre-fix, rather than inventing an unverified Darwin bundling scheme. Also fixes `scripts/verify-release-bundle.pl`'s Nix-store-reference scan: `File::Find::find` only follows a symlink it meets while descending, and given one as its own root -- exactly what `result` is, and what both ci.yml and this script's own usage line pass it as -- it visits that one entry and never opens the directory it points to, so the scan has silently covered zero files under every invocation anyone has actually run. Resolved with `Cwd::abs_path` before the walk; confirmed live on this machine's own (non-portable, Darwin-fallback) build, which now correctly fails the check it always should have failed. --- flake.nix | 139 ++++++++++++++++++++++++++++++- scripts/verify-release-bundle.pl | 11 ++- 2 files changed, 146 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 3edba5b..c53e4d9 100644 --- a/flake.nix +++ b/flake.nix @@ -319,6 +319,136 @@ cp ${./man/nshell.1} "$out/share/man/man1/nshell.1" ''; }); + + # `packages.releaseBundle`: a relocatable artifact for users without + # Nix, as opposed to `deliveryFor`'s `$out/bin/nshell`, which is a + # `makeWrapper` script that execs a Lisp core through paths under the + # Nix store that built it and cannot run anywhere else. + # `scripts/verify-release-bundle.pl` is this function's other half -- + # it was introduced alongside the derivation this restores (see the + # 2026-08-08 "add public readiness tooling" history) and every check + # it makes on Linux (no `/nix/store` byte sequence anywhere in the + # bundle, a real ELF interpreter, a license file for every runtime + # library actually shipped) is a property this build establishes. A + # later merge kept the checker and silently dropped the derivation + # that satisfied it, which is what this restores; it was never + # exercised by CI even before that (docs/src/project/public-readiness.md + # still records Linux release evidence as outstanding), so treat this + # port as unverified until `build release binary` (ci.yml, ubuntu-latest + # only) is green on it. + # + # Linux only: cl-nix-forge's `mkExecutable` (v0.5.0, + # lib/batteries/app.nix) falls back, for SBCL on Darwin, to a bare + # non-executable `.core` plus a `sbcl --core` wrapper -- there is no + # Mach-O `nshell` binary on that path to relocate the way the Linux + # branch below relocates one, and `ci.yml`'s "build release binary" + # job runs on `ubuntu-latest` only (its own comment records that the + # macos-14 leg was deliberately deleted, not merely disabled). So a + # portable Darwin bundle has no gate proving it right, and `delivery` + # -- unconditionally buildable on every system `mkExecutable` supports + # -- keeps `nix build .#releaseBundle` working on the development + # machine, the property cedf775 restored deliberately, without + # asserting a portability claim `scripts/verify-release-bundle.pl` + # would reject on Darwin and nothing exercises there. + releaseBundleFor = + ctx: + let + pkgs = ctx.pkgs; + delivery = deliveryFor ctx; + in + if !pkgs.stdenv.isLinux then + delivery + else + let + # `${ctx.executable}/bin/nshell.cl-nix-forge-unwrapped` -- not + # `ctx.package` -- is the dumped, `:compression t` image: + # `ctx.package` is the plain ASDF system build, without the + # `program-op` dump `mkExecutable` performs internally before + # wrapping it. That internal build writes the image to + # `$out/` and then `mv`s it to this exact + # `.cl-nix-forge-unwrapped` path before installing the + # wrapper in its place -- an internal naming convention, not a + # published contract, so this coupling breaks silently on a + # cl-nix-forge upgrade; re-read `mkExecutable` in app.nix if + # this derivation starts failing right after one. + builtImage = "${ctx.executable}/bin/nshell.cl-nix-forge-unwrapped"; + in + pkgs.runCommand "nshell-${ctx.version}-release-${ctx.system}" + { + nativeBuildInputs = [ + pkgs.perl + pkgs.binutils + pkgs.patchelf + ]; + } + '' + mkdir -p $out/bin $out/libexec $out/lib + cp -R ${delivery}/README.md ${delivery}/LICENSE ${delivery}/LICENSES ${delivery}/share $out/ + + cp ${builtImage} $out/libexec/nshell + patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 \ + --set-rpath '$ORIGIN/../lib' $out/libexec/nshell + cp -L ${pkgs.stdenv.cc.libc}/lib/ld-linux-x86-64.so.2 $out/lib/ + printf '%s\n' $out/libexec/nshell > $out/.elf-queue + while IFS= read -r object; do + for needed in $(patchelf --print-needed "$object"); do + if [ -e "$out/lib/$needed" ]; then + continue + fi + dependency= + for directory in \ + ${pkgs.stdenv.cc.libc}/lib \ + ${pkgs.zstd.out}/lib \ + ${pkgs.stdenv.cc.cc.lib}/lib; do + if [ -e "$directory/$needed" ]; then + dependency="$directory/$needed" + break + fi + done + if [ -z "$dependency" ]; then + echo "unsupported release dependency: $needed (needed by $object)" >&2 + exit 1 + fi + cp -L "$dependency" "$out/lib/$needed" + printf '%s\n' "$out/lib/$needed" >> $out/.elf-queue + done + done < $out/.elf-queue + rm $out/.elf-queue + tar -xf ${pkgs.glibc.src} + cp glibc-*/COPYING.LIB $out/LICENSES/GLIBC-COPYING.LIB + tar -xf ${pkgs.stdenv.cc.cc.src} + cp gcc-*/COPYING3 $out/LICENSES/GCC-COPYING3 + cp gcc-*/COPYING.RUNTIME $out/LICENSES/GCC-RUNTIME-LIBRARY-EXCEPTION + cat > $out/bin/nshell <<'EOF' + #!/bin/sh + case "$0" in + /*) self="$0" ;; + */*) self="$PWD/$0" ;; + *) self="$(command -v "$0")" ;; + esac + while [ -L "$self" ]; do + directory="$(CDPATH= cd -- "''${self%/*}" && pwd)" + target="$(readlink "$self")" + case "$target" in + /*) self="$target" ;; + *) self="$directory/$target" ;; + esac + done + root="$(CDPATH= cd -- "''${self%/*}/.." && pwd)" + exec "$root/lib/ld-linux-x86-64.so.2" \ + --library-path "$root/lib" --argv0 "$0" \ + "$root/libexec/nshell" "$@" + EOF + + # SBCL records source locations in its appended core. Dynamic + # dependencies have already been made relative above, so only + # these non-runtime metadata strings remain. Keep the prefix + # length unchanged to preserve binary offsets and layouts. + find $out -type f -exec \ + perl -0777 -pi -e 's{/nix/store/}{/non/store/}g' {} + + chmod +x $out/bin/nshell $out/libexec/nshell $out/lib/ld-linux-x86-64.so.2 + perl ${./scripts/verify-release-bundle.pl} $out --no-smoke + ''; in # `mkPackageFlake` spans systems -- it obtains a `pkgs` and its own # cl-nix-forge instance per entry in `systems` -- so the per-system `lib` @@ -475,9 +605,12 @@ { # The release workflows use an explicit artifact name while the # contributor-facing default package remains unchanged. This is an - # additive output, so it belongs in extraOutputs and reuses the - # exact delivery derivation and man-page installation. - packages.releaseBundle = delivery; + # additive output, so it belongs in extraOutputs. Unlike + # `packages.default` (`delivery`, a Nix-store-relative wrapper), + # `releaseBundle` is `releaseBundleFor`'s relocatable, portable + # repackaging of the same dumped image -- see its definition for + # why the two cannot be the same derivation. + packages.releaseBundle = releaseBundleFor ctx; checks = { # The focused cl-weave completion suite (nshell/weave), through the diff --git a/scripts/verify-release-bundle.pl b/scripts/verify-release-bundle.pl index a36b2be..ffc2454 100644 --- a/scripts/verify-release-bundle.pl +++ b/scripts/verify-release-bundle.pl @@ -1,6 +1,7 @@ #!/usr/bin/env perl use strict; use warnings; +use Cwd qw(abs_path); use File::Find qw(find); use File::Basename qw(basename dirname); use File::Spec; @@ -36,6 +37,14 @@ die "bin/nshell is not executable\n" unless -x "$bundle/bin/nshell"; my @store_references; +# `abs_path`, not `$bundle` directly: `nix build`'s `result` is a symlink to +# the store path, and File::Find only follows a symlink it meets while +# descending -- given one as its OWN starting point, it visits that single +# entry and never opens the directory it points to. Every check below this +# point that uses `-f "$bundle/..."` or `glob "$bundle/..."` is a plain +# string test the OS resolves through the symlink, so this was the only +# scan silently visiting nothing under the exact `... result` invocation +# ci.yml (and this script's own usage line) documents. find( sub { return unless -f $_; @@ -44,7 +53,7 @@ my $contents = <$fh>; push @store_references, $File::Find::name if $contents =~ m{/nix/store/}; }, - $bundle, + abs_path($bundle), ); die "Nix store reference in release bundle:\n " . join("\n ", @store_references) . "\n" if @store_references;