Skip to content

0.4.36

Choose a tag to compare

@github-actions github-actions released this 15 May 22:34
· 261 commits to main since this release
8e72e62
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)