- 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
44 lines
1.2 KiB
Go
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
|
|
}
|