Files
rea/src/process/ProcessOwnershipProcessTree.ts
T
morluto 3c84080aab refactor(app): split Setup and ProcessOwnership modules (#628)
* refactor(domain): consolidate canonical ordering and digest helpers (#624)

* refactor(domain): consolidate canonical ordering and digest helpers

Single owner for code-point ordering (domain/canonicalOrdering.ts)
and canonical JSON digests (domain/comparisonSemantics.ts). Delete
all local compareCodePoints/compareText/digestCanonical duplicates
and migrate every importer. No re-export shims.

* fix(ci): allow slower real browser startup

* chore(config): remove dead eslint, dedupe scripts, cacheable turbo tasks

Delete eslint.config.js (oxlint is the linter), drop lint:dead alias,
pin smol-toml, fold jscpd/scan:todos into check:pr, make test:run
cacheable, align oxlint ignores.

* fix(config): hash all test inputs for cached runs

* docs: fix architecture diagram and pretty-print tool catalog

Drop dangling REPLAY edges, add dotnet/reference/error/evaluation
nodes. Emit 2-space JSON from the catalog generator and regenerate.

* test: extract shared fixtures, drop knip carve-outs

Dedupe android/apple session tests, bundler adapter headers, and
reconstruction helpers into tests/support fixtures. Delete unused
type aliases and the knip ignoreIssues block. Lower jscpd threshold
2.7 to 2.5.

* refactor(app): split Setup and ProcessOwnership modules

Extract SetupTypes/SetupHost from Setup.ts and move observation
helpers into ProcessOwnershipObservation/ProcessTree. Migrate all
importers including CLI commands. No re-export shims.
2026-10-06 05:00:32 +08:00

50 lines
1.9 KiB
TypeScript

import type { ProcessTableEntry } from "./ProcessOwnership.js";
/** Exclude process-table entries that the operating system has already reaped. */
export const liveProcesses = (
members: readonly ProcessTableEntry[],
): readonly ProcessTableEntry[] =>
members.filter(({ state }) => !state.startsWith("Z"));
/** Return every live-table descendant of a launcher in breadth-first order. */
export const descendantsOf = (
launcherPid: number,
processes: readonly ProcessTableEntry[],
): ProcessTableEntry[] => {
const childrenByParent = new Map<number, ProcessTableEntry[]>();
for (const process of processes) {
const siblings = childrenByParent.get(process.parentPid) ?? [];
siblings.push(process);
childrenByParent.set(process.parentPid, siblings);
}
const descendants: ProcessTableEntry[] = [];
const pending = [...(childrenByParent.get(launcherPid) ?? [])];
const visited = new Set<number>([launcherPid]);
for (const process of pending) {
if (visited.has(process.pid)) continue;
visited.add(process.pid);
descendants.push(process);
pending.push(...(childrenByParent.get(process.pid) ?? []));
}
return descendants;
};
/** Select the PTY root group and groups led by an observed captured process. */
export const selectCapturedProcessGroupIds = (
rootPid: number,
samples: readonly {
readonly pid: number;
readonly process_group_id: number | null;
}[],
): readonly number[] => {
const processGroupIds = new Set<number>([rootPid]);
for (const sample of samples) {
// A sampled member may transiently inherit an unrelated group. POSIX group
// leaders have pid === pgid, so only that observation establishes that the
// group leader itself belonged to the captured tree. Token checks below
// remain the final authority immediately before observation or signaling.
if (sample.pid === sample.process_group_id) processGroupIds.add(sample.pid);
}
return [...processGroupIds];
};