AMC is a local fixture/compatibility launcher and diagnostic tool for systemd
memory policy. RFC 0.4 in docs/rfc-v0.4/ is authoritative. It is not a policy
standard, resident daemon, sandbox, or transparent replacement for normal
application launching.
Real applications stay with their existing native lifecycle owner. For
OpenCode, the discovered shared backend is opencode.service; wrapping an
activation client does not configure that backend. See
native integration.
amc inspect opencode.service --json
amc inspect some-system-unit.service --system --json
./scripts/prove-local.sh opencode.serviceInspection is passive: it does not start services or change policy. It queries allowlisted manager metadata and samples the leaf and visible cgroup ancestry. Each snapshot has a timestamp; unavailable/malformed measurements have a null value and a reason, never an invented zero. The visible mount root is a namespace boundary, not proof that no hidden ancestor exists. Manager queries are bounded to 2 seconds and 64 KiB each; ancestry has a disclosed 64-cgroup limit and a 10-second manager-query budget (one in-flight query can add 2 seconds).
Default text/JSON diagnostics omit application journal messages, ExecStart,
Environment, and arbitrary subprocess error streams. This is omission, not
a general-purpose secret scrubber. amc run forwards workload output as a
separate raw interface; do not publish it as a sanitized diagnostic report.
amc doctor is not passive: it creates and cleans up a short-lived transient
capability probe with fixture settings. Run it only deliberately; the local
script does not run it automatically. --host-stress is explicitly rejected.
amc --config examples/config.toml explain --id amc.proof --json
amc --config examples/config.toml run --id amc.proof --unit-file /private/attempt.unit -- command argThe private TOML interface retains version 1 and its existing search order:
explicit --config, XDG config, HOME config, then /etc/xdg/amc/config.toml.
It is used only when these fixture tools are invoked. It does not configure
native application services. Requested values are not effective values until
observed; submitted properties and native drop-ins can conflict. No custom
policy merge engine is provided.
Fixtures request OOMPolicy=kill, Restart=no, memory accounting, max/swap
limits and optional MemoryHigh. They do not emit a KillMode override.
An absent optional high value is not emitted. Fixture byte parsing is not a
validator for every legal native systemd value. Fixture numbers are not
production defaults, and max-only tests are not recommendations against high.
The existing systemd-run service backend preserves literal argv,
--expand-environment=no, cwd, environment-name allowlisting, and PTY/pipe
selection. No scope or direct-D-Bus backend is added.
Each attempt has one generated unit identity. --unit-file publishes it
privately before submission. Spawn failure is distinct from rejected or
ambiguous submission. Startup control is bounded; after an observed start,
amc run has no AMC runtime deadline. --runtime-max-sec explicitly gives a
disposable fixture a separate manager-enforced runtime bound. Detached launches
remain running after successful acknowledgment.
SIGINT/SIGTERM during submission triggers bounded cleanup of only that attempt. An absent/collected unit or unavailable manager leaves an explicit UNKNOWN outcome. There is no retry, unrestricted fallback, or promise of cleanup after SIGKILL or manager unavailability. Inspect the recorded identity before any manual retry; work may already have happened.
Helper self-checks observe settings at helper entry, before allocation. They do not prove arbitrary loader/constructor ordering or fail-closed launch under every controller failure. That stronger strict-launch guarantee remains unsupported. Systemd continues to own execution and placement.
--retain-unit does not retain kernel counters. Collect evidence while the
cgroup exists; holding file descriptors also provides no indefinite retention
guarantee. Limits are accounting/reclaim controls, not preallocated RAM, an exact
instantaneous physical ceiling, or a fixed-time recovery promise.
Use the project-local direnv environment pinned by flake.lock. Review .envrc
and authorize it once with direnv allow .; it deliberately does not source the
parent canix environment or fall back to a stale shell. The first load may fetch
the pinned toolchain. direnv exec also works in noninteractive agent sessions:
direnv allow .
direnv exec . cargo fmt --all --check
direnv exec . cargo test --all-targets --locked -j 2
direnv exec . cargo clippy --all-targets --locked -j 2 -- -D warnings
direnv exec . python3 scripts/check-fixtures.py
nix flake check --no-build --no-write-lock-file --all-systemsVM tests remain outside ordinary checks. Only after cheap gates pass:
nix build --no-write-lock-file --max-jobs 1 --cores 2 .#nixosTests.x86_64-linux.genericThe VM target contains mechanism tests and small A/B/C smoke tests, not a validated pressure benchmark. It exports observer snapshots and explicit work report files. Pressure/high-max/aggregate comparisons and OpenCode UX trials are deferred until mechanism gates actually pass. See the corrective results and checklist.
The optional NixOS AMC module installs the tool and private compatibility
configuration. Its slices remain fixture-specific. Nix/Lix daemon builders,
containers, remote work and independently launched servers are separate execution
domains. nixBuildPool remains disabled and blocked; this milestone neither caps
nor restarts a broker or production backend.