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.
- package/CHANGELOG.md +152 -2
- package/README.md +99 -146
- package/bin/valise +57 -5376
- package/docs/architecture.md +77 -121
- package/docs/contrib-modules.md +172 -218
- package/docs/installation.md +137 -83
- package/docs/module-abi.md +125 -126
- package/docs/projects.md +249 -0
- package/docs/release-policy.md +68 -93
- package/docs/shared-modules.md +40 -39
- package/examples/README.md +12 -11
- package/examples/e2e/README.md +59 -66
- package/examples/e2e/bundles.tsv +6 -0
- package/examples/e2e/module.d/e2e_aliases.meta +1 -2
- package/examples/e2e/module.d/e2e_completions_bash.meta +0 -1
- package/examples/e2e/module.d/e2e_completions_zsh.meta +0 -1
- package/examples/e2e/module.d/e2e_env_setup.meta +2 -3
- package/examples/e2e/module.d/e2e_fish_features.meta +0 -1
- package/examples/e2e/module.d/e2e_generated_config.meta +1 -2
- package/examples/e2e/module.d/e2e_ksh_features.meta +0 -1
- package/examples/e2e/module.d/e2e_layer_probe.meta +1 -2
- package/examples/e2e/module.d/e2e_optional_network.meta +1 -2
- package/examples/e2e/module.d/e2e_platform_tools.meta +8 -0
- package/examples/e2e/module.d/e2e_platform_tools_bsd.meta +2 -3
- package/examples/e2e/module.d/e2e_platform_tools_darwin.meta +2 -3
- package/examples/e2e/module.d/e2e_platform_tools_linux.meta +2 -3
- package/examples/e2e/valise.conf +4 -0
- package/examples/e2e/variants.tsv +3 -0
- package/examples/local/module.d/hello_valise.meta +1 -2
- package/examples/profile-project/README.md +78 -108
- package/examples/profile-project/bundles.tsv +8 -0
- package/examples/profile-project/{shell/layers → layers}/demo/module.d/contrib_demo_greeting.meta +1 -2
- package/examples/profile-project/{shell/module.d → module.d}/greeting.meta +1 -2
- package/examples/profile-project/{shell/module.d → module.d}/profile_main.meta +0 -1
- package/examples/profile-project/{shell/modules → modules}/greeting.sh +1 -1
- package/examples/profile-project/valise.conf +4 -0
- package/examples/profile-project/variants.tsv +3 -0
- package/examples/shared/README.md +13 -34
- package/examples/shared/module.d/contrib_shared_paths.meta +2 -3
- package/examples/shared/module.d/contrib_shared_umask.meta +1 -2
- package/examples/shared/modules/shared/contrib_shared_paths.sh +2 -2
- package/lib/capabilities.sh +40 -13
- package/lib/cli/commands.sh +278 -0
- package/lib/cli/common.sh +326 -0
- package/lib/cli/devtools.sh +539 -0
- package/lib/cli/fish-hook.sh +986 -0
- package/lib/cli/integration.sh +337 -0
- package/lib/cli/lifecycle.sh +578 -0
- package/lib/cli/project.sh +1807 -0
- package/lib/cli/store.sh +1023 -0
- package/lib/cli/usage.sh +308 -0
- package/lib/compiler.awk +11 -4
- package/lib/fish/loader.fish +69 -9
- package/lib/fish/metadata.fish +49 -5
- package/lib/fish/profile.fish +170 -0
- package/lib/loader.sh +6 -8
- package/lib/metadata.sh +111 -5
- package/manifests/parser-support.tsv +2 -2
- package/module.d/valise_editor.meta +9 -0
- package/module.d/valise_history.meta +9 -0
- package/module.d/valise_pager.meta +9 -0
- package/module.d/valise_path.meta +9 -0
- package/module.d/{platform_bsd.meta → valise_platform_bsd.meta} +3 -4
- package/module.d/{platform_linux.meta → valise_platform_linux.meta} +3 -4
- package/module.d/{platform_macos.meta → valise_platform_macos.meta} +3 -4
- package/module.d/{platform_posix.meta → valise_platform_posix.meta} +2 -3
- package/module.d/valise_xdg.meta +9 -0
- package/modules/system/{contrib_editor.sh → valise_editor.sh} +2 -2
- package/modules/system/{contrib_history.sh → valise_history.sh} +2 -2
- package/modules/system/{contrib_pager.sh → valise_pager.sh} +2 -2
- package/modules/system/{contrib_path.sh → valise_path.sh} +3 -3
- package/modules/system/{contrib_xdg.sh → valise_xdg.sh} +2 -2
- package/package.json +91 -10
- package/docs/variants.md +0 -327
- package/entrypoints/.gitkeep +0 -0
- package/entrypoints/fish/profile.fish +0 -99
- package/examples/e2e/build-manifest.sh +0 -138
- package/examples/local/.gitkeep +0 -0
- package/examples/profile-project/shell/release/bundle-roots +0 -9
- package/examples/profile-project/shell/release/install-variants +0 -3
- package/examples/profile-project/shell/release/module-registry.tsv +0 -4
- package/examples/profile-project/shell/release/project.conf +0 -3
- package/lib/.gitkeep +0 -0
- package/manifests/.gitkeep +0 -0
- package/module.d/.gitkeep +0 -0
- package/module.d/contrib_editor.meta +0 -10
- package/module.d/contrib_history.meta +0 -10
- package/module.d/contrib_pager.meta +0 -10
- package/module.d/contrib_path.meta +0 -10
- package/module.d/contrib_xdg.meta +0 -10
- package/modules/.gitkeep +0 -0
- /package/examples/profile-project/{shell/layers → layers}/demo/modules/shared/contrib_demo_greeting.sh +0 -0
package/package.json
CHANGED
|
@@ -1,20 +1,101 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "valise-sh",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Pure POSIX shell profile engine and CLI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"valise": "./bin/valise"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
|
-
"bin/",
|
|
10
|
-
"
|
|
11
|
-
"modules
|
|
12
|
-
"
|
|
13
|
-
"module.
|
|
14
|
-
"
|
|
15
|
-
"docs/",
|
|
16
|
-
"
|
|
17
|
-
"
|
|
9
|
+
"bin/valise",
|
|
10
|
+
"docs/architecture.md",
|
|
11
|
+
"docs/contrib-modules.md",
|
|
12
|
+
"docs/installation.md",
|
|
13
|
+
"docs/module-abi.md",
|
|
14
|
+
"docs/projects.md",
|
|
15
|
+
"docs/release-policy.md",
|
|
16
|
+
"docs/shared-modules.md",
|
|
17
|
+
"entrypoints/profile.sh",
|
|
18
|
+
"examples/README.md",
|
|
19
|
+
"examples/e2e/README.md",
|
|
20
|
+
"examples/e2e/bundles.tsv",
|
|
21
|
+
"examples/e2e/module.d/e2e_aliases.meta",
|
|
22
|
+
"examples/e2e/module.d/e2e_completions_bash.meta",
|
|
23
|
+
"examples/e2e/module.d/e2e_completions_zsh.meta",
|
|
24
|
+
"examples/e2e/module.d/e2e_env_setup.meta",
|
|
25
|
+
"examples/e2e/module.d/e2e_fish_features.meta",
|
|
26
|
+
"examples/e2e/module.d/e2e_generated_config.meta",
|
|
27
|
+
"examples/e2e/module.d/e2e_ksh_features.meta",
|
|
28
|
+
"examples/e2e/module.d/e2e_layer_probe.meta",
|
|
29
|
+
"examples/e2e/module.d/e2e_optional_network.meta",
|
|
30
|
+
"examples/e2e/module.d/e2e_platform_tools.meta",
|
|
31
|
+
"examples/e2e/module.d/e2e_platform_tools_bsd.meta",
|
|
32
|
+
"examples/e2e/module.d/e2e_platform_tools_darwin.meta",
|
|
33
|
+
"examples/e2e/module.d/e2e_platform_tools_linux.meta",
|
|
34
|
+
"examples/e2e/modules/e2e/aliases.sh",
|
|
35
|
+
"examples/e2e/modules/e2e/completions_bash.sh",
|
|
36
|
+
"examples/e2e/modules/e2e/completions_zsh.sh",
|
|
37
|
+
"examples/e2e/modules/e2e/env_setup.sh",
|
|
38
|
+
"examples/e2e/modules/e2e/fish_features.fish",
|
|
39
|
+
"examples/e2e/modules/e2e/generated_config.sh",
|
|
40
|
+
"examples/e2e/modules/e2e/ksh_features.sh",
|
|
41
|
+
"examples/e2e/modules/e2e/layer_probe.sh",
|
|
42
|
+
"examples/e2e/modules/e2e/optional_network.sh",
|
|
43
|
+
"examples/e2e/modules/e2e/platform_tools_bsd.sh",
|
|
44
|
+
"examples/e2e/modules/e2e/platform_tools_darwin.sh",
|
|
45
|
+
"examples/e2e/modules/e2e/platform_tools_linux.sh",
|
|
46
|
+
"examples/e2e/valise.conf",
|
|
47
|
+
"examples/e2e/variants.tsv",
|
|
48
|
+
"examples/local/module.d/hello_valise.meta",
|
|
49
|
+
"examples/local/modules/hello_valise.sh",
|
|
50
|
+
"examples/profile-project/README.md",
|
|
51
|
+
"examples/profile-project/bundles.tsv",
|
|
52
|
+
"examples/profile-project/layers/demo/module.d/contrib_demo_greeting.meta",
|
|
53
|
+
"examples/profile-project/layers/demo/modules/shared/contrib_demo_greeting.sh",
|
|
54
|
+
"examples/profile-project/module.d/greeting.meta",
|
|
55
|
+
"examples/profile-project/module.d/profile_main.meta",
|
|
56
|
+
"examples/profile-project/modules/greeting.sh",
|
|
57
|
+
"examples/profile-project/valise.conf",
|
|
58
|
+
"examples/profile-project/variants.tsv",
|
|
59
|
+
"examples/shared/README.md",
|
|
60
|
+
"examples/shared/module.d/contrib_shared_paths.meta",
|
|
61
|
+
"examples/shared/module.d/contrib_shared_umask.meta",
|
|
62
|
+
"examples/shared/modules/shared/contrib_shared_paths.sh",
|
|
63
|
+
"examples/shared/modules/shared/contrib_shared_umask.sh",
|
|
64
|
+
"lib/capabilities.sh",
|
|
65
|
+
"lib/cli/commands.sh",
|
|
66
|
+
"lib/cli/common.sh",
|
|
67
|
+
"lib/cli/devtools.sh",
|
|
68
|
+
"lib/cli/fish-hook.sh",
|
|
69
|
+
"lib/cli/integration.sh",
|
|
70
|
+
"lib/cli/lifecycle.sh",
|
|
71
|
+
"lib/cli/project.sh",
|
|
72
|
+
"lib/cli/store.sh",
|
|
73
|
+
"lib/cli/usage.sh",
|
|
74
|
+
"lib/compiler.awk",
|
|
75
|
+
"lib/fish/loader.fish",
|
|
76
|
+
"lib/fish/metadata.fish",
|
|
77
|
+
"lib/fish/profile.fish",
|
|
78
|
+
"lib/loader.sh",
|
|
79
|
+
"lib/metadata.sh",
|
|
80
|
+
"manifests/parser-support.tsv",
|
|
81
|
+
"module.d/valise_editor.meta",
|
|
82
|
+
"module.d/valise_history.meta",
|
|
83
|
+
"module.d/valise_pager.meta",
|
|
84
|
+
"module.d/valise_path.meta",
|
|
85
|
+
"module.d/valise_platform_bsd.meta",
|
|
86
|
+
"module.d/valise_platform_linux.meta",
|
|
87
|
+
"module.d/valise_platform_macos.meta",
|
|
88
|
+
"module.d/valise_platform_posix.meta",
|
|
89
|
+
"module.d/valise_xdg.meta",
|
|
90
|
+
"modules/platform/bsd/capabilities.sh",
|
|
91
|
+
"modules/platform/linux/capabilities.sh",
|
|
92
|
+
"modules/platform/macos/capabilities.sh",
|
|
93
|
+
"modules/platform/posix.sh",
|
|
94
|
+
"modules/system/valise_editor.sh",
|
|
95
|
+
"modules/system/valise_history.sh",
|
|
96
|
+
"modules/system/valise_pager.sh",
|
|
97
|
+
"modules/system/valise_path.sh",
|
|
98
|
+
"modules/system/valise_xdg.sh",
|
|
18
99
|
"LICENSE",
|
|
19
100
|
"CHANGELOG.md"
|
|
20
101
|
],
|
package/docs/variants.md
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
# The compile and build contract
|
|
2
|
-
|
|
3
|
-
This document describes how a consuming project turns metadata into an
|
|
4
|
-
installed release: what each input file contains, what `valise compile`
|
|
5
|
-
produces, what `valise build` packages, and how the two fail.
|
|
6
|
-
|
|
7
|
-
Two different mechanisms share the word "variant". They compose, but they are
|
|
8
|
-
not the same command.
|
|
9
|
-
|
|
10
|
-
- **Build variants** are exclusion lists decided at compile time inside the
|
|
11
|
-
consuming project. They live in `shell/release/install-variants`.
|
|
12
|
-
- **Installed releases** are sealed directories on this machine. They are
|
|
13
|
-
listed, switched, and pruned with `valise release list|use|prune`.
|
|
14
|
-
|
|
15
|
-
Neither reads the other's file. `release use` never reads `install-variants`;
|
|
16
|
-
variant exclusion is decided when the plans are compiled.
|
|
17
|
-
|
|
18
|
-
## The project layout
|
|
19
|
-
|
|
20
|
-
A consuming project that uses the CLI has this shape:
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
shell/
|
|
24
|
-
module.d/ primary modules: <name>.meta
|
|
25
|
-
modules/ primary module bodies
|
|
26
|
-
layers/<provider>/ provider layers (optional)
|
|
27
|
-
module.d/ layer modules: <name>.meta
|
|
28
|
-
modules/ layer module bodies
|
|
29
|
-
release/
|
|
30
|
-
bundle-roots which modules seed each bundle, per shell
|
|
31
|
-
install-variants build variants and their exclusion lists
|
|
32
|
-
module-registry.tsv GENERATED from the metadata above
|
|
33
|
-
project.conf project defaults (optional)
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
`shell/module.d/` and `shell/release/module-registry.tsv` are the two markers
|
|
37
|
-
that identify a directory as a valise project. A layer's `<provider>` is a
|
|
38
|
-
path component made of letters, digits, `_`, `-`, and `.`; it may not start
|
|
39
|
-
with `.` or contain `..`. The registry rejects any other provider name,
|
|
40
|
-
because the compiler emits module identities from it as shell source text. The CLI resolves the project
|
|
41
|
-
root from the working directory first, then from the engine's own location, so
|
|
42
|
-
running `valise compile` from the project root always compiles *that* project
|
|
43
|
-
rather than a tree that merely happens to contain the engine.
|
|
44
|
-
|
|
45
|
-
## Metadata is the source of truth
|
|
46
|
-
|
|
47
|
-
Module metadata is data: `key=value` lines in a `.meta` file, parsed and
|
|
48
|
-
validated, never sourced. See [module-abi.md](module-abi.md) for the full
|
|
49
|
-
field list and the grammar each value must satisfy.
|
|
50
|
-
|
|
51
|
-
The registry is a **generated artifact**, not a second source of truth. The
|
|
52
|
-
generator is `valise registry`:
|
|
53
|
-
|
|
54
|
-
```sh
|
|
55
|
-
valise registry # write shell/release/module-registry.tsv
|
|
56
|
-
valise registry --check # compare, fail on drift, write nothing
|
|
57
|
-
valise registry path/to/registry.tsv # write somewhere else
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
`valise build` regenerates the registry before it builds, so a project
|
|
61
|
-
that only has `.meta` files and bodies builds with no hand-written TSV. The
|
|
62
|
-
generator refuses to publish a registry when the metadata is inconsistent:
|
|
63
|
-
a `name` that does not match its filename, a missing body, a layer module
|
|
64
|
-
without the `contrib_` prefix, a load path that is not representable, or an
|
|
65
|
-
export name that is not a shell identifier.
|
|
66
|
-
|
|
67
|
-
The registry is a tab-separated file with one header row and one row per
|
|
68
|
-
module:
|
|
69
|
-
|
|
70
|
-
| # | Column | Meaning |
|
|
71
|
-
|---|---|---|
|
|
72
|
-
| 1 | `name` | Module identifier. |
|
|
73
|
-
| 2 | `version` | Optional version string; empty means unversioned. |
|
|
74
|
-
| 3 | `side_effect` | Startup side-effect class. |
|
|
75
|
-
| 4 | `requires` | Space-separated required dependencies. |
|
|
76
|
-
| 5 | `optional` | Space-separated optional dependencies. |
|
|
77
|
-
| 6 | `shells` | Space-separated shell identifiers. |
|
|
78
|
-
| 7 | `platforms` | Space-separated platform identifiers. |
|
|
79
|
-
| 8 | `exports` | Space-separated exported identifiers. |
|
|
80
|
-
| 9 | `load` | Repository-relative body path, or empty for a meta module. |
|
|
81
|
-
| 10 | `updates` | Space-separated update registration identifiers. |
|
|
82
|
-
| 11 | `source` | Directory that holds the `.meta`: `shell/module.d` or `shell/layers/<provider>/module.d`. |
|
|
83
|
-
|
|
84
|
-
Rows come out in a fixed order: the primary modules of `shell/module.d/`
|
|
85
|
-
first, then the layer modules of each `shell/layers/<provider>/module.d/`,
|
|
86
|
-
each group in C-locale name order. The order does not depend on the caller's
|
|
87
|
-
locale, so regenerating an unchanged project produces a byte-identical file.
|
|
88
|
-
|
|
89
|
-
## Bundles: which modules seed each shell
|
|
90
|
-
|
|
91
|
-
A bundle names the root modules for each shell. The file is
|
|
92
|
-
`shell/release/bundle-roots`, tab-separated:
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
# bundle shell roots
|
|
96
|
-
default bash profile_main
|
|
97
|
-
default zsh profile_main
|
|
98
|
-
default ksh profile_main
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
- Column 1 is the bundle name.
|
|
102
|
-
- Column 2 is the shell the roots apply to.
|
|
103
|
-
- Column 3 is a space-separated list of root module names.
|
|
104
|
-
|
|
105
|
-
A root may be a bare name (`profile_main`), which resolves against
|
|
106
|
-
`shell/module.d/`, or a qualified name (`contrib_tool@shell/layers/vendor/module.d`)
|
|
107
|
-
that names its source directory explicitly. Use the qualified form when a
|
|
108
|
-
layer module and a primary module share a name.
|
|
109
|
-
|
|
110
|
-
The first row may be a header (`bundle`, `shell`, `roots`); it is not a bundle
|
|
111
|
-
definition.
|
|
112
|
-
|
|
113
|
-
A bundle names the **starting points**, not the final set. `valise compile`
|
|
114
|
-
walks each root's `requires` and `optional` edges, so the installed plan
|
|
115
|
-
contains the whole reachable closure. `valise explain-bundles` prints that
|
|
116
|
-
closure per shell, which is the fastest way to see what a bundle actually
|
|
117
|
-
loads:
|
|
118
|
-
|
|
119
|
-
```sh
|
|
120
|
-
valise explain-bundles
|
|
121
|
-
valise explain-bundles --bundle=default
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
It reads `bundle-roots` and the registry directly, and needs no Python. An
|
|
125
|
-
unknown `--bundle` name is an error, not an empty report.
|
|
126
|
-
|
|
127
|
-
## Variants: what to leave out
|
|
128
|
-
|
|
129
|
-
A build variant is an exclusion list. The file is
|
|
130
|
-
`shell/release/install-variants`, tab-separated:
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
variant_name description excluded_modules
|
|
134
|
-
default All project modules
|
|
135
|
-
workstation-lean No editor defaults contrib_editor
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
- Column 1 is the variant name.
|
|
139
|
-
- Column 2 is a human-readable description.
|
|
140
|
-
- Column 3 is a space-separated list of excluded modules.
|
|
141
|
-
|
|
142
|
-
An exclusion is a bare module name (matching a `shell/module.d/` module) or a
|
|
143
|
-
qualified name (`<name>@<source>`) that names the source directory
|
|
144
|
-
explicitly. Every exclusion must match exactly one registry row; an unknown
|
|
145
|
-
or ambiguous exclusion fails the compile rather than silently excluding
|
|
146
|
-
nothing.
|
|
147
|
-
|
|
148
|
-
Exclusion is applied to the whole resolved graph, not just the roots. A module
|
|
149
|
-
excluded by name is not loaded, and neither is anything that depends on it.
|
|
150
|
-
`valise explain-variant <name>` shows a variant's description, its exclusion
|
|
151
|
-
list, and the per-shell impact.
|
|
152
|
-
|
|
153
|
-
The variant and the bundle compose: the bundle decides the starting points
|
|
154
|
-
and the layers they reach, and the variant then removes modules from the
|
|
155
|
-
resolved graph.
|
|
156
|
-
|
|
157
|
-
## `valise compile`
|
|
158
|
-
|
|
159
|
-
```sh
|
|
160
|
-
valise compile [--bundle=<name>] [--variant=<name>] <output-dir>
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Compile resolves the module graph and writes one plan per shell. It does not
|
|
164
|
-
copy module bodies; that is `build`'s job.
|
|
165
|
-
|
|
166
|
-
The steps, in order:
|
|
167
|
-
|
|
168
|
-
1. Resolve the project root. Fail with `cannot find source tree` when the
|
|
169
|
-
project has no `shell/release/module-registry.tsv`.
|
|
170
|
-
2. Validate the variant: the name must appear exactly once in
|
|
171
|
-
`install-variants`, and every exclusion must match exactly one registry
|
|
172
|
-
row.
|
|
173
|
-
3. Validate the bundle when `--bundle` is given: the name must exist, and
|
|
174
|
-
its roots must resolve.
|
|
175
|
-
4. For each of `bash`, `zsh`, and `ksh`, resolve the
|
|
176
|
-
bundle's roots for that shell, walk the dependency closure, drop the
|
|
177
|
-
variant's exclusions, select each module by `shells=`, emit its
|
|
178
|
-
`platforms=` gate, and emit a plan.
|
|
179
|
-
5. Replace the output directory atomically.
|
|
180
|
-
|
|
181
|
-
The output directory must be empty or absent. Compile stages into a private
|
|
182
|
-
sibling directory and publishes only after every plan has compiled, so a
|
|
183
|
-
failed compile never leaves a half-written output tree.
|
|
184
|
-
|
|
185
|
-
### What a plan contains
|
|
186
|
-
|
|
187
|
-
Each plan is a POSIX shell file at `generated/installed-modules.<shell>`:
|
|
188
|
-
|
|
189
|
-
```
|
|
190
|
-
# shell-profile-installed-modules-v1
|
|
191
|
-
# Generated by valise compile; DO NOT EDIT.
|
|
192
|
-
# plan=bash
|
|
193
|
-
# roots=profile_main
|
|
194
|
-
# order=hello profile_main
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
The header names the format, the generator, the shell, the roots, and the
|
|
198
|
-
resolved load order. The body then:
|
|
199
|
-
|
|
200
|
-
- validates `VALISE_MODE` (`strict` or `permissive`; default `strict`);
|
|
201
|
-
- probes the platform once and gates each module by `platforms=`;
|
|
202
|
-
- sources `vendor/shell-profile/lib/capabilities.sh`, so `sp_cap_*` helpers
|
|
203
|
-
stay available to module functions after the plan finishes;
|
|
204
|
-
- checks each module's declared exports before and after loading it;
|
|
205
|
-
- does not run a module whose required dependency is unavailable, whether that
|
|
206
|
-
dependency failed or was skipped for this platform, and reports it by name;
|
|
207
|
-
- in strict mode, returns nonzero at the first failure in the required closure:
|
|
208
|
-
the bundle's roots and everything they require;
|
|
209
|
-
- in permissive mode, reports each failure, continues with the unrelated
|
|
210
|
-
modules, and returns zero;
|
|
211
|
-
- treats an optional dependency as best effort: it loads first when it can, and
|
|
212
|
-
its absence never affects the module that declared it. A failure is reported;
|
|
213
|
-
an unsupported platform is expected and prints nothing;
|
|
214
|
-
- when `VALISE_RELOAD=1` is set, clears the plan's declared exports first, so
|
|
215
|
-
the plan can be sourced again.
|
|
216
|
-
|
|
217
|
-
The plan is the compiled equivalent of the loader: same dependency rules,
|
|
218
|
-
same export checks, same strict and permissive behavior. The plan is static and fast;
|
|
219
|
-
the loader parses metadata at runtime and is the fallback for releases that
|
|
220
|
-
ship an `entrypoints/` tree instead of `generated/` plans.
|
|
221
|
-
|
|
222
|
-
### Failure behavior
|
|
223
|
-
|
|
224
|
-
Compile fails closed, before writing anything, when:
|
|
225
|
-
|
|
226
|
-
- the project root cannot be resolved;
|
|
227
|
-
- the variant is unknown or ambiguous;
|
|
228
|
-
- a variant exclusion matches no registry row, or more than one;
|
|
229
|
-
- the bundle is unknown, or its roots do not resolve;
|
|
230
|
-
- a module in the closure has a `side_effect` that is not safe to source at
|
|
231
|
-
startup (`generated-file`, `update-network`, `install-time`);
|
|
232
|
-
- the capabilities prelude is missing or defines no `sp_cap_*` functions;
|
|
233
|
-
- the registry names a module whose source, load path, or export name is not
|
|
234
|
-
representable.
|
|
235
|
-
|
|
236
|
-
Fish plans are not produced by the POSIX plan generator. `valise compile`
|
|
237
|
-
emits POSIX plans only; a Fish integration uses the native Fish loader.
|
|
238
|
-
|
|
239
|
-
## `valise build`
|
|
240
|
-
|
|
241
|
-
```sh
|
|
242
|
-
valise build [--bundle=<name>] [--variant=<name>] [out]
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
Build a complete, installable release tree. It runs `valise
|
|
246
|
-
compile` internally, so everything compile validates is validated here too.
|
|
247
|
-
|
|
248
|
-
The built tree has this layout:
|
|
249
|
-
|
|
250
|
-
```
|
|
251
|
-
generated/installed-modules.bash compiled plans
|
|
252
|
-
generated/installed-modules.zsh
|
|
253
|
-
generated/installed-modules.ksh
|
|
254
|
-
module.d/<name>.meta primary module metadata
|
|
255
|
-
modules/<path> primary module bodies
|
|
256
|
-
layers/<provider>/module.d/<name>.meta layer metadata
|
|
257
|
-
layers/<provider>/<path> layer bodies
|
|
258
|
-
vendor/shell-profile/lib/capabilities.sh the capability prelude
|
|
259
|
-
shell/release/ bundle-roots, install-variants, registry
|
|
260
|
-
shell/install/profile-release.manifest the release manifest
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
Build:
|
|
264
|
-
|
|
265
|
-
1. Runs from the project root — it needs `shell/module.d/`.
|
|
266
|
-
2. Regenerates `shell/release/module-registry.tsv` from the metadata.
|
|
267
|
-
3. Compiles the plans into a staging directory.
|
|
268
|
-
4. Copies the capability prelude from the installed engine. The packaged
|
|
269
|
-
file is the same file the plans were built against.
|
|
270
|
-
5. Copies each module's metadata and body to its release path. A primary
|
|
271
|
-
module lands at the release root; a layer module lands at
|
|
272
|
-
`layers/<provider>/`, matching the paths the plan references.
|
|
273
|
-
6. Normalizes file modes to `0644` and writes the release manifest.
|
|
274
|
-
7. Publishes the tree at the destination.
|
|
275
|
-
|
|
276
|
-
Like compile, build stages beside the destination and publishes only after
|
|
277
|
-
the complete tree and its manifest exist. A failed build never leaves a
|
|
278
|
-
partial release. The default destination is `build/release`; an existing
|
|
279
|
-
default tree is replaced only after the new tree has compiled and been
|
|
280
|
-
manifested. An explicit destination must be empty or absent.
|
|
281
|
-
|
|
282
|
-
Building the same project twice produces byte-identical output, including
|
|
283
|
-
the manifest.
|
|
284
|
-
|
|
285
|
-
## `valise build` and `valise apply`
|
|
286
|
-
|
|
287
|
-
`valise build` produces the tree; `valise apply` adds install and shell
|
|
288
|
-
integration on top of it:
|
|
289
|
-
|
|
290
|
-
- `valise build [--variant=<name>] [--bundle=<name>] [out]` builds to
|
|
291
|
-
`build/release` by default, reading the variant and bundle defaults from
|
|
292
|
-
`shell/release/project.conf`.
|
|
293
|
-
- `valise apply [--variant=<name>] [--bundle=<name>] [--no-integration]`
|
|
294
|
-
builds, installs the release, writes the managed shell integration,
|
|
295
|
-
verifies the active release, and reports what changed.
|
|
296
|
-
|
|
297
|
-
Both are idempotent: running them twice leaves the same state.
|
|
298
|
-
|
|
299
|
-
`shell/release/project.conf` holds the defaults:
|
|
300
|
-
|
|
301
|
-
```
|
|
302
|
-
variant=default
|
|
303
|
-
bundle=default
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
## `valise release list`, `use`, and `prune`
|
|
307
|
-
|
|
308
|
-
These operate on the releases installed on this machine. No source tree is
|
|
309
|
-
needed.
|
|
310
|
-
|
|
311
|
-
```sh
|
|
312
|
-
valise release list
|
|
313
|
-
valise release use <release-id>
|
|
314
|
-
valise release prune --keep=3
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
Release directories are named by the content-derived SHA-256 of their
|
|
318
|
-
manifest, and the active one is marked in the list. `release use` verifies
|
|
319
|
-
the named release byte-for-byte against its own manifest before switching the
|
|
320
|
-
active pointer.
|
|
321
|
-
|
|
322
|
-
`release prune --keep=N` removes old releases. It keeps the active release
|
|
323
|
-
and the `N` newest others, ordered by directory modification time. Before
|
|
324
|
-
removing any candidate it verifies the candidate against its own manifest; a
|
|
325
|
-
release that fails verification is **kept** and reported, because a release
|
|
326
|
-
that cannot be verified may be the only recoverable copy. The default is
|
|
327
|
-
`--keep=3`.
|
package/entrypoints/.gitkeep
DELETED
|
File without changes
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2026 Joseph Cumines
|
|
2
|
-
# SPDX-License-Identifier: MIT
|
|
3
|
-
|
|
4
|
-
# Generic Fish entrypoint adapter shipped with the valise engine.
|
|
5
|
-
#
|
|
6
|
-
# The valise Fish integration authenticates the active sealed release and
|
|
7
|
-
# exports SHELL_PROJECT_ROOT pointing at its root before sourcing this file.
|
|
8
|
-
# This adapter then requests modules the same way the POSIX entrypoint does:
|
|
9
|
-
# VALISE_MODULES selects the graph (unset loads nothing), VALISE_MODE selects
|
|
10
|
-
# strict or permissive failure handling (default permissive). It sources the
|
|
11
|
-
# release's native Fish metadata and loader, consumes the loader's bootstrap
|
|
12
|
-
# status marker, and publishes VALISE_FISH_READY=1 only after a successful
|
|
13
|
-
# activation. Consuming projects may ship their own adapter at the same
|
|
14
|
-
# release path to add project-specific selection policy.
|
|
15
|
-
|
|
16
|
-
if not builtin set -q SHELL_PROJECT_ROOT
|
|
17
|
-
builtin printf '%s\n' 'valise Fish entrypoint: SHELL_PROJECT_ROOT is not set' >&2
|
|
18
|
-
return 1
|
|
19
|
-
end
|
|
20
|
-
set -l _valise_fish_entrypoint_root "$SHELL_PROJECT_ROOT"
|
|
21
|
-
|
|
22
|
-
if not builtin test -r "$_valise_fish_entrypoint_root/lib/fish/metadata.fish"
|
|
23
|
-
builtin printf '%s\n' "valise Fish entrypoint: metadata library is not readable: $_valise_fish_entrypoint_root/lib/fish/metadata.fish" >&2
|
|
24
|
-
return 1
|
|
25
|
-
end
|
|
26
|
-
if not builtin test -r "$_valise_fish_entrypoint_root/lib/fish/loader.fish"
|
|
27
|
-
builtin printf '%s\n' "valise Fish entrypoint: loader library is not readable: $_valise_fish_entrypoint_root/lib/fish/loader.fish" >&2
|
|
28
|
-
return 1
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# The bootstrap handshake variables are engine-private state. A forged or
|
|
32
|
-
# stale marker must not survive into this activation: erase every visible
|
|
33
|
-
# scope before requesting a fresh bootstrap, failing closed if an erase
|
|
34
|
-
# is refused.
|
|
35
|
-
for _valise_fish_entrypoint_stale in _sp_fish_loader_bootstrap_mode _sp_fish_loader_bootstrap_seeds _sp_fish_loader_bootstrap_status
|
|
36
|
-
if builtin set -q -g "$_valise_fish_entrypoint_stale"; and not builtin set -e -g "$_valise_fish_entrypoint_stale"
|
|
37
|
-
builtin printf '%s\n' "valise Fish entrypoint: cannot clear stale global $_valise_fish_entrypoint_stale" >&2
|
|
38
|
-
return 1
|
|
39
|
-
end
|
|
40
|
-
if builtin set -q -U "$_valise_fish_entrypoint_stale"; and not builtin set -e -U "$_valise_fish_entrypoint_stale"
|
|
41
|
-
builtin printf '%s\n' "valise Fish entrypoint: cannot clear stale universal $_valise_fish_entrypoint_stale" >&2
|
|
42
|
-
return 1
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
set -l _valise_fish_entrypoint_mode permissive
|
|
47
|
-
if builtin set -q VALISE_MODE
|
|
48
|
-
set _valise_fish_entrypoint_mode "$VALISE_MODE"
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
set -l _valise_fish_entrypoint_seeds
|
|
52
|
-
if builtin set -q VALISE_MODULES; and builtin test -n "$VALISE_MODULES"
|
|
53
|
-
set _valise_fish_entrypoint_seeds (builtin string split ' ' -- $VALISE_MODULES)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
builtin set -gx _sp_fish_loader_bootstrap_mode "$_valise_fish_entrypoint_mode"
|
|
57
|
-
builtin set -gx _sp_fish_loader_bootstrap_seeds $_valise_fish_entrypoint_seeds
|
|
58
|
-
|
|
59
|
-
builtin source "$_valise_fish_entrypoint_root/lib/fish/metadata.fish"
|
|
60
|
-
set -l _valise_fish_entrypoint_metadata_status $status
|
|
61
|
-
if builtin test $_valise_fish_entrypoint_metadata_status -ne 0
|
|
62
|
-
builtin set -e _sp_fish_loader_bootstrap_mode
|
|
63
|
-
builtin set -e _sp_fish_loader_bootstrap_seeds
|
|
64
|
-
return $_valise_fish_entrypoint_metadata_status
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
builtin source "$_valise_fish_entrypoint_root/lib/fish/loader.fish"
|
|
68
|
-
set -l _valise_fish_entrypoint_loader_status $status
|
|
69
|
-
# The loader consumes the bootstrap request when it sources cleanly; erase
|
|
70
|
-
# any request a failed source left behind so it cannot leak to callers.
|
|
71
|
-
if builtin set -q _sp_fish_loader_bootstrap_mode
|
|
72
|
-
builtin set -e _sp_fish_loader_bootstrap_mode
|
|
73
|
-
end
|
|
74
|
-
if builtin set -q _sp_fish_loader_bootstrap_seeds
|
|
75
|
-
builtin set -e _sp_fish_loader_bootstrap_seeds
|
|
76
|
-
end
|
|
77
|
-
if builtin test $_valise_fish_entrypoint_loader_status -ne 0
|
|
78
|
-
# A failed source may have published a partial status marker; erase it
|
|
79
|
-
# so the caller's fresh-marker check below cannot see stale state.
|
|
80
|
-
if builtin set -q _sp_fish_loader_bootstrap_status
|
|
81
|
-
builtin set -e _sp_fish_loader_bootstrap_status
|
|
82
|
-
end
|
|
83
|
-
return $_valise_fish_entrypoint_loader_status
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# The loader publishes a fresh bootstrap status marker on every activation;
|
|
87
|
-
# its absence means the loader never completed its handshake.
|
|
88
|
-
if not builtin set -q _sp_fish_loader_bootstrap_status
|
|
89
|
-
builtin printf '%s\n' 'valise Fish entrypoint: loader bootstrap status marker is absent' >&2
|
|
90
|
-
return 1
|
|
91
|
-
end
|
|
92
|
-
set -l _valise_fish_entrypoint_status $_sp_fish_loader_bootstrap_status
|
|
93
|
-
builtin set -e _sp_fish_loader_bootstrap_status
|
|
94
|
-
if builtin test $_valise_fish_entrypoint_status -ne 0
|
|
95
|
-
return $_valise_fish_entrypoint_status
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
builtin set -gx VALISE_FISH_READY 1
|
|
99
|
-
return 0
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
|
|
3
|
-
# Copyright (c) 2026 Joseph Cumines
|
|
4
|
-
# SPDX-License-Identifier: MIT
|
|
5
|
-
|
|
6
|
-
# build-manifest.sh: vendor engine files into an e2e release tree and
|
|
7
|
-
# generate a profile-release.manifest with correct sizes and SHA-256 digests.
|
|
8
|
-
#
|
|
9
|
-
# Usage: sh build-manifest.sh [output-dir]
|
|
10
|
-
# Default output-dir: examples/e2e/build/release
|
|
11
|
-
|
|
12
|
-
set -eu
|
|
13
|
-
|
|
14
|
-
_script_dir=$(cd "$(dirname "$0")" && pwd -P)
|
|
15
|
-
_repo_root=$(cd "$_script_dir/../.." && pwd -P)
|
|
16
|
-
_e2e_root="$_script_dir"
|
|
17
|
-
_out_dir="${1:-$_e2e_root/build/release}"
|
|
18
|
-
_valise="$_repo_root/bin/valise"
|
|
19
|
-
|
|
20
|
-
[ -x "$_valise" ] || { printf 'ERROR: valise CLI not found at %s\n' "$_valise" >&2; exit 1; }
|
|
21
|
-
|
|
22
|
-
# Prepare clean output directory
|
|
23
|
-
rm -rf "$_out_dir"
|
|
24
|
-
mkdir -p "$_out_dir"
|
|
25
|
-
|
|
26
|
-
_vendor_copy() {
|
|
27
|
-
_src="$_repo_root/$1"
|
|
28
|
-
_dst="$_out_dir/$1"
|
|
29
|
-
_dst_dir=$(dirname "$_dst")
|
|
30
|
-
[ -f "$_src" ] || { printf 'ERROR: engine source missing: %s\n' "$_src" >&2; exit 1; }
|
|
31
|
-
mkdir -p "$_dst_dir"
|
|
32
|
-
cp "$_src" "$_dst"
|
|
33
|
-
chmod 0644 "$_dst"
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
printf 'Vendoring engine files into %s...\n' "$_out_dir"
|
|
37
|
-
|
|
38
|
-
# Core libraries
|
|
39
|
-
_vendor_copy lib/metadata.sh
|
|
40
|
-
_vendor_copy lib/loader.sh
|
|
41
|
-
_vendor_copy lib/capabilities.sh
|
|
42
|
-
_vendor_copy lib/compiler.awk
|
|
43
|
-
|
|
44
|
-
# Fish libraries
|
|
45
|
-
_vendor_copy lib/fish/loader.fish
|
|
46
|
-
_vendor_copy lib/fish/metadata.fish
|
|
47
|
-
|
|
48
|
-
# Generic Fish entrypoint adapter
|
|
49
|
-
_vendor_copy entrypoints/fish/profile.fish
|
|
50
|
-
|
|
51
|
-
# Entrypoint
|
|
52
|
-
_vendor_copy entrypoints/profile.sh
|
|
53
|
-
|
|
54
|
-
# Platform module metadata
|
|
55
|
-
_vendor_copy module.d/platform_posix.meta
|
|
56
|
-
_vendor_copy module.d/platform_macos.meta
|
|
57
|
-
_vendor_copy module.d/platform_linux.meta
|
|
58
|
-
_vendor_copy module.d/platform_bsd.meta
|
|
59
|
-
|
|
60
|
-
# Platform module bodies
|
|
61
|
-
_vendor_copy modules/platform/posix.sh
|
|
62
|
-
_vendor_copy modules/platform/macos/capabilities.sh
|
|
63
|
-
_vendor_copy modules/platform/linux/capabilities.sh
|
|
64
|
-
_vendor_copy modules/platform/bsd/capabilities.sh
|
|
65
|
-
|
|
66
|
-
# Shareable engine catalog (ships in every release built from this engine)
|
|
67
|
-
_engine_contrib_count=0
|
|
68
|
-
for _contrib_src in "$_repo_root"/module.d/contrib_*.meta; do
|
|
69
|
-
[ -f "$_contrib_src" ] || continue
|
|
70
|
-
_vendor_copy "module.d/$(basename "$_contrib_src")"
|
|
71
|
-
_engine_contrib_count=$((_engine_contrib_count + 1))
|
|
72
|
-
done
|
|
73
|
-
for _contrib_src in "$_repo_root"/modules/system/contrib_*.sh; do
|
|
74
|
-
[ -f "$_contrib_src" ] || continue
|
|
75
|
-
_vendor_copy "modules/system/$(basename "$_contrib_src")"
|
|
76
|
-
_engine_contrib_count=$((_engine_contrib_count + 1))
|
|
77
|
-
done
|
|
78
|
-
if [ "$_engine_contrib_count" -eq 0 ]; then
|
|
79
|
-
printf 'ERROR: no shareable engine modules found in %s\n' "$_repo_root" >&2
|
|
80
|
-
exit 1
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
# --- Native e2e example modules ---
|
|
84
|
-
_e2e_meta_count=0
|
|
85
|
-
mkdir -p "$_out_dir/module.d"
|
|
86
|
-
for _meta in "$_e2e_root"/module.d/e2e_*.meta; do
|
|
87
|
-
[ -f "$_meta" ] || continue
|
|
88
|
-
cp "$_meta" "$_out_dir/module.d/"
|
|
89
|
-
chmod 0644 "$_out_dir/module.d/$(basename "$_meta")"
|
|
90
|
-
_e2e_meta_count=$((_e2e_meta_count + 1))
|
|
91
|
-
done
|
|
92
|
-
|
|
93
|
-
_e2e_body_count=0
|
|
94
|
-
mkdir -p "$_out_dir/modules/e2e"
|
|
95
|
-
for _body in "$_e2e_root"/modules/e2e/*.sh "$_e2e_root"/modules/e2e/*.fish; do
|
|
96
|
-
[ -f "$_body" ] || continue
|
|
97
|
-
cp "$_body" "$_out_dir/modules/e2e/"
|
|
98
|
-
chmod 0644 "$_out_dir/modules/e2e/$(basename "$_body")"
|
|
99
|
-
_e2e_body_count=$((_e2e_body_count + 1))
|
|
100
|
-
done
|
|
101
|
-
|
|
102
|
-
if [ "$_e2e_meta_count" -eq 0 ]; then
|
|
103
|
-
printf 'ERROR: no e2e module metadata found in %s\n' "$_e2e_root/module.d" >&2
|
|
104
|
-
exit 1
|
|
105
|
-
fi
|
|
106
|
-
if [ "$_e2e_body_count" -eq 0 ]; then
|
|
107
|
-
printf 'ERROR: no e2e module bodies found in %s\n' "$_e2e_root/modules/e2e" >&2
|
|
108
|
-
exit 1
|
|
109
|
-
fi
|
|
110
|
-
|
|
111
|
-
# --- Vendor shared layer (cross-repo composition) ---
|
|
112
|
-
_shared_src="$_repo_root/examples/shared"
|
|
113
|
-
_shared_dst="$_out_dir/layer/shared"
|
|
114
|
-
[ -d "$_shared_src/module.d" ] || { printf 'ERROR: shared provider missing: %s\n' "$_shared_src" >&2; exit 1; }
|
|
115
|
-
mkdir -p "$_shared_dst/module.d" "$_shared_dst/modules"
|
|
116
|
-
for _shared_meta in "$_shared_src"/module.d/*.meta; do
|
|
117
|
-
[ -f "$_shared_meta" ] || { printf 'ERROR: no shared provider metadata in %s\n' "$_shared_src/module.d" >&2; exit 1; }
|
|
118
|
-
cp "$_shared_meta" "$_shared_dst/module.d/"
|
|
119
|
-
chmod 0644 "$_shared_dst/module.d/$(basename "$_shared_meta")"
|
|
120
|
-
done
|
|
121
|
-
for _shared_area in "$_shared_src"/modules/*; do
|
|
122
|
-
[ -d "$_shared_area" ] || continue
|
|
123
|
-
mkdir -p "$_shared_dst/modules/$(basename "$_shared_area")"
|
|
124
|
-
for _shared_body in "$_shared_area"/*.sh; do
|
|
125
|
-
[ -f "$_shared_body" ] || continue
|
|
126
|
-
cp "$_shared_body" "$_shared_dst/modules/$(basename "$_shared_area")/"
|
|
127
|
-
chmod 0644 "$_shared_dst/modules/$(basename "$_shared_area")/$(basename "$_shared_body")"
|
|
128
|
-
done
|
|
129
|
-
done
|
|
130
|
-
_shared_rev=$(cd "$_shared_src" && git rev-parse HEAD 2>/dev/null || printf 'unknown')
|
|
131
|
-
printf 'provider=examples/shared\nrevision=%s\n' "$_shared_rev" > "$_shared_dst/layer-pin.txt"
|
|
132
|
-
chmod 0644 "$_shared_dst/layer-pin.txt"
|
|
133
|
-
|
|
134
|
-
# Normalise file modes before manifesting
|
|
135
|
-
find "$_out_dir" -type f -exec chmod 0644 {} +
|
|
136
|
-
|
|
137
|
-
# --- Generate manifest using valise CLI ---
|
|
138
|
-
"$_valise" make-manifest "$_out_dir"
|
package/examples/local/.gitkeep
DELETED
|
File without changes
|