- 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
34 lines
1.2 KiB
Go
34 lines
1.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// spec:26174-planctl-context-tokens/R6.3+D§3.3
|
|
// parseStatStartTime extracts field 22 (starttime — clock ticks since boot)
|
|
// from a /proc/<pid>/stat line. The `comm` field at position 2 is wrapped in
|
|
// parens and can contain any bytes including spaces and parens; we tokenize
|
|
// only the remainder after the LAST ')' so comm contents can't shift indices.
|
|
//
|
|
// Lives in a non-build-tagged file so it compiles — and is testable — on all
|
|
// platforms. Only proc_linux.go's processStartTimeSec actually consumes it.
|
|
func parseStatStartTime(stat string) (int64, error) {
|
|
i := strings.LastIndex(stat, ")")
|
|
if i < 0 || i+1 >= len(stat) {
|
|
return 0, fmt.Errorf("stat: no ')' terminator")
|
|
}
|
|
// After the ')' we have: " state ppid ... starttime ..."
|
|
// Fields counted from 1 in the man page: (1) pid, (2) (comm), (3) state, ..., (22) starttime.
|
|
// Remainder starts at field 3, so starttime is index 19 (22-3).
|
|
fields := strings.Fields(stat[i+1:])
|
|
if len(fields) < 20 {
|
|
return 0, fmt.Errorf("stat: only %d tail fields", len(fields))
|
|
}
|
|
n, err := strconv.ParseInt(fields[19], 10, 64)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("stat: starttime parse: %w", err)
|
|
}
|
|
return n, nil
|
|
}
|