You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(amico-run): attribute CPU cost to principal and Lab using the solve unit's cgroup CPU, not process.cpuUsage() #2132
Central-hub cost ledger (ADR 0041 §5; replaces the approach in #2121, which measured process.cpuUsage(): the engine process only, not the Julia child, so every solve would be costed at about zero). A1 runs each solve in its own transient unit amico-run-<id>.service, whose cgroup accounts the solve's real CPU including all child threads.
What
Add principal, lab, cpu_seconds to ReceiptRecord (+ ledger-record.schema.json), and costTotals rollup by principal and Lab. Keep the optionality: unattributed runs roll up under (unattributed).
Measure CPU from the unit's cgroup: on Linux read cpu.statusage_usec of the run's cgroup (find it via the A1 run.lock unit name / systemctl --user show -p ControlGroup), read BEFORE the unit is torn down and again at settle; the delta is cpu_seconds. Where no cgroup is available (macOS, a run not in a unit), fall back to child rusage if obtainable, else record cpu_seconds absent and cost_basis: unmeasured. NEVER fall back to process.cpuUsage().
Cost = cpu_seconds x a rate read from a human-edited config file (~/.amico/amicode/rates.json), default 0, so an unconfigured install records seconds and no invented dollars. Label every dollar figure basis: list_price_estimate.
Never fail a run because accounting failed.
Acceptance Criteria
a test runs a real child process that burns CPU in a transient cgroup/unit (or a faithful temp cgroup fixture) and asserts cpu_seconds reflects the CHILD's CPU, and that a parent that only waits records ~0 for itself.
a test proves process.cpuUsage() is never used (a run whose engine process is idle but whose child burns 1+ s must record >= 1 s).
no rate configured => seconds recorded, no cost_usd; rate configured => cost_usd = seconds x rate with basis list_price_estimate.
unattributed runs roll up under (unattributed); principal and Lab rollups sum to the total.
accounting failure never fails or changes the exit code of a run.
Activity