diff --git a/experimental/user-dirs/starptr.andref.app/plans/silverwood-cli-spec-views.md b/experimental/user-dirs/starptr.andref.app/plans/silverwood-cli-spec-views.md new file mode 100644 index 0000000..2027994 --- /dev/null +++ b/experimental/user-dirs/starptr.andref.app/plans/silverwood-cli-spec-views.md @@ -0,0 +1,172 @@ +# Silverwood CLI spec views + +## Follow-up: indented output + +The existing scripts and named apps now print indented text. Both scripts and +apps reject arguments. The JSON packages described below remain available. + +A shared `indented_commands` renderer in `CLI_SPEC-views.jq` consumes each JSON +projection. It puts positionals inline (`` when required, `[NAME]` when +optional, and `ARG` when the semantic name is absent). The intent view prints +prose as indented `#` comments, labels positional intents with their placeholder, +and uses a `subcommands:` heading for groups that carry an intent. + +Nix builds cached `view.txt` artifacts with pinned `jq -r`, exposed as +`cli-spec-commands-positionals-text` and +`cli-spec-commands-positionals-intent-text`. The existing apps print those text +artifacts. The remainder of this document records the original JSON packaging +plan and its source-filtering adjustment. + +## Goal + +Provide executable `.sh` files that print readable JSON projections of +`experimental/silverwood/CLI_SPEC.jsonnet`, regardless of the caller's working +directory. Nix supplies pinned dependencies and caches the generated views. +Users invoke the scripts directly; each script invokes a named `nix run` app. + +Initial entry points: + +- `experimental/silverwood/view-commands-positionals.cmd.sh` +- `experimental/silverwood/view-commands-positionals-intent.cmd.sh` + +## Current groundwork + +The working copy already contains: + +- `CLI_SPEC-views.jq`, with `command_positionals` and + `commands_positionals_intent` functions and a shared recursive projection. +- Two executable wrappers that locate the spec and jq module relative to their + own files, then invoke Jsonnet and jq from `PATH`. +- `pkgs.jq` in Silverwood's development shell. +- Documentation showing invocation through `nix develop`. + +Both projections have been exercised with Nix-provided tools from outside the +repository. The remaining work is to package the generated JSON, expose apps, +and update the wrappers and documentation. + +## View semantics + +Keep both views in the shared jq module and preserve the source's nested shape: + +- Both retain command names and `subcommands.choices`, recursively. +- Both retain positional arguments, including their full `domain` objects and + explicit `required` values. +- The intent view additionally retains `intentHint` on commands, positionals, + and subcommand groups. +- Options and `generatedDescriptionHint` are omitted from these two views. +- Omitted fields remain omitted. The views do not materialize defaults or + change the spec's meaning; positional arguments still default to required. +- Preserve array order and JSON value types. + +Future views can add functions to this module and use the same Nix packaging +helper. The initial implementation covers the two agreed views. + +## Nix architecture + +Implement the view targets in `experimental/silverwood/flake.nix` for every +system already supported by the flake. + +### Build the JSON artifacts + +1. Construct a narrow source containing `CLI_SPEC.jsonnet` and + `CLI_SPEC-views.jq`. Preserve their filenames so jq's + `include "CLI_SPEC-views"` resolves correctly. Keep these inputs independent + of the Rust source filter and Cargo artifacts. +2. Add a derivation that evaluates the spec with the flake's pinned + `pkgs.go-jsonnet`, writing the result to `$out/spec.json`. +3. Add a small helper that projects that evaluated JSON using pinned `pkgs.jq` + and a selected function in the shared module. Each projection produces + `$out/view.json`. +4. Expose these artifact packages: + + - `packages..cli-spec-json` + - `packages..cli-spec-commands-positionals-json` + - `packages..cli-spec-commands-positionals-intent-json` + +The two projections share the evaluated spec artifact. Nix caches each output +using its declared inputs. Changes to the spec, query, or relevant pinned tools +produce new outputs. View builds must not depend on compiling Silverwood or +preparing its Rust development environment. + +The current Jsonnet file has no imports. If it gains imports later, include +those files in the declared source inputs as well. + +### Expose executable apps + +Add these named flake apps: + +- `apps..view-commands-positionals` +- `apps..view-commands-positionals-intent` + +Each app is a small Nix-generated executable that prints its corresponding +cached `view.json`, using an absolute store path to `cat`. Running an app prints +the generated JSON to stdout. Nix progress and errors remain on stderr, and +failures propagate as nonzero exit codes. + +This separates the cached data artifact from the operation of displaying it: +Nix builds the JSON, the app prints it, and the repository wrapper invokes the +app. The apps must be usable independently through `nix run`. + +## Shell wrappers + +Replace each wrapper's Jsonnet/jq pipeline with `exec nix run`, selecting the +matching app in the flake beside the script. For example: + +```sh +#!/usr/bin/env bash +set -euo pipefail + +script_dir="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +exec nix run "$script_dir#view-commands-positionals" +``` + +Keep both wrappers executable. Resolve the flake through the script's absolute +directory and quote paths. Use an absolute local flake reference so Nix uses +Git's source filtering in a checkout, including uncommitted edits to tracked +files and excluding ignored build artifacts. Changes to the spec or query must +be visible without requiring a commit. New source files must be tracked first. + +Implementation adjustment: validation showed that an explicit `path:` reference +also copies the ignored 5.9 GB Cargo `target/` directory into the Nix store and +can exhaust disk space. The absolute local reference avoids this while retaining +the current working tree's tracked content. Outside Git it uses the local path. + +Invoking a wrapper by its absolute path, by a relative path, or through its +directory on `PATH` must work without first changing directories. It requires +Nix and Bash; Jsonnet and jq come from the flake. No development-shell command +is part of this workflow. + +## Documentation + +Update the spec-view section of `experimental/silverwood/DESIGN.md` to show +direct script invocation and describe the two projections. Include an example +of invoking a wrapper by path from another directory and the equivalent named +`nix run` app. + +Explain that the view is generated from the current spec, with pinned tools, +and cached by Nix. Remove `nix develop` from the view instructions. The existing +development-shell tools may remain available for editing and debugging queries. + +## Validation and acceptance + +1. Build both JSON artifact targets and run both named apps. Confirm stdout is + valid JSON and each app prints its corresponding artifact exactly. +2. Run both repository wrappers from Silverwood's directory, the repository + root, and an unrelated temporary directory. Confirm identical output and no + `result` symlink or generated view file in the caller's directory. +3. Check representative branches: `session run` retains its two ordered + positionals, and `new` retains the subcommand group's intent in the intent + view. Confirm options and generated descriptions are omitted, and all + `intentHint` fields are omitted in the view without intents. +4. Exercise small fixture inputs covering omitted child lists, an explicit + `required: false`, and intent hints on subcommand groups and positionals. + Confirm the projections preserve these distinctions. +5. In a temporary source copy, change the spec and then the jq query. Verify + that each relevant output changes and the wrappers display the new result. + Repeat an unchanged invocation to confirm the generated artifact is reused. +6. Confirm that building or running a view does not compile Silverwood or + instantiate its development shell. Run shell syntax and whitespace checks + on the final changes. + +Completion means either `.cmd.sh` file can be invoked directly from any working +directory to display its view, using the named flake app and cached JSON output.