valise-sh 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/CHANGELOG.md +152 -2
  2. package/README.md +99 -146
  3. package/bin/valise +57 -5376
  4. package/docs/architecture.md +77 -121
  5. package/docs/contrib-modules.md +172 -218
  6. package/docs/installation.md +137 -83
  7. package/docs/module-abi.md +125 -126
  8. package/docs/projects.md +249 -0
  9. package/docs/release-policy.md +68 -93
  10. package/docs/shared-modules.md +40 -39
  11. package/examples/README.md +12 -11
  12. package/examples/e2e/README.md +59 -66
  13. package/examples/e2e/bundles.tsv +6 -0
  14. package/examples/e2e/module.d/e2e_aliases.meta +1 -2
  15. package/examples/e2e/module.d/e2e_completions_bash.meta +0 -1
  16. package/examples/e2e/module.d/e2e_completions_zsh.meta +0 -1
  17. package/examples/e2e/module.d/e2e_env_setup.meta +2 -3
  18. package/examples/e2e/module.d/e2e_fish_features.meta +0 -1
  19. package/examples/e2e/module.d/e2e_generated_config.meta +1 -2
  20. package/examples/e2e/module.d/e2e_ksh_features.meta +0 -1
  21. package/examples/e2e/module.d/e2e_layer_probe.meta +1 -2
  22. package/examples/e2e/module.d/e2e_optional_network.meta +1 -2
  23. package/examples/e2e/module.d/e2e_platform_tools.meta +8 -0
  24. package/examples/e2e/module.d/e2e_platform_tools_bsd.meta +2 -3
  25. package/examples/e2e/module.d/e2e_platform_tools_darwin.meta +2 -3
  26. package/examples/e2e/module.d/e2e_platform_tools_linux.meta +2 -3
  27. package/examples/e2e/valise.conf +4 -0
  28. package/examples/e2e/variants.tsv +3 -0
  29. package/examples/local/module.d/hello_valise.meta +1 -2
  30. package/examples/profile-project/README.md +78 -108
  31. package/examples/profile-project/bundles.tsv +8 -0
  32. package/examples/profile-project/{shell/layers → layers}/demo/module.d/contrib_demo_greeting.meta +1 -2
  33. package/examples/profile-project/{shell/module.d → module.d}/greeting.meta +1 -2
  34. package/examples/profile-project/{shell/module.d → module.d}/profile_main.meta +0 -1
  35. package/examples/profile-project/{shell/modules → modules}/greeting.sh +1 -1
  36. package/examples/profile-project/valise.conf +4 -0
  37. package/examples/profile-project/variants.tsv +3 -0
  38. package/examples/shared/README.md +13 -34
  39. package/examples/shared/module.d/contrib_shared_paths.meta +2 -3
  40. package/examples/shared/module.d/contrib_shared_umask.meta +1 -2
  41. package/examples/shared/modules/shared/contrib_shared_paths.sh +2 -2
  42. package/lib/capabilities.sh +40 -13
  43. package/lib/cli/commands.sh +278 -0
  44. package/lib/cli/common.sh +326 -0
  45. package/lib/cli/devtools.sh +539 -0
  46. package/lib/cli/fish-hook.sh +986 -0
  47. package/lib/cli/integration.sh +337 -0
  48. package/lib/cli/lifecycle.sh +578 -0
  49. package/lib/cli/project.sh +1807 -0
  50. package/lib/cli/store.sh +1023 -0
  51. package/lib/cli/usage.sh +308 -0
  52. package/lib/compiler.awk +11 -4
  53. package/lib/fish/loader.fish +69 -9
  54. package/lib/fish/metadata.fish +49 -5
  55. package/lib/fish/profile.fish +170 -0
  56. package/lib/loader.sh +6 -8
  57. package/lib/metadata.sh +111 -5
  58. package/manifests/parser-support.tsv +2 -2
  59. package/module.d/valise_editor.meta +9 -0
  60. package/module.d/valise_history.meta +9 -0
  61. package/module.d/valise_pager.meta +9 -0
  62. package/module.d/valise_path.meta +9 -0
  63. package/module.d/{platform_bsd.meta → valise_platform_bsd.meta} +3 -4
  64. package/module.d/{platform_linux.meta → valise_platform_linux.meta} +3 -4
  65. package/module.d/{platform_macos.meta → valise_platform_macos.meta} +3 -4
  66. package/module.d/{platform_posix.meta → valise_platform_posix.meta} +2 -3
  67. package/module.d/valise_xdg.meta +9 -0
  68. package/modules/system/{contrib_editor.sh → valise_editor.sh} +2 -2
  69. package/modules/system/{contrib_history.sh → valise_history.sh} +2 -2
  70. package/modules/system/{contrib_pager.sh → valise_pager.sh} +2 -2
  71. package/modules/system/{contrib_path.sh → valise_path.sh} +3 -3
  72. package/modules/system/{contrib_xdg.sh → valise_xdg.sh} +2 -2
  73. package/package.json +91 -10
  74. package/docs/variants.md +0 -327
  75. package/entrypoints/.gitkeep +0 -0
  76. package/entrypoints/fish/profile.fish +0 -99
  77. package/examples/e2e/build-manifest.sh +0 -138
  78. package/examples/local/.gitkeep +0 -0
  79. package/examples/profile-project/shell/release/bundle-roots +0 -9
  80. package/examples/profile-project/shell/release/install-variants +0 -3
  81. package/examples/profile-project/shell/release/module-registry.tsv +0 -4
  82. package/examples/profile-project/shell/release/project.conf +0 -3
  83. package/lib/.gitkeep +0 -0
  84. package/manifests/.gitkeep +0 -0
  85. package/module.d/.gitkeep +0 -0
  86. package/module.d/contrib_editor.meta +0 -10
  87. package/module.d/contrib_history.meta +0 -10
  88. package/module.d/contrib_pager.meta +0 -10
  89. package/module.d/contrib_path.meta +0 -10
  90. package/module.d/contrib_xdg.meta +0 -10
  91. package/modules/.gitkeep +0 -0
  92. /package/examples/profile-project/{shell/layers → layers}/demo/modules/shared/contrib_demo_greeting.sh +0 -0
@@ -1,146 +1,102 @@
1
1
  # Architecture and scope
2
2
 
3
- `valise-sh` contains a shell-profile loader, a compiler that turns module
4
- metadata into a static startup plan, a small catalog of reusable modules,
5
- and a CLI for installing and verifying sealed profile releases. It can be
6
- used from a source checkout or vendored by a consuming profile project.
3
+ valise-sh is a shell-profile engine. It reads module metadata as data,
4
+ compiles a static startup plan for each shell, packages the plans and module
5
+ bodies into a sealed release, installs the release, and verifies it. Your
6
+ profile lives in a separate valise project; the engine supplies the tools
7
+ and a few generic modules.
7
8
 
8
9
  ## Components
9
10
 
10
11
  | Path | Responsibility |
11
12
  |---|---|
12
- | `entrypoints/profile.sh` | Sourced POSIX entrypoint. Locates the engine and module roots, loads the libraries, then invokes the loader. |
13
- | `lib/metadata.sh` | Parses and validates `module.d/*.meta` as data; it does not execute metadata. |
14
- | `lib/loader.sh` | Resolves dependencies, selects modules by shell/platform/phase, sources bodies, checks declared exports, and cleans up failures. |
15
- | `lib/compiler.awk` | Compiles the preprocessed module graph into a static POSIX startup plan. |
16
- | `lib/capabilities.sh` | Portable OS, command, path, temporary-file, and system-information helpers for modules. |
17
- | `lib/fish/` and `entrypoints/fish/` | Fish-native metadata reader, loader, and adapter. Fish modules are not POSIX shell scripts. |
18
- | `module.d/`, `modules/` | Metadata and module bodies, including generic platform and `contrib_` utilities. |
19
- | `bin/valise` | POSIX shell CLI for integration snippets, sealed release installation and verification, project scaffolding, and the source-tree commands used by consumer projects. |
20
- | `manifests/parser-support.tsv` | Declares parser requirements for shipped shell files. |
13
+ | `bin/valise` | The CLI. It sources the parts under `lib/cli/` and dispatches commands. |
14
+ | `lib/cli/` | CLI parts: `project.sh` (project config, registry, compile, build), `store.sh` (release store, install, `release`), `integration.sh` (startup-file blocks, `doctor`), `fish-hook.sh`, `commands.sh` (published commands), `lifecycle.sh` (rollback, transactions, uninstall, dry runs), `devtools.sh` (`lint`, `test`, `run`, `env`), `usage.sh`, `common.sh`. |
15
+ | `lib/metadata.sh` | Parses and validates `.meta` files as data. |
16
+ | `lib/compiler.awk` | Turns the resolved module graph into a static POSIX plan. |
17
+ | `lib/capabilities.sh` | The `sp_cap_*` helpers. A release carries it as `runtime/capabilities.sh`. |
18
+ | `lib/fish/` | The native Fish metadata reader, loader, and adapter. A release carries them under `runtime/fish/`. |
19
+ | `lib/loader.sh`, `entrypoints/profile.sh` | The development loader, which resolves and sources modules at load time from a checkout. Installed profiles do not use it. |
20
+ | `module.d/`, `modules/` | The engine modules (`valise_*`). |
21
+ | `manifests/parser-support.tsv` | The parsers each shipped file class must pass. |
21
22
  | `tests/`, `examples/` | Quarantined tests and runnable examples. |
22
23
 
23
- See [module-abi.md](module-abi.md) for metadata and loader contracts,
24
- [installation.md](installation.md) for CLI and release behavior,
25
- [variants.md](variants.md) for the compile and build contract, and
26
- [contrib-modules.md](contrib-modules.md) for authoring modules.
27
-
28
- ## Two ways to load a profile
29
-
30
- A profile can be loaded two ways, and both are supported.
31
-
32
- The **loader** reads the metadata at startup, resolves the dependency
33
- graph, and sources the module bodies. It is the general mechanism: it
34
- honours every metadata field, including optional dependencies, and it
35
- works for a source tree that is still being edited.
36
-
37
- The **compiled plan** is a single static POSIX script per shell,
38
- generated ahead of time from the same metadata. It is faster to source,
39
- because nothing is parsed or resolved at startup. It carries the
40
- contract that matters for a startup file: platform gating, export
41
- checks, per-module failure reporting, strict and permissive failure
42
- policy, and the capability helpers left available to the modules it
43
- loads.
44
-
45
- The two are deliberately close in behavior, so a profile can be compiled
46
- for speed without changing what it does. The compile contract, including
47
- the exact fields the plan honors, is in [variants.md](variants.md).
48
-
49
- ## Two release shapes
50
-
51
- A release directory takes one of two shapes, and the startup snippet
52
- handles both.
53
-
54
- A **built release** is what `valise build` produces. It carries
55
- `generated/installed-modules.<shell>` compiled plans, the capability
56
- prelude under `vendor/shell-profile/lib/`, the module bodies, and no
57
- `entrypoints/`.
58
-
59
- An **engine release** carries `entrypoints/profile.sh` and `lib/`, and no
60
- `generated/`. It loads through the loader rather than a compiled plan.
61
-
62
- The POSIX integration snippet prefers the compiled plan for the running
63
- shell and falls back to the loader, so a startup file written by either
64
- shape loads the release it is pointed at.
65
-
66
- ## Loading modules
67
-
68
- The POSIX entrypoint is sourced, not executed. A caller can select roots,
69
- modules, and failure policy explicitly:
24
+ [projects.md](projects.md) describes a project and the compile and build
25
+ contract, [module-abi.md](module-abi.md) the metadata,
26
+ [installation.md](installation.md) installation and the release store, and
27
+ [contrib-modules.md](contrib-modules.md) writing and testing modules.
28
+
29
+ ## From metadata to a running shell
30
+
31
+ 1. `valise build` reads every `.meta` file in the project (`module.d/`, each
32
+ `layers/<provider>/module.d/`) and the engine's own `module.d/`, as data,
33
+ into an internal table. `valise registry` prints that table; nothing reads
34
+ a saved copy.
35
+ 2. For each POSIX shell in the bundle, the compiler resolves the roots'
36
+ closure, applies the variant's exclusions, orders the modules by
37
+ dependency, and writes `plans/<shell>.sh`. A module that publishes
38
+ commands gets its own plan under `plans/commands/`.
39
+ 3. The build copies the modules some shell loads, the capability prelude,
40
+ and the Fish runtime when the bundle has Fish roots, then writes
41
+ `manifest.tsv`. The release id is the SHA-256 of the manifest.
42
+ 4. `valise install` copies the tree into the release store, verifies it,
43
+ switches the active link, writes the startup-file blocks and the Fish
44
+ hook, and publishes command stubs. If any step fails, install restores
45
+ the previous state.
46
+ 5. At startup, the POSIX block picks the plan for the running shell class
47
+ (`bash`, `zsh`, `ksh`, or `sh`) and sources it. The plan contains the
48
+ load order; it reads no metadata. Fish verifies the release, then runs
49
+ the native Fish loader over the release's Fish metadata.
50
+
51
+ There is one release shape. The plan is generated ahead of time so that
52
+ startup does no resolution work and so that you can read exactly what will
53
+ run.
54
+
55
+ ## The development loader
56
+
57
+ `entrypoints/profile.sh` and `lib/loader.sh` load modules straight from a
58
+ checkout, resolving dependencies when they are sourced. They are for working
59
+ on the engine's own modules and for the loader's tests; installed profiles
60
+ and `valise run` use compiled plans. The loader honors the same metadata,
61
+ including optional dependencies, platform gating, export checks, and failure
62
+ cleanup:
70
63
 
71
64
  ```sh
72
65
  VALISE_ROOT=/path/to/valise-sh
73
- VALISE_MODULE_ROOT=/path/to/profile
66
+ VALISE_MODULE_ROOT=/path/to/modules
74
67
  VALISE_MODULES='module_a module_b'
75
68
  VALISE_MODE=strict
76
69
  . "$VALISE_ROOT/entrypoints/profile.sh"
77
70
  ```
78
71
 
79
- `VALISE_MODULES` unset means no modules are requested. A consuming profile is
80
- responsible for choosing its default module set and for setting the roots in
81
- its startup integration. Searching upward from the current directory when
82
- `VALISE_ROOT` is omitted is a checkout convenience, not an installed-profile
83
- configuration strategy.
72
+ `VALISE_MODULES` unset means nothing is loaded. Its search path is described
73
+ in [module-abi.md](module-abi.md#the-development-loaders-search-path).
84
74
 
85
- Metadata is validated before module bodies run. Required dependencies load
86
- first; present optional dependencies are also considered. Cycles and invalid
87
- or conflicting records are rejected. Strict mode returns failure for a
88
- requested module's failure; permissive mode reports the affected module and
89
- continues with unrelated requests. The loader has no unload operation.
75
+ ## Scope boundaries
90
76
 
91
- The Fish adapter uses the native Fish loader and native `.fish` bodies; it
92
- never sources POSIX bodies. Fish startup integration verifies the installed
93
- release before loading it. See [installation.md](installation.md) for the
94
- specific integrity boundary.
77
+ The engine does not define your modules, your bundles, your workstation
78
+ policy, or wrappers around other tools. Those belong in your project.
79
+ `valise new` writes an empty project so you do not have to invent the
80
+ layout.
95
81
 
96
- ## Scope boundaries
82
+ Project commands (`module`, `build`, `apply`, `status`, `lint`, `test`,
83
+ `run`, `compile`, `registry`, `explain-variant`, `explain-bundles`) run
84
+ inside a directory that holds `valise.conf`, found by walking up from the
85
+ working directory. Release commands (`install`, `release`, `uninstall`,
86
+ `init`, `doctor`, `make-manifest`) and `new`, `env`, `layer-lint`, and
87
+ `version` run anywhere.
97
88
 
98
- The engine does not define a consumer's module catalog, default startup graph,
99
- workstation policy, project wrappers, or project-specific release build.
100
- Those belong in the consuming repository. `valise new` scaffolds an empty
101
- project so a consumer never has to invent the directory layout by hand, but
102
- the catalog itself is still the consumer's to write.
103
-
104
- The CLI splits into two groups by what they need.
105
-
106
- Commands that work in a bare checkout: `init`, `install`, `release`,
107
- `doctor`, `make-manifest`, `version`, and `new`.
108
-
109
- Commands that need a consuming project, because they read or write the
110
- project's source tree: `registry`, `module`, `build`, `apply`, `status`,
111
- `compile`, `explain-variant`, `explain-bundles`, and
112
- `layer-lint`. A project is recognised by `shell/module.d/` or
113
- `shell/release/module-registry.tsv`; the project commands run from the
114
- project root and read their defaults from `shell/release/project.conf`.
115
-
116
- ## The registry is generated, not authored
117
-
118
- `shell/release/module-registry.tsv` is a build artifact. `valise registry`
119
- reads every `.meta` file under `shell/module.d/` and
120
- `shell/layers/<provider>/module.d/` and writes the registry from them, in the
121
- C locale, so repeated generation is byte-identical. `valise registry --check`
122
- compares the file against the metadata without rewriting it, which is what
123
- `valise status` reports as registry freshness. `build` regenerates the
124
- registry before compiling, so a project that contains only
125
- metadata and bodies still builds.
126
-
127
- This makes the `.meta` files the single source of truth. A hand-edited
128
- registry is not supported: the next build overwrites it.
129
-
130
- The `updates=` metadata field records identifiers for a consumer's update
131
- manifest. It does not make this engine a network updater. Shared modules are
132
- vendored snapshots: consumers review provider changes, update the snapshot,
133
- and rebuild their release. The engine does not authenticate authors or sign
134
- releases; its manifest check detects changes to bytes after the manifest is
135
- created.
89
+ Shared modules are vendored copies. You review a provider's changes, copy
90
+ them into `layers/<provider>/`, and rebuild. The engine does not fetch
91
+ updates, authenticate authors, or sign releases; the manifest detects bytes
92
+ that changed after the release was built.
136
93
 
137
94
  ## Verification
138
95
 
139
- Run `make check-fast` while developing and `make check` for the available
140
- suite. Extended runtime lanes run when their tools are installed; missing tools
141
- are visible skips locally and are required in CI. Set
142
- `VALISE_REQUIRE_TOOLING=1` to require them on a developer machine. The GitHub
143
- Actions workflow installs the shell runtimes used by the release check.
96
+ Run `make check-fast` while developing and `make check` for the full suite.
97
+ Extended runtime lanes run when their tools are installed; missing tools are
98
+ visible skips locally and failures in CI. Set `VALISE_REQUIRE_TOOLING=1` to
99
+ require them on a developer machine.
144
100
 
145
- These targets live in the source repository. The npm package ships the
146
- runtime, the docs, and the examples, not the Makefile or the test suite.
101
+ The Makefile and the tests live in the source repository. The npm package
102
+ ships the runtime, the docs, and the examples.