@dsh-cc/subagent-task 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Process-level one-shot subagent ledger (memory-recall hardening follow-ups
3
+ * W2a, `docs/plans/2026-09-09-memory-recall-hardening-followups.md` §2 W2):
4
+ * one shared `subagent/start` + `subagent/end` listener pair (mirroring
5
+ * `epoch-collector.ts` wiring) folds every run the process observes into
6
+ * rows keyed by runId.
7
+ *
8
+ * Pairing is BY RUN ID, never by child id: a cold-resumed child gets a new
9
+ * runId and must not satisfy a stale watcher (epoch-collector's documented
10
+ * lesson). Parentage resolves from the child's session header
11
+ * `parentSession` via the `agents` seam (`ctx.agents.get(id)`), the same
12
+ * probe the TUI driver uses; unresolvable parentage is kept but treated as
13
+ * unscoped and never injected into any session's context.
14
+ *
15
+ * Internal (infra-fork) classification prefers the child's session
16
+ * descriptor metadata — the `subagent/descriptor` event's `label` — falling
17
+ * back to nothing (a child with no descriptor label is never internal on
18
+ * label grounds). {@link INTERNAL_LABELS} lists the production labels that
19
+ * must always classify as internal; a completeness test pins it.
20
+ *
21
+ * Rows prune by TTL both after ending AND while active (a crashed child may
22
+ * never emit `end`); an `end` arriving after its row was pruned is a no-op.
23
+ *
24
+ * @module @dsh-cc/subagent-task/one-shot-ledger
25
+ */
26
+ /** Production labels that mark a child as internal dsh-cc infrastructure. */
27
+ export declare const INTERNAL_LABELS: readonly string[];
28
+ /** One observed subagent run. */
29
+ export interface OneShotLedgerRow {
30
+ /** Unique identity shared by the paired start/end events. */
31
+ runId: string;
32
+ /** The child agent's (session) id. */
33
+ id: string;
34
+ /** Provider name snapshot from the events. */
35
+ provider: string;
36
+ /** Creation label from the child's session descriptor, when enumerable. */
37
+ label?: string;
38
+ /** Parent session id resolved from the child's session header, when resolvable. */
39
+ parentId?: string;
40
+ /** Wall-clock ms when the start event arrived. */
41
+ startedAt: number;
42
+ /** Wall-clock ms when the paired end event arrived. */
43
+ endedAt?: number;
44
+ /** Terminal stop reason from the end event. */
45
+ stopReason?: string;
46
+ /** True when the child is internal dsh-cc infrastructure (descriptor label ∈ {@link INTERNAL_LABELS}). */
47
+ internal: boolean;
48
+ /** Descriptor mode snapshot when enumerable (`one-shot` / `continuable`). */
49
+ mode?: string;
50
+ }
51
+ /** The duck-typed child-agent snapshot probed for parentage/label metadata. */
52
+ export interface LedgerChildSnapshot {
53
+ session?: {
54
+ id?: unknown;
55
+ header?: {
56
+ parentSession?: unknown;
57
+ };
58
+ events?: readonly {
59
+ type?: string;
60
+ data?: {
61
+ label?: unknown;
62
+ mode?: unknown;
63
+ };
64
+ }[];
65
+ };
66
+ }
67
+ /** Duck-typed `ctx.agents` accessor for child-session parentage probes. */
68
+ export interface LedgerAgents {
69
+ get?(id: string): LedgerChildSnapshot | undefined;
70
+ }
71
+ /** Duck-typed event bus (cordis `ctx.on`) the lifecycle events arrive on. */
72
+ export interface LedgerEventBus {
73
+ on(event: string, listener: (info: Record<string, unknown>) => void): (() => void) | void;
74
+ }
75
+ export interface OneShotLedgerDeps {
76
+ /** The bus the shared listener pair subscribes to. */
77
+ bus: LedgerEventBus;
78
+ /** The live agent registry (`ctx.agents`) used for parentage/label probes. */
79
+ agents?: LedgerAgents | undefined;
80
+ /** Wall clock; defaults to `Date.now`. */
81
+ now?: () => number;
82
+ /** How long an ended row stays queryable. Default 5 minutes. */
83
+ endedTtlMs?: number;
84
+ /** How long a never-ended (active) row stays queryable. Default 60 minutes. */
85
+ activeTtlMs?: number;
86
+ }
87
+ export declare const DEFAULT_ENDED_TTL_MS: number;
88
+ export declare const DEFAULT_ACTIVE_TTL_MS: number;
89
+ /**
90
+ * Create the ledger and attach its shared `subagent/start` / `subagent/end`
91
+ * listener pair to the bus (mirrors `epoch-collector`'s shared-watcher
92
+ * wiring). The returned handle prunes lazily on every read.
93
+ */
94
+ export declare function createOneShotLedger(deps: OneShotLedgerDeps): {
95
+ rows(): readonly OneShotLedgerRow[];
96
+ activeFor(parentId: string): readonly OneShotLedgerRow[];
97
+ dispose(): void;
98
+ };
99
+ //# sourceMappingURL=one-shot-ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"one-shot-ledger.d.ts","sourceRoot":"","sources":["../src/one-shot-ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAS5C,CAAA;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0GAA0G;IAC1G,QAAQ,EAAE,OAAO,CAAA;IACjB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE;QACR,EAAE,CAAC,EAAE,OAAO,CAAA;QACZ,MAAM,CAAC,EAAE;YAAE,aAAa,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;QACpC,MAAM,CAAC,EAAE,SAAS;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE;gBAAE,KAAK,CAAC,EAAE,OAAO,CAAC;gBAAC,IAAI,CAAC,EAAE,OAAO,CAAA;aAAE,CAAA;SAAE,EAAE,CAAA;KAClF,CAAA;CACF;AAED,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAAA;CAClD;AAED,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;CAC1F;AAED,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,GAAG,EAAE,cAAc,CAAA;IACnB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;IACjC,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,eAAO,MAAM,oBAAoB,QAAa,CAAA;AAC9C,eAAO,MAAM,qBAAqB,QAAc,CAAA;AAmBhD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG;IAC5D,IAAI,IAAI,SAAS,gBAAgB,EAAE,CAAA;IACnC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,gBAAgB,EAAE,CAAA;IACxD,OAAO,IAAI,IAAI,CAAA;CAChB,CAuDA"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Process-level one-shot subagent ledger (memory-recall hardening follow-ups
3
+ * W2a, `docs/plans/2026-09-09-memory-recall-hardening-followups.md` §2 W2):
4
+ * one shared `subagent/start` + `subagent/end` listener pair (mirroring
5
+ * `epoch-collector.ts` wiring) folds every run the process observes into
6
+ * rows keyed by runId.
7
+ *
8
+ * Pairing is BY RUN ID, never by child id: a cold-resumed child gets a new
9
+ * runId and must not satisfy a stale watcher (epoch-collector's documented
10
+ * lesson). Parentage resolves from the child's session header
11
+ * `parentSession` via the `agents` seam (`ctx.agents.get(id)`), the same
12
+ * probe the TUI driver uses; unresolvable parentage is kept but treated as
13
+ * unscoped and never injected into any session's context.
14
+ *
15
+ * Internal (infra-fork) classification prefers the child's session
16
+ * descriptor metadata — the `subagent/descriptor` event's `label` — falling
17
+ * back to nothing (a child with no descriptor label is never internal on
18
+ * label grounds). {@link INTERNAL_LABELS} lists the production labels that
19
+ * must always classify as internal; a completeness test pins it.
20
+ *
21
+ * Rows prune by TTL both after ending AND while active (a crashed child may
22
+ * never emit `end`); an `end` arriving after its row was pruned is a no-op.
23
+ *
24
+ * @module @dsh-cc/subagent-task/one-shot-ledger
25
+ */
26
+ /** Production labels that mark a child as internal dsh-cc infrastructure. */
27
+ export const INTERNAL_LABELS = [
28
+ // packages/memory/memory/src/recall.ts (the recall selector)
29
+ 'memory-recall',
30
+ // packages/memory/memory-consolidation/src/index.ts (startMemoryJob call sites)
31
+ 'extract-memories',
32
+ 'memory-consolidation',
33
+ // packages/hooks/hooks-claude-code/src/dispatch.ts (CC hook bridge forks)
34
+ 'hook-prompt',
35
+ 'hook-agent',
36
+ ];
37
+ export const DEFAULT_ENDED_TTL_MS = 5 * 60_000;
38
+ export const DEFAULT_ACTIVE_TTL_MS = 60 * 60_000;
39
+ function resolveDescriptor(child) {
40
+ const event = child?.session?.events?.find(e => e.type === 'subagent/descriptor');
41
+ if (event === undefined)
42
+ return {};
43
+ return {
44
+ ...event.data?.label !== undefined ? { label: String(event.data.label) } : {},
45
+ ...event.data?.mode !== undefined ? { mode: String(event.data.mode) } : {},
46
+ };
47
+ }
48
+ function resolveParentId(child) {
49
+ const parent = child?.session?.header?.parentSession;
50
+ return parent === undefined || parent === null || parent === '' ? undefined : String(parent);
51
+ }
52
+ /**
53
+ * Create the ledger and attach its shared `subagent/start` / `subagent/end`
54
+ * listener pair to the bus (mirrors `epoch-collector`'s shared-watcher
55
+ * wiring). The returned handle prunes lazily on every read.
56
+ */
57
+ export function createOneShotLedger(deps) {
58
+ const now = deps.now ?? Date.now;
59
+ const endedTtlMs = deps.endedTtlMs ?? DEFAULT_ENDED_TTL_MS;
60
+ const activeTtlMs = deps.activeTtlMs ?? DEFAULT_ACTIVE_TTL_MS;
61
+ // Rows the ledger keeps, keyed by runId (one row per epoch).
62
+ const rowsByRunId = new Map();
63
+ const offStart = deps.bus.on('subagent/start', info => {
64
+ const id = String(info.id);
65
+ const child = deps.agents?.get?.(id);
66
+ const descriptor = resolveDescriptor(child);
67
+ const label = descriptor.label;
68
+ const parentId = resolveParentId(child);
69
+ rowsByRunId.set(String(info.runId), {
70
+ runId: String(info.runId),
71
+ id,
72
+ provider: String(info.provider),
73
+ ...label !== undefined ? { label } : {},
74
+ ...parentId !== undefined ? { parentId } : {},
75
+ startedAt: now(),
76
+ internal: label !== undefined && INTERNAL_LABELS.includes(label),
77
+ ...descriptor.mode !== undefined ? { mode: descriptor.mode } : {},
78
+ });
79
+ });
80
+ const offEnd = deps.bus.on('subagent/end', info => {
81
+ const runId = String(info.runId);
82
+ const row = rowsByRunId.get(runId);
83
+ if (row === undefined)
84
+ return; // pruned or never started: a no-op
85
+ row.endedAt = now();
86
+ row.stopReason = String(info.stopReason);
87
+ });
88
+ const prune = () => {
89
+ const t = now();
90
+ for (const [runId, row] of rowsByRunId) {
91
+ if (row.endedAt !== undefined ? t - row.endedAt > endedTtlMs : t - row.startedAt > activeTtlMs) {
92
+ rowsByRunId.delete(runId);
93
+ }
94
+ }
95
+ };
96
+ return {
97
+ rows() {
98
+ prune();
99
+ return [...rowsByRunId.values()];
100
+ },
101
+ activeFor(parentId) {
102
+ prune();
103
+ return [...rowsByRunId.values()].filter(row => row.parentId === parentId && row.endedAt === undefined
104
+ // Unresolvable parentage is never scoped to any session.
105
+ && row.parentId !== undefined);
106
+ },
107
+ dispose() {
108
+ offStart?.();
109
+ offEnd?.();
110
+ },
111
+ };
112
+ }
113
+ //# sourceMappingURL=one-shot-ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"one-shot-ledger.js","sourceRoot":"","sources":["../src/one-shot-ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Parent-scoped subagent-child notice (memory-recall hardening follow-ups
3
+ * W2c): on `agent/pre-step`, ONLY the agent whose `session.id` matches a
4
+ * ledger row's `parentId` gets one folded observe-only line — contributed
5
+ * via `agent.inject()` + `createUserMessage` with a dedicated
6
+ * `MessageSourceMap` kind, mirroring `packages/memory/memory/src/recall.ts`'s
7
+ * contribution shape — when that session has ≥1 active non-internal
8
+ * one-shot child. Zero emission otherwise: sessions with no children see
9
+ * nothing; internal-only activity yields at most a folded count, never
10
+ * per-child rows.
11
+ *
12
+ * Registration follows `strip-instructions.ts` / `suppress-settled.ts`: a
13
+ * plain `agent/pre-step` waterfall listener that delegates to `next()`
14
+ * unchanged (observe-only). No `prepend` — unlike the strip, this listener
15
+ * reads only the ledger and its own agent, so ordering is irrelevant.
16
+ *
17
+ * @module @dsh-cc/subagent-task/one-shot-notice
18
+ */
19
+ import type { Context } from '@deepseek-ai/cordis';
20
+ import type { OneShotLedgerRow } from './one-shot-ledger.ts';
21
+ declare module '@deepseek-ai/dsh-llm' {
22
+ interface MessageSourceMap {
23
+ ccSubagentChild: {
24
+ kind: 'cc-subagent-children';
25
+ };
26
+ }
27
+ }
28
+ /** MessageSourceMap kind for the observe-only child notice. */
29
+ export declare const CHILD_NOTICE_SOURCE_KIND = "cc-subagent-children";
30
+ /**
31
+ * Fold the active children of one parent into the single observe-only line.
32
+ * Non-internal children surface their labels; internal children fold into a
33
+ * bare count (`… +N internal`), and internal-only activity yields a count
34
+ * line with no per-child rows at all.
35
+ */
36
+ export declare function foldChildNotice(rows: readonly {
37
+ label?: string;
38
+ internal: boolean;
39
+ }[]): string;
40
+ /** The ledger surface the notice listener reads. */
41
+ export interface ChildNoticeLedger {
42
+ activeFor(parentId: string): readonly OneShotLedgerRow[];
43
+ }
44
+ /**
45
+ * Mount the `agent/pre-step` child-notice listener.
46
+ * @param ctx - the plug context.
47
+ * @param ledger - the ledger to read.
48
+ * @returns an unmount callback.
49
+ */
50
+ export declare function mountSubagentChildNotice(ctx: Context, ledger: ChildNoticeLedger): () => void;
51
+ //# sourceMappingURL=one-shot-notice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"one-shot-notice.d.ts","sourceRoot":"","sources":["../src/one-shot-notice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAE5D,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,gBAAgB;QACxB,eAAe,EAAE;YAAE,IAAI,EAAE,sBAAsB,CAAA;SAAE,CAAA;KAClD;CACF;AAED,+DAA+D;AAC/D,eAAO,MAAM,wBAAwB,yBAAyB,CAAA;AAE9D;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,EAAE,GAAG,MAAM,CAW9F;AAED,oDAAoD;AACpD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,gBAAgB,EAAE,CAAA;CACzD;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAmB5F"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Parent-scoped subagent-child notice (memory-recall hardening follow-ups
3
+ * W2c): on `agent/pre-step`, ONLY the agent whose `session.id` matches a
4
+ * ledger row's `parentId` gets one folded observe-only line — contributed
5
+ * via `agent.inject()` + `createUserMessage` with a dedicated
6
+ * `MessageSourceMap` kind, mirroring `packages/memory/memory/src/recall.ts`'s
7
+ * contribution shape — when that session has ≥1 active non-internal
8
+ * one-shot child. Zero emission otherwise: sessions with no children see
9
+ * nothing; internal-only activity yields at most a folded count, never
10
+ * per-child rows.
11
+ *
12
+ * Registration follows `strip-instructions.ts` / `suppress-settled.ts`: a
13
+ * plain `agent/pre-step` waterfall listener that delegates to `next()`
14
+ * unchanged (observe-only). No `prepend` — unlike the strip, this listener
15
+ * reads only the ledger and its own agent, so ordering is irrelevant.
16
+ *
17
+ * @module @dsh-cc/subagent-task/one-shot-notice
18
+ */
19
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
20
+ /** MessageSourceMap kind for the observe-only child notice. */
21
+ export const CHILD_NOTICE_SOURCE_KIND = 'cc-subagent-children';
22
+ /**
23
+ * Fold the active children of one parent into the single observe-only line.
24
+ * Non-internal children surface their labels; internal children fold into a
25
+ * bare count (`… +N internal`), and internal-only activity yields a count
26
+ * line with no per-child rows at all.
27
+ */
28
+ export function foldChildNotice(rows) {
29
+ const visible = rows.filter(row => !row.internal);
30
+ const internalCount = rows.length - visible.length;
31
+ if (visible.length === 0 && internalCount === 0)
32
+ return '';
33
+ const parts = [];
34
+ if (visible.length > 0) {
35
+ const labels = visible.map(row => row.label ?? 'unlabeled');
36
+ parts.push(`${visible.length} active subagent child${visible.length === 1 ? '' : 'ren'}: ${labels.join(', ')}`);
37
+ }
38
+ if (internalCount > 0)
39
+ parts.push(`+${internalCount} internal`);
40
+ return `[observe] ${parts.join(' ')}`.trim();
41
+ }
42
+ /**
43
+ * Mount the `agent/pre-step` child-notice listener.
44
+ * @param ctx - the plug context.
45
+ * @param ledger - the ledger to read.
46
+ * @returns an unmount callback.
47
+ */
48
+ export function mountSubagentChildNotice(ctx, ledger) {
49
+ return ctx.on('agent/pre-step', async ({ agent }, next) => {
50
+ const decision = await next();
51
+ // Fire-and-forget: the notice is model-visible enrichment, never worth
52
+ // an unhandled rejection in the host.
53
+ try {
54
+ const sid = agent.session?.id;
55
+ if (sid === undefined)
56
+ return decision;
57
+ const active = ledger.activeFor(String(sid));
58
+ if (active.length === 0)
59
+ return decision;
60
+ agent.inject(createUserMessage({
61
+ content: [{ type: 'text', text: foldChildNotice(active) }],
62
+ source: { kind: 'cc-subagent-children' },
63
+ }));
64
+ }
65
+ catch {
66
+ // Absent llm seam or inject surface: skip quietly.
67
+ }
68
+ return decision;
69
+ });
70
+ }
71
+ //# sourceMappingURL=one-shot-notice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"one-shot-notice.js","sourceRoot":"","sources":["../src/one-shot-notice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AASxD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,wBAAwB,GAAG,sBAAsB,CAAA;AAE9D;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAsD;IACpF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACjD,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAClD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,aAAa,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,WAAW,CAAC,CAAA;QAC3D,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,yBAAyB,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACjH,CAAC;IACD,IAAI,aAAa,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,aAAa,WAAW,CAAC,CAAA;IAC/D,OAAO,aAAa,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAA;AAC9C,CAAC;AAOD;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAY,EAAE,MAAyB;IAC9E,OAAO,GAAG,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,EAAE,KAAK,EAAoB,EAAE,IAAI,EAA4B,EAAE;QACpG,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAA;QAC7B,uEAAuE;QACvE,sCAAsC;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,GAAI,KAAK,CAAC,OAAwC,EAAE,EAAE,CAAA;YAC/D,IAAI,GAAG,KAAK,SAAS;gBAAE,OAAO,QAAQ,CAAA;YACtC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;YAC5C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,QAAQ,CAAA;YACxC,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC;gBAC7B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1D,MAAM,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE;aACzC,CAAC,CAAC,CAAA;QACL,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Live enumeration of plugin agent providers over the `subagents` seam.
3
+ *
4
+ * The CC Task tool treats the seam's registered agent providers purely as a
5
+ * DEFINITION source: `cc-plugin-loader`'s `mountAgents` registers one
6
+ * `AgentProvider` per plugin agent under the scoped id
7
+ * `` `${pluginName}:${agentType}` `` (the `namespacePrefix` mechanism), and
8
+ * this index enumerates them live on every call — plugin mounts are
9
+ * effect-scoped Cordis contexts that may appear (or disappear) after this
10
+ * plugin's `apply()`, so nothing is cached.
11
+ *
12
+ * Builtin providers (`spawn`, `fork`, …) are excluded naturally: they carry
13
+ * no `definition`.
14
+ *
15
+ * @module @dsh-cc/subagent-task/plugin-agents
16
+ */
17
+ import type { Context } from '@deepseek-ai/cordis';
18
+ import type { AgentDefinition } from '@dsh-cc/claude-code-agents';
19
+ import type { SubagentsLike } from './background-start.ts';
20
+ /** Options for the index, mostly injectable seams for tests. */
21
+ export interface PluginAgentIndexOptions {
22
+ /**
23
+ * Override the seam lookup (hermetic tests). Defaults to
24
+ * `ctx.get('subagents')`, re-read on every call.
25
+ */
26
+ seam?: () => SubagentsLike | undefined;
27
+ }
28
+ /**
29
+ * The structural guard for a plugin agent provider: a `start` function, a
30
+ * string `name` containing `:` (the scoped `plugin:agent` id), and a
31
+ * `definition` with a string `agentType` and `systemPrompt`. Builtin
32
+ * providers (spawn/fork/…) carry no definition and are excluded naturally.
33
+ *
34
+ * The guard additionally REQUIRES the loader brand (`Symbol.for(
35
+ * 'dsh-cc.plugin-agent-provider')`, plan §9.4): the structural shape alone is
36
+ * an accidental protocol any foreign provider could fake, so only providers
37
+ * the loader actually created are adopted.
38
+ *
39
+ * Precondition (load-bearing): the provider only carries a scoped name when
40
+ * `mountAgents` was given a `namespacePrefix` — no prefix at mount ⇒ the
41
+ * agent is undiscoverable: neither addressable by Task nor listed in the
42
+ * catalog.
43
+ */
44
+ export declare function isPluginAgentProvider(provider: unknown): provider is {
45
+ name: string;
46
+ start: unknown;
47
+ definition: AgentDefinition;
48
+ };
49
+ /**
50
+ * A live view over the seam's plugin agent providers. All methods read the
51
+ * seam lazily on EVERY call so effect-scoped plugin mounts that appear after
52
+ * `apply()` are still discovered.
53
+ */
54
+ export declare class PluginAgentIndex {
55
+ private readonly ctx;
56
+ private readonly seamOverride;
57
+ constructor(ctx: Context, options?: PluginAgentIndexOptions);
58
+ /** The seam, re-read on every call (lazy: mounts may appear after apply). */
59
+ private getSeam;
60
+ /**
61
+ * List every plugin agent currently registered on the seam, as
62
+ * `{ id, definition }` pairs. The scan is synchronous and uncached.
63
+ */
64
+ list(): {
65
+ id: string;
66
+ definition: AgentDefinition;
67
+ }[];
68
+ /**
69
+ * Resolve one plugin agent by its exact scoped id (`plugin:agent`).
70
+ * Bare plugin agent names are NOT addressable — matching CC, where plugin
71
+ * agents are addressed only by scoped id.
72
+ */
73
+ resolve(type: string): AgentDefinition | undefined;
74
+ /** A snapshot of the currently known scoped ids (for catalog diffing). */
75
+ knownIds(): string[];
76
+ }
77
+ //# sourceMappingURL=plugin-agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-agents.d.ts","sourceRoot":"","sources":["../src/plugin-agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAiB1D,gEAAgE;AAChE,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,aAAa,GAAG,SAAS,CAAA;CACvC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,GAAG,QAAQ,IAAI;IACpE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,UAAU,EAAE,eAAe,CAAA;CAC5B,CASA;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA+C;gBAEhE,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,uBAA4B;IAK/D,6EAA6E;IAC7E,OAAO,CAAC,OAAO;IAKf;;;OAGG;IACH,IAAI,IAAI;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,eAAe,CAAA;KAAE,EAAE;IAerD;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIlD,0EAA0E;IAC1E,QAAQ,IAAI,MAAM,EAAE;CAGrB"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Live enumeration of plugin agent providers over the `subagents` seam.
3
+ *
4
+ * The CC Task tool treats the seam's registered agent providers purely as a
5
+ * DEFINITION source: `cc-plugin-loader`'s `mountAgents` registers one
6
+ * `AgentProvider` per plugin agent under the scoped id
7
+ * `` `${pluginName}:${agentType}` `` (the `namespacePrefix` mechanism), and
8
+ * this index enumerates them live on every call — plugin mounts are
9
+ * effect-scoped Cordis contexts that may appear (or disappear) after this
10
+ * plugin's `apply()`, so nothing is cached.
11
+ *
12
+ * Builtin providers (`spawn`, `fork`, …) are excluded naturally: they carry
13
+ * no `definition`.
14
+ *
15
+ * @module @dsh-cc/subagent-task/plugin-agents
16
+ */
17
+ /**
18
+ * The loader's brand key, duplicated as a `Symbol.for` lookup instead of a
19
+ * runtime import of `@dsh-cc/plugin-loader` (a devDependency — a runtime
20
+ * import here would break published consumers). Kept in lockstep with
21
+ * `PLUGIN_AGENT_PROVIDER_BRAND` in the loader; both resolve to the same
22
+ * registry symbol.
23
+ */
24
+ const PLUGIN_AGENT_PROVIDER_BRAND = Symbol.for('dsh-cc.plugin-agent-provider');
25
+ /** Whether a value was created by the loader as a plugin agent provider. */
26
+ function hasLoaderBrand(value) {
27
+ return typeof value === 'object' && value !== null
28
+ && value[PLUGIN_AGENT_PROVIDER_BRAND] === true;
29
+ }
30
+ /**
31
+ * The structural guard for a plugin agent provider: a `start` function, a
32
+ * string `name` containing `:` (the scoped `plugin:agent` id), and a
33
+ * `definition` with a string `agentType` and `systemPrompt`. Builtin
34
+ * providers (spawn/fork/…) carry no definition and are excluded naturally.
35
+ *
36
+ * The guard additionally REQUIRES the loader brand (`Symbol.for(
37
+ * 'dsh-cc.plugin-agent-provider')`, plan §9.4): the structural shape alone is
38
+ * an accidental protocol any foreign provider could fake, so only providers
39
+ * the loader actually created are adopted.
40
+ *
41
+ * Precondition (load-bearing): the provider only carries a scoped name when
42
+ * `mountAgents` was given a `namespacePrefix` — no prefix at mount ⇒ the
43
+ * agent is undiscoverable: neither addressable by Task nor listed in the
44
+ * catalog.
45
+ */
46
+ export function isPluginAgentProvider(provider) {
47
+ if (!hasLoaderBrand(provider))
48
+ return false;
49
+ const candidate = provider;
50
+ if (typeof candidate.name !== 'string' || !candidate.name.includes(':'))
51
+ return false;
52
+ if (typeof candidate.start !== 'function')
53
+ return false;
54
+ const def = candidate.definition;
55
+ if (typeof def !== 'object' || def === null)
56
+ return false;
57
+ const shape = def;
58
+ return typeof shape.agentType === 'string' && typeof shape.systemPrompt === 'string';
59
+ }
60
+ /**
61
+ * A live view over the seam's plugin agent providers. All methods read the
62
+ * seam lazily on EVERY call so effect-scoped plugin mounts that appear after
63
+ * `apply()` are still discovered.
64
+ */
65
+ export class PluginAgentIndex {
66
+ ctx;
67
+ seamOverride;
68
+ constructor(ctx, options = {}) {
69
+ this.ctx = ctx;
70
+ this.seamOverride = options.seam;
71
+ }
72
+ /** The seam, re-read on every call (lazy: mounts may appear after apply). */
73
+ getSeam() {
74
+ if (this.seamOverride !== undefined)
75
+ return this.seamOverride();
76
+ return this.ctx.get('subagents');
77
+ }
78
+ /**
79
+ * List every plugin agent currently registered on the seam, as
80
+ * `{ id, definition }` pairs. The scan is synchronous and uncached.
81
+ */
82
+ list() {
83
+ const seam = this.getSeam();
84
+ // The seam is duck-typed: a host (or test harness) may expose a partial
85
+ // seam without `list` — treat that as "no plugin agents", not a crash.
86
+ if (seam === undefined || typeof seam.list !== 'function')
87
+ return [];
88
+ const entries = [];
89
+ for (const name of seam.list()) {
90
+ const provider = seam.getProvider(name);
91
+ if (isPluginAgentProvider(provider)) {
92
+ entries.push({ id: provider.name, definition: provider.definition });
93
+ }
94
+ }
95
+ return entries.sort((a, b) => a.id.localeCompare(b.id));
96
+ }
97
+ /**
98
+ * Resolve one plugin agent by its exact scoped id (`plugin:agent`).
99
+ * Bare plugin agent names are NOT addressable — matching CC, where plugin
100
+ * agents are addressed only by scoped id.
101
+ */
102
+ resolve(type) {
103
+ return this.list().find(entry => entry.id === type)?.definition;
104
+ }
105
+ /** A snapshot of the currently known scoped ids (for catalog diffing). */
106
+ knownIds() {
107
+ return this.list().map(entry => entry.id);
108
+ }
109
+ }
110
+ //# sourceMappingURL=plugin-agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-agents.js","sourceRoot":"","sources":["../src/plugin-agents.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Duplicate-notice suppression for inline-collected subagent epochs
3
- * (`docs/plans/2026-09-10-epoch-collector-dsh-cc.md` §5): a pre-step
3
+ * (`docs/plans/2026-09-05-epoch-collector-dsh-cc.md` §5): a pre-step
4
4
  * waterfall listener that DROPs pending `subagent-settled` messages whose
5
5
  * `senderSessionId` is in the pop-once "collected" set, so a collected
6
6
  * epoch's settlement account lives only in the tool result and never also
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Duplicate-notice suppression for inline-collected subagent epochs
3
- * (`docs/plans/2026-09-10-epoch-collector-dsh-cc.md` §5): a pre-step
3
+ * (`docs/plans/2026-09-05-epoch-collector-dsh-cc.md` §5): a pre-step
4
4
  * waterfall listener that DROPs pending `subagent-settled` messages whose
5
5
  * `senderSessionId` is in the pop-once "collected" set, so a collected
6
6
  * epoch's settlement account lives only in the tool result and never also
package/lib/tool.d.ts CHANGED
@@ -18,6 +18,10 @@
18
18
  * task text as the first user message, a routes-resolved `agentOptions`
19
19
  * override, and the definition's tool restriction (sanitized of tool names
20
20
  * this composition no longer registers).
21
+ * - A type matching a plugin agent's scoped id (`plugin:agent`, from the
22
+ * `subagents` seam's namespaced providers) → the identical fold: the
23
+ * provider's `AgentDefinition` is dispatched through the same `spawn`
24
+ * provider mechanics; no new start path exists for plugin agents.
21
25
  * - Any other type → an error result listing the available types.
22
26
  *
23
27
  * The seam's capability contract (`assertCapabilities`) is honoured
@@ -33,6 +37,7 @@
33
37
  */
34
38
  import type { Context } from '@deepseek-ai/cordis';
35
39
  import type { AgentRegistry } from './registry.ts';
40
+ import { PluginAgentIndex } from './plugin-agents.ts';
36
41
  import { SpawnPinCapture } from './resume-capture.ts';
37
42
  export { MAX_LIVE_CONTINUABLE_CHILDREN, CLAUDE_CODE_DISABLE_BACKGROUND_TASKS, backgroundTasksDisabled, } from './background-start.ts';
38
43
  /** The registered tool name (the CC display mapping surfaces it as `Task`). */
@@ -45,5 +50,5 @@ export declare const TASK_TOOL = "subagent_fork";
45
50
  * no `resumePins` plugin config) writes no pins and runs no preflight.
46
51
  * @returns the registration disposer, or undefined when the tools seam is absent.
47
52
  */
48
- export declare function registerTaskTool(ctx: Context, registry: AgentRegistry, capture?: SpawnPinCapture): (() => void) | undefined;
53
+ export declare function registerTaskTool(ctx: Context, registry: AgentRegistry, capture?: SpawnPinCapture, pluginIndex?: PluginAgentIndex): (() => void) | undefined;
49
54
  //# sourceMappingURL=tool.d.ts.map
package/lib/tool.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAMlD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAYrD,OAAO,EACL,6BAA6B,EAC7B,oCAAoC,EACpC,uBAAuB,GACxB,MAAM,uBAAuB,CAAA;AAE9B,+EAA+E;AAC/E,eAAO,MAAM,SAAS,kBAAkB,CAAA;AA8CxC;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,eAAe,GACxB,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAkL1B"}
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../src/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAOlD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAYrD,OAAO,EACL,6BAA6B,EAC7B,oCAAoC,EACpC,uBAAuB,GACxB,MAAM,uBAAuB,CAAA;AAE9B,+EAA+E;AAC/E,eAAO,MAAM,SAAS,kBAAkB,CAAA;AA8CxC;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,eAAe,EACzB,WAAW,GAAE,gBAA4C,GACxD,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CA8M1B"}