Skip to content

Commit 467f890

Browse files
committed
docs: substantive CRG C annotation (EXPLAINME.adoc)
1 parent cce2320 commit 467f890

File tree

1 file changed

+140
-7
lines changed

1 file changed

+140
-7
lines changed

EXPLAINME.adoc

Lines changed: 140 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,158 @@
11
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
23
= Modshells: Modular Shell Configuration Manager — Show Me The Receipts
34
:toc:
45
:icons: font
56

6-
The README makes claims. This file backs them up.
7+
The README makes claims. This file backs them up. For each headline feature:
8+
what makes it work, where the code is, and an honest caveat.
9+
10+
== Claim: Idempotent modularisation across ten shells
711

812
[quote, README]
913
____
10-
This project must declare **MPL-2.0-or-later** for platform/tooling compatibility.
14+
All Modshells operations are idempotent: running the tool multiple times
15+
produces the same result. Existing configurations are never destroyed.
16+
Automatic backup before any modification.
1117
____
1218

13-
== File Map
19+
Idempotency works through signature-based detection. Before injecting any
20+
sourcing block, `Shell_Manager.Modularise_Shell` calls `Is_Already_Modularised`
21+
which scans the target config file for the string `MODSHELLS_START`. If found,
22+
the shell is skipped entirely. If absent, the procedure creates a timestamped
23+
backup (`<path>.modshells-backup-YYYYMMDD-HHMMSS`) then appends the
24+
shell-specific sourcing block delimited by `MODSHELLS_START` / `MODSHELLS_END`
25+
markers. The entry point `Modshells` in `src/main/modshells.adb` calls
26+
`Shell_Manager.Modularise_All_Shells` which iterates `Detect_Shells` and
27+
applies this pattern to every installed shell in a single pass.
28+
29+
**Caveat:** The signature check is text-based. A user who manually edits
30+
the markers or copies config files between machines could confuse the check.
31+
There is no cryptographic protection on the injected block; it trusts the
32+
filesystem.
33+
34+
- Implementation: `src/shell_manager/shell_manager.adb` — `Modularise_Shell`,
35+
`Is_Already_Modularised`, `Create_Backup`, `Get_Sourcing_Block`
36+
- Interface spec: `src/shell_manager/shell_manager.ads`
37+
38+
== Claim: Written in Ada for safety-critical reliability
39+
40+
[quote, README]
41+
____
42+
Built in Ada for maximum reliability: strong static typing catches errors at
43+
compile time, exception handling ensures graceful failure, no unsafe memory
44+
operations, deterministic behaviour.
45+
____
46+
47+
The entire core is Ada 2012, compiled with GPRBuild via `modshells.gpr`. The
48+
package hierarchy separates concerns cleanly: `Config_Store` resolves paths
49+
(reads `MODSHELLS_CONFIG_PATH` or defaults to `~/.config/nushell/modshells`),
50+
`Shell_Manager` owns all shell-specific knowledge, and `Shell_Validator`
51+
provides input guards. Ada's discriminant-constrained `Shell_List` array type
52+
(declared in `shell_manager.ads`) prevents buffer overruns by construction.
53+
The top-level `exception when others => raise` in `modshells.adb` ensures
54+
that any unhandled error surfaces rather than silently failing.
55+
56+
**Caveat:** The Ada runtime exception handler re-raises, so the binary will
57+
exit with a non-zero code on failure but the error message is plain text —
58+
there is no structured error output yet. Unit tests are in
59+
`tests/unit/test_shell_manager.adb` but the test suite is smoke-test-level
60+
rather than exhaustive at v0.1.
61+
62+
- Project file: `modshells.gpr`
63+
- Entry point: `src/main/modshells.adb`
64+
- Package spec: `src/shell_manager/shell_manager.ads`
65+
- Tests: `tests/smoke_test.sh`, `tests/unit/`
66+
67+
== Dogfooded Across The Account
1468

1569
[cols="1,2"]
1670
|===
71+
| Technology | Also Used In
72+
73+
| **Ada / GPRBuild** | https://github.com/hyperpolymath/modshells[modshells] is the primary
74+
Ada CLI in the account; Ada is also used in safety-critical FFI layers across
75+
repos that require GNAT ecosystem tools
76+
| **POSIX shell config patterns** | Used as the human-readable layer in
77+
https://github.com/hyperpolymath/developer-ecosystem[developer-ecosystem]
78+
shell tooling and https://github.com/hyperpolymath/ambientops[ambientops]
79+
personal sysadmin scripts
80+
| **Guix + Nix packaging** | `guix.scm` / `flake.nix` present in all RSR repos;
81+
see https://github.com/hyperpolymath/proof-of-work[proof-of-work],
82+
https://github.com/hyperpolymath/burble[burble], and dozens of others
83+
|===
84+
85+
== File Map
86+
87+
[cols="1,3"]
88+
|===
1789
| Path | What's There
1890

19-
| `src/` | Source code
20-
| `test(s)/` | Test suite
91+
| `src/main/modshells.adb`
92+
| Entry point. Three-step procedure: create directories, detect shells,
93+
modularise all installed shells. Exception handler at top level.
94+
95+
| `src/shell_manager/shell_manager.ads`
96+
| Public interface spec. Declares `Shell_Type` (10-member enum), `Shell_Status`,
97+
`Shell_Info` record, `Shell_List` unconstrained array, and all function
98+
signatures used by the main procedure.
99+
100+
| `src/shell_manager/shell_manager.adb`
101+
| Implementation. Contains `Is_Shell_Installed` (checks `/usr/bin`, `/bin`,
102+
`/usr/local/bin`, `/opt/homebrew/bin`), `Get_Sourcing_Block` (generates
103+
shell-specific syntax for POSIX, Fish, Nushell, Tcsh, Ion, PowerShell),
104+
`Create_Backup`, `Is_Already_Modularised`, `Modularise_Shell`, and
105+
`Modularise_All_Shells`.
106+
107+
| `src/config_store/config_store.adb`
108+
| Resolves the modshells root path. Reads `MODSHELLS_CONFIG_PATH` environment
109+
variable; falls back to `~/.config/nushell/modshells`.
110+
111+
| `src/shell_validator/`
112+
| Input guards (separate from shell_manager to avoid circular dependencies).
113+
114+
| `tests/smoke_test.sh`
115+
| Shell-based smoke test: checks source files exist, SPDX headers present,
116+
binary runs, directory creation works, idempotency check passes.
117+
118+
| `tests/unit/test_shell_manager.adb`
119+
| Ada unit tests for Shell_Manager functions. Built separately via `tests/tests.gpr`.
120+
121+
| `tests/e2e/`
122+
| End-to-end tests against a live shell environment.
123+
124+
| `tests/property/`
125+
| Property-based tests (QuickCheck style).
126+
127+
| `examples/`
128+
| Ready-to-use config snippets: `core/00-path.sh`, `tools/git.sh`, `tools/fzf.sh`,
129+
`misc/aliases.sh`, `os/linux.sh`, `ui/colours.sh`, and others.
130+
131+
| `modshells.gpr`
132+
| GPRBuild project file. Source directories, object output path (`obj/`),
133+
binary output path (`bin/`).
134+
135+
| `guix.scm` / `flake.nix`
136+
| Package manager manifests (primary: Guix; fallback: Nix).
137+
138+
| `.machine_readable/6a2/`
139+
| A2ML checkpoint files: STATE, META, ECOSYSTEM, AGENTIC, NEUROSYM, PLAYBOOK.
21140
|===
22141

23-
== Questions?
142+
== Checking It
143+
144+
[source,bash]
145+
----
146+
# Build
147+
gprbuild -p -j0 modshells.gpr
148+
149+
# Smoke test (does not require build)
150+
./tests/smoke_test.sh
151+
152+
# Unit tests
153+
gprbuild -p -j0 -P tests/tests.gpr
154+
./bin/test_shell_manager
24155
25-
Open an issue or reach out directly — happy to explain anything in more detail.
156+
# Dry-run (inspect what would be changed)
157+
MODSHELLS_CONFIG_PATH=/tmp/modshells-test ./bin/modshells
158+
----

0 commit comments

Comments
 (0)