Files
nanoclaw/src/modules/self-mod/project.md
gavrielc 95fdec335a refactor(modules): re-tier approvals as default; extract self-mod as optional
Promotes approvals to the default tier with a public API (requestApproval +
registerApprovalHandler) that other modules consume. Self-modification
(install_packages / request_rebuild / add_mcp_server) moves into a new
optional module that registers delivery actions + matching approval handlers
via the new API.

## Approvals (default tier)

- Adds `src/modules/approvals/primitive.ts` exporting `requestApproval`,
  `registerApprovalHandler`, `notifyAgent`. Absorbs `pickApprover` /
  `pickApprovalDelivery` / `channelTypeOf` from the deleted `src/access.ts`.
- Rewrites `response-handler.ts` to dispatch to registered approval handlers
  on approve (action-keyed Map). Reject path is centralized.
- Drops the three self-mod-specific delivery-action registrations from
  `approvals/index.ts`; they belong to self-mod now.
- `onecli-approvals.ts` now imports picks from the primitive instead of
  `src/access.ts`.

## Self-mod (optional tier)

- New `src/modules/self-mod/` with request handlers (validate input + call
  requestApproval) and apply handlers (orchestration on approve).
- `apply.ts` owns updateContainerConfig + buildAgentGroupImage + killContainer
  calls. Self-mod depends on approvals (via registerApprovalHandler +
  requestApproval + notifyAgent) and on core (container-runner, container-config).
- Registers 3 delivery actions + 3 approval handlers at import time.

## Other changes

- `src/access.ts` and `src/access.test.ts` deleted. Tests split across
  `src/modules/approvals/picks.test.ts` (approver selection) and
  `src/modules/permissions/permissions.test.ts` (access + roles + DM).
- `src/modules/index.ts` barrel: approvals loads before self-mod so
  registerApprovalHandler is bound when self-mod registers at import time.

## Validation

- `pnpm run build` clean
- `pnpm test` — 137 host tests pass
- `bun test` in container/agent-runner — 17 tests pass
- Service starts; boot log shows `OneCLI approval handler started`,
  `NanoClaw running`; clean SIGTERM shutdown

Resolves the transitional tier violation flagged in PR #5 where core
imported from the permissions optional module via `src/access.ts`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 19:41:26 +03:00

1.4 KiB

Self-mod module

Optional-tier module that gives agents admin-gated self-modification: installing OS/npm packages, rebuilding the container image, and registering new MCP servers. All three paths go through the approvals module's request primitive — no unapproved changes ever land.

What this module adds

  • Three delivery actions (install_packages, request_rebuild, add_mcp_server) that the container's self-mod MCP tools write into outbound.db. On the host, each handler validates input and queues an approval via approvals.requestApproval().
  • Three matching approval handlers that run on approve: mutate the container config via updateContainerConfig, rebuild the image via buildAgentGroupImage, and kill the container so the host sweep respawns it on the new image.

Dependency

Self-mod depends on the approvals default module for:

  • requestApproval() to enqueue admin confirmation cards
  • registerApprovalHandler(action, handler) to run orchestration on approve
  • notifyAgent() to send failure feedback back to the requesting agent

It also calls core's buildAgentGroupImage, killContainer, and updateContainerConfig.

Removing the module

Delete src/modules/self-mod/ and its import line in src/modules/index.ts. The container's self-mod MCP tools will still write outbound system messages, but core delivery will log "Unknown system action" and drop them — no admin card, no container mutation.