Commit 8e72e62
authored
feat(subos): subos-as-xpkg system (M1-M5) (#296)
* feat(xim): map PackageType::Subos to pkgType=4
Mirrors upstream mcpplibs/libxpkg enum addition. Foundation for
type=subos package dispatch — see
.agents/docs/subos-as-xpkg-design-2026-05-16.md (Phase 0 / Task 1).
Requires upstream commit "feat(xpkg): add PackageType::Subos for
subos-as-xpkg" on mcpplibs/libxpkg feat/pkgtype-subos branch.
* feat(xim): dispatch type='subos' through default install/config/uninstall
Adds xim::subos namespace mirroring the script.cppm pattern. Default
hooks:
- install: ensure install_dir + bin/ skeleton; synthesize .xlings.json
workspace from xpm.deps when tarball doesn't carry one
- config: register via xvm.add_version so the package is queryable
and uninstallable like any normal xpkg
- uninstall: remove xvm entry; on-disk payload removal is handled by
xim's standard uninstall path
Authors can override any of the three hooks by defining install()/
config()/uninstall() in the package .lua. The existing executor's
has_hook() check still routes to user code first.
Package path convention is unchanged — type='subos' packages land at
xpkgs/<namespace>-x-<name>/<ver>/, identical to xim-x-foo / scode-x-foo.
E2E test covers: install path, xpkgs layout, .xlings.json synthesis,
xvm registration. Fixture in tests/e2e/fixtures/subos_xpkg/py-demo.lua.
Refs: .agents/docs/subos-as-xpkg-design-2026-05-16.md (M1)
* feat(subos): subos use --cmd <string> for non-interactive exec
Extends 'xlings subos use' with --cmd <string> (and --cmd=<value>)
to run a single command in the subos and exit with the command's
exit code. POSIX: shell -c <cmd>; Windows: pwsh -Command / cmd /c.
Works in both shell-level and sandbox modes; threaded through
build_bwrap_argv_ and build_proot_argv_ to append -c <cmd>.
Rejected combinations:
--cmd + --global : --global persists active subos, doesn't spawn
--cmd + --shell : --shell emits eval-able env code, no shell to exec
E2E coverage: stdout capture, exit-code propagation, incompatible
flag combinations, --cmd=<value> equals form.
Refs: .agents/docs/subos-as-xpkg-design-2026-05-16.md (M3)
* feat(subos): subos new --from <spec> for fork from local subos or pkg
Adds `xlings subos new <name> --from <spec>` which forks the new subos
from either:
- a local subos (bare name, e.g. --from base-env): copies content
from subos/<base>/ to subos/<new>/
- a pkg-spec (contains ':' or '@', e.g. --from subos:py-ds@1.0.0):
locates xpkgs/<ns>-x-<name>/<ver>/; if not yet installed,
auto-invokes `xlings install <spec>` (E5: agent always 1 command)
Cross-platform copy uses reflink-where-possible (Linux btrfs/xfs,
macOS APFS clonefile); falls back to full byte copy via
std::filesystem::copy on Windows / non-COW filesystems. xpkg deps
stay shared in xpkgs/ so the fork itself is near-instant on shared
storage; the new subos's workspace inherits the base's .xlings.json.
Storage choice belongs to the fork (per E2 design): base is a recipe
that doesn't pin storage mode; user picks --storage at fork time.
copy_tree_ overlays base content, then storage/imageSize fields in
.xlings.json are re-applied so the new subos's storage wins.
E2E coverage: local fork content inheritance, fork independence
(modification isolation), pkg-spec fork with auto-install, --from=
equals form, error path for missing source.
Refs: .agents/docs/subos-as-xpkg-design-2026-05-16.md (M2, E1-E5)
* feat(subos): auto-keeper primitives + --keep/--no-keep/--ttl + subos stop
Adds the keeper module (Linux-focused, cross-platform stubs) that
holds bwrap's mount namespace alive between sandboxed --cmd execs
so high-frequency agent workloads avoid per-call mount overhead.
This commit lands:
- keeper.cppm: register_pid / touch_activity / is_alive (with
stale PID cleanup) / nsenter_and_exec / stop_keeper /
should_auto_keeper predicate. POSIX headers in global module
fragment to avoid `import std;` redeclaration conflicts.
- subos.cppm: argparse for --keep / --no-keep / --ttl <sec> on
`subos use`; mutual-exclusion validation; integer-parse error
handling for --ttl.
- `xlings subos stop <name>` CLI: SIGTERM then SIGKILL fallback,
cleans .keeper.pid + .keeper.lastused. Idempotent — safe to call
when no keeper is running.
- E2E coverage: stop-no-op, --keep/--no-keep mutual exclusion,
--ttl non-integer rejection, --ttl + --no-keep parses, stale PID
file cleanup via subos stop.
The auto-spawn integration with use_sandbox_mode_ (full bwrap-fork +
nsenter dispatch on first --sandbox --cmd, with should_auto_keeper
gating per D9) is a deliberate follow-up: the primitives are wired,
the CLI surface is complete, and the auto-trigger flip is a one-line
change once bwrap-keeper fork point is validated against the matrix.
Refs: .agents/docs/subos-as-xpkg-design-2026-05-16.md (M4 + M5, D9)
* docs: subos-as-xpkg design (rev4) + implementation plan
Design doc records the converged subos-as-xpkg architecture across
revisions:
rev1: initial brainstorming convergence
rev2: simplification (no Lua API needed)
rev3: bring back type='subos' + default hooks; sandbox/storage
decisions; xvm-as-normal-package registration
rev4: auto-keeper with TTL=5min idle (M4); explicit overrides (M5)
Plan decomposes into 11 tasks across 5 phases (Phase 0 + M1-M5),
with parallel/sequential dependencies noted so a downstream
subagent run can fan out where the file map allows. Each task has
TDD-style checkpoints + exact file paths.
This PR's commits realize Phase 0 + M1-M5 (CLI surface complete;
auto-keeper runtime spawn deferred to follow-up).
Refs design: .agents/docs/subos-as-xpkg-design-2026-05-16.md
Refs plan: docs/superpowers/plans/2026-05-16-subos-as-xpkg.md
* chore: bump mcpplibs-xpkg dep to 0.0.41 (PackageType::Subos)
Pulls in the upstream Subos enum addition required by the
subos-as-xpkg dispatch. Replaces the local_libxpkg dev override that
was needed before openxlings/libxpkg#23 merged.
Refs: mcpplibs/mcpplibs-index#13, openxlings/libxpkg#23
* chore(0.4.36): bump version for release
Includes:
- feat(subos): subos-as-xpkg system (M1-M5)
- type='subos' xpkg dispatch + default install/config/uninstall hooks
- subos new --from <local|pkg-spec> fork with auto-install
- subos use --cmd <string> non-interactive exec (POSIX + Windows)
- keeper primitives + --keep/--no-keep/--ttl flags + subos stop
- chore: bump mcpplibs-xpkg dep to 0.0.41 (brings PackageType::Subos)1 parent 884f95b commit 8e72e62
15 files changed
Lines changed: 3203 additions & 22 deletions
File tree
- .agents/docs
- docs/superpowers/plans
- src/core
- subos
- xim
- libxpkg/types
- tests/e2e
- fixtures/subos_xpkg
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| |||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
28 | 29 | | |
29 | 30 | | |
30 | 31 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| |||
1361 | 1362 | | |
1362 | 1363 | | |
1363 | 1364 | | |
| 1365 | + | |
| 1366 | + | |
| 1367 | + | |
| 1368 | + | |
| 1369 | + | |
| 1370 | + | |
| 1371 | + | |
| 1372 | + | |
| 1373 | + | |
1364 | 1374 | | |
1365 | 1375 | | |
1366 | 1376 | | |
| |||
1445 | 1455 | | |
1446 | 1456 | | |
1447 | 1457 | | |
| 1458 | + | |
| 1459 | + | |
| 1460 | + | |
| 1461 | + | |
| 1462 | + | |
| 1463 | + | |
| 1464 | + | |
| 1465 | + | |
1448 | 1466 | | |
1449 | 1467 | | |
1450 | 1468 | | |
| |||
1598 | 1616 | | |
1599 | 1617 | | |
1600 | 1618 | | |
1601 | | - | |
| 1619 | + | |
1602 | 1620 | | |
| 1621 | + | |
1603 | 1622 | | |
1604 | 1623 | | |
1605 | | - | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
1606 | 1628 | | |
1607 | 1629 | | |
1608 | | - | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
1609 | 1634 | | |
| 1635 | + | |
1610 | 1636 | | |
1611 | | - | |
1612 | 1637 | | |
| 1638 | + | |
| 1639 | + | |
1613 | 1640 | | |
1614 | 1641 | | |
1615 | 1642 | | |
| |||
0 commit comments