Files
my-pi/pi-permission-system/src/authority/subagent-detection.ts
T

67 lines
2.1 KiB
TypeScript

import {
isRegisteredSubagentChild,
isSubagentExecutionContext,
type SubagentDetectionContext,
} from "#src/authority/subagent-context";
import type { SubagentSessionRegistry } from "#src/authority/subagent-registry";
import type { PathFlavor } from "#src/path/path-flavor";
/**
* Narrow seam for the ask-path consumers: "is the current session a subagent?"
*
* `selectAuthorizer`/`AuthorizerSelection` and `ForwardingManager` depend on
* this single-method view so their unit tests inject a one-field fake without
* casts. It is the Authorizer-selection predicate the Phase 9 spine consumes.
*/
export interface SubagentDetector {
isSubagent(ctx: SubagentDetectionContext): boolean;
}
/**
* Narrow seam for the service-publication guard (#302): "is the current
* session a registered in-process child?"
*
* `PermissionServiceLifecycle` depends on this single-method view so a
* registered child never publishes over its parent's process-global slot.
*/
export interface RegisteredChildDetector {
isRegisteredChild(ctx: SubagentDetectionContext): boolean;
}
/** Composition-root inputs for {@link SubagentDetection}. */
export interface SubagentDetectionDeps {
subagentSessionsDir: string;
flavor: PathFlavor;
registry?: SubagentSessionRegistry;
}
/**
* Single owner of subagent detection.
*
* Constructed once in the composition root with the detection inputs
* (`subagentSessionsDir`, `flavor`, `registry`) and shared across every
* consumer, replacing the dep triple those consumers previously threaded
* individually. Delegates to the pure detection functions in
* {@link ./subagent-context}, holding only the deps.
*/
export class SubagentDetection
implements SubagentDetector, RegisteredChildDetector
{
constructor(private readonly deps: SubagentDetectionDeps) {}
isSubagent(ctx: SubagentDetectionContext): boolean {
return isSubagentExecutionContext(
ctx,
this.deps.subagentSessionsDir,
this.deps.flavor,
this.deps.registry,
);
}
isRegisteredChild(ctx: SubagentDetectionContext): boolean {
return this.deps.registry
? isRegisteredSubagentChild(ctx, this.deps.registry)
: false;
}
}