template-jj/cmd/planctl/proc_darwin.go
sid 935b86b791 feat(planctl): context-window token awareness — core (parent 1.0)
- TokenCtx + Classify + formatTokenCount (R2.2, R3.1-3.5, R4.4)
- ReadTokenCtx orchestrator: env > PID walk > transcript parse (R1.1-1.6, R2.1-2.6)
- parseLastUsage: 10MB scanner, JSONL last-assistant-wins, zero-usage qualifies (R2.1-2.3)
- parsePIDFile: strict two-line layout; rejects partial/corrupted writes (R6.2-6.3)
- resolveViaPIDWalk: 8-hop ancestor walk, liveness + start-stamp check (R1.2, R6.1, R6.3)
- proc_darwin.go (x/sys/unix kinfo_proc) + proc_linux.go (/proc/stat field 22)
- parseStatStartTime: platform-agnostic, handles comm with parens/spaces

Parent 1.0 from dev/plans/26174-planctl-context-tokens/tasks.md
2026-04-23 17:38:37 -06:00

44 lines
1.2 KiB
Go

//go:build darwin
package main
import (
"syscall"
"golang.org/x/sys/unix"
)
// NOTE: design §7 says "stdlib + goldmark only", but stdlib syscall on modern Go
// no longer exposes KinfoProc/SysctlRaw on macOS. Using golang.org/x/sys/unix
// (the de-facto-stdlib extension) is the least-fragile alternative to hand-rolling
// struct layouts against raw sysctl bytes. Design divergence noted.
// spec:26174-planctl-context-tokens/R1.2+R6.3+D§3.3
// ppidOf returns the parent PID of pid, or 0 on error.
func ppidOf(pid int) int {
kp, err := unix.SysctlKinfoProc("kern.proc.pid", pid)
if err != nil {
return 0
}
return int(kp.Eproc.Ppid)
}
// spec:26174-planctl-context-tokens/R6.3+D§3.3
// processAlive reports whether a process with pid exists.
func processAlive(pid int) bool {
if pid <= 0 {
return false
}
return syscall.Kill(pid, 0) == nil
}
// spec:26174-planctl-context-tokens/R6.3+D§3.3+D§4.1
// processStartTimeSec returns the process start time as seconds since the Unix epoch,
// read from kinfo_proc.kp_proc.p_starttime.tv_sec on macOS.
func processStartTimeSec(pid int) (int64, error) {
kp, err := unix.SysctlKinfoProc("kern.proc.pid", pid)
if err != nil {
return 0, err
}
return int64(kp.Proc.P_starttime.Sec), nil
}