kankaku-pi 1.0.0

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.
Files changed (153) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1438 -0
  3. package/dist/adapters/cached-catalog.d.ts +42 -0
  4. package/dist/adapters/cached-catalog.js +121 -0
  5. package/dist/adapters/export-writer.d.ts +13 -0
  6. package/dist/adapters/export-writer.js +28 -0
  7. package/dist/adapters/file-modes.d.ts +20 -0
  8. package/dist/adapters/file-modes.js +34 -0
  9. package/dist/adapters/hub-actions.d.ts +35 -0
  10. package/dist/adapters/hub-actions.js +70 -0
  11. package/dist/adapters/hub-credentials.d.ts +35 -0
  12. package/dist/adapters/hub-credentials.js +58 -0
  13. package/dist/adapters/jsonl-work-log.d.ts +20 -0
  14. package/dist/adapters/jsonl-work-log.js +62 -0
  15. package/dist/adapters/kankaku-dir.d.ts +38 -0
  16. package/dist/adapters/kankaku-dir.js +85 -0
  17. package/dist/adapters/lazy-jsonl-work-log.d.ts +17 -0
  18. package/dist/adapters/lazy-jsonl-work-log.js +31 -0
  19. package/dist/adapters/pocketbase-catalog.d.ts +16 -0
  20. package/dist/adapters/pocketbase-catalog.js +56 -0
  21. package/dist/adapters/pocketbase-client.d.ts +81 -0
  22. package/dist/adapters/pocketbase-client.js +148 -0
  23. package/dist/adapters/pocketbase-sink.d.ts +53 -0
  24. package/dist/adapters/pocketbase-sink.js +181 -0
  25. package/dist/adapters/project-config.d.ts +42 -0
  26. package/dist/adapters/project-config.js +108 -0
  27. package/dist/adapters/report-data.d.ts +12 -0
  28. package/dist/adapters/report-data.js +8 -0
  29. package/dist/adapters/report-views.d.ts +45 -0
  30. package/dist/adapters/report-views.js +73 -0
  31. package/dist/adapters/report.d.ts +112 -0
  32. package/dist/adapters/report.js +236 -0
  33. package/dist/adapters/sync-runner.d.ts +114 -0
  34. package/dist/adapters/sync-runner.js +273 -0
  35. package/dist/adapters/sync-state-store.d.ts +62 -0
  36. package/dist/adapters/sync-state-store.js +188 -0
  37. package/dist/config.d.ts +168 -0
  38. package/dist/config.js +392 -0
  39. package/dist/domain/ancestry-match.d.ts +49 -0
  40. package/dist/domain/ancestry-match.js +82 -0
  41. package/dist/domain/client-label.d.ts +28 -0
  42. package/dist/domain/client-label.js +44 -0
  43. package/dist/domain/day.d.ts +2 -0
  44. package/dist/domain/day.js +8 -0
  45. package/dist/domain/export.d.ts +38 -0
  46. package/dist/domain/export.js +68 -0
  47. package/dist/domain/hub-entry.d.ts +234 -0
  48. package/dist/domain/hub-entry.js +265 -0
  49. package/dist/domain/index.d.ts +19 -0
  50. package/dist/domain/index.js +19 -0
  51. package/dist/domain/intervals.d.ts +17 -0
  52. package/dist/domain/intervals.js +43 -0
  53. package/dist/domain/registry-health.d.ts +49 -0
  54. package/dist/domain/registry-health.js +58 -0
  55. package/dist/domain/segment-rule.d.ts +10 -0
  56. package/dist/domain/segment-rule.js +1 -0
  57. package/dist/domain/subagent-profile.d.ts +278 -0
  58. package/dist/domain/subagent-profile.js +418 -0
  59. package/dist/domain/sync-plan.d.ts +151 -0
  60. package/dist/domain/sync-plan.js +196 -0
  61. package/dist/domain/task-view.d.ts +117 -0
  62. package/dist/domain/task-view.js +428 -0
  63. package/dist/domain/work-record.d.ts +236 -0
  64. package/dist/domain/work-record.js +91 -0
  65. package/dist/domain/work-target.d.ts +101 -0
  66. package/dist/domain/work-target.js +149 -0
  67. package/dist/domain/work-tracker.d.ts +90 -0
  68. package/dist/domain/work-tracker.js +405 -0
  69. package/dist/hub/index.d.ts +25 -0
  70. package/dist/hub/index.js +25 -0
  71. package/dist/ports/catalog.d.ts +31 -0
  72. package/dist/ports/catalog.js +1 -0
  73. package/dist/ports/clock.d.ts +3 -0
  74. package/dist/ports/clock.js +1 -0
  75. package/dist/ports/index.d.ts +11 -0
  76. package/dist/ports/index.js +1 -0
  77. package/dist/ports/inflight-store.d.ts +15 -0
  78. package/dist/ports/inflight-store.js +1 -0
  79. package/dist/ports/process-registry.d.ts +72 -0
  80. package/dist/ports/process-registry.js +1 -0
  81. package/dist/ports/work-log.d.ts +14 -0
  82. package/dist/ports/work-log.js +1 -0
  83. package/dist/ports/work-sink.d.ts +39 -0
  84. package/dist/ports/work-sink.js +1 -0
  85. package/package.json +66 -0
  86. package/src/adapters/agent-info.ts +86 -0
  87. package/src/adapters/ancestry.ts +260 -0
  88. package/src/adapters/cached-catalog.ts +147 -0
  89. package/src/adapters/export-writer.ts +33 -0
  90. package/src/adapters/file-inflight-store.ts +115 -0
  91. package/src/adapters/file-modes.ts +35 -0
  92. package/src/adapters/hub-actions.ts +82 -0
  93. package/src/adapters/hub-credentials.ts +95 -0
  94. package/src/adapters/jsonl-work-log.ts +67 -0
  95. package/src/adapters/kankaku-command.ts +717 -0
  96. package/src/adapters/kankaku-dir.ts +102 -0
  97. package/src/adapters/lazy-file-inflight-store.ts +43 -0
  98. package/src/adapters/lazy-jsonl-work-log.ts +39 -0
  99. package/src/adapters/machine-process-registry.ts +256 -0
  100. package/src/adapters/panel/kankaku-panel.ts +419 -0
  101. package/src/adapters/panel/panel-items.ts +87 -0
  102. package/src/adapters/panel/panel-lines.ts +13 -0
  103. package/src/adapters/panel/panel-theme.ts +32 -0
  104. package/src/adapters/panel/screens/about.ts +69 -0
  105. package/src/adapters/panel/screens/doctor.ts +89 -0
  106. package/src/adapters/panel/screens/export.ts +123 -0
  107. package/src/adapters/panel/screens/report.ts +143 -0
  108. package/src/adapters/panel/screens/sync.ts +136 -0
  109. package/src/adapters/panel/screens/target.ts +384 -0
  110. package/src/adapters/pi-tracker.ts +753 -0
  111. package/src/adapters/pocketbase-catalog.ts +89 -0
  112. package/src/adapters/pocketbase-client.ts +197 -0
  113. package/src/adapters/pocketbase-sink.ts +236 -0
  114. package/src/adapters/process-identity-memo.ts +102 -0
  115. package/src/adapters/process-identity.ts +162 -0
  116. package/src/adapters/project-config.ts +116 -0
  117. package/src/adapters/report-data.ts +13 -0
  118. package/src/adapters/report-views.ts +98 -0
  119. package/src/adapters/report.ts +335 -0
  120. package/src/adapters/session-client.ts +116 -0
  121. package/src/adapters/session-dir.ts +28 -0
  122. package/src/adapters/session-target.ts +431 -0
  123. package/src/adapters/status-bar.ts +86 -0
  124. package/src/adapters/subagent-startup.ts +66 -0
  125. package/src/adapters/sync-runner.ts +340 -0
  126. package/src/adapters/sync-state-store.ts +227 -0
  127. package/src/adapters/target-picker.ts +127 -0
  128. package/src/config.ts +536 -0
  129. package/src/domain/ancestry-match.ts +84 -0
  130. package/src/domain/client-label.ts +56 -0
  131. package/src/domain/day.ts +8 -0
  132. package/src/domain/export.ts +107 -0
  133. package/src/domain/hub-entry.ts +433 -0
  134. package/src/domain/index.ts +19 -0
  135. package/src/domain/intervals.ts +53 -0
  136. package/src/domain/panel-model.ts +270 -0
  137. package/src/domain/registry-health.ts +87 -0
  138. package/src/domain/segment-rule.ts +10 -0
  139. package/src/domain/subagent-profile.ts +495 -0
  140. package/src/domain/sync-plan.ts +266 -0
  141. package/src/domain/task-view.ts +526 -0
  142. package/src/domain/work-record.ts +320 -0
  143. package/src/domain/work-target.ts +234 -0
  144. package/src/domain/work-tracker.ts +485 -0
  145. package/src/extension.ts +346 -0
  146. package/src/hub/index.ts +25 -0
  147. package/src/ports/catalog.ts +33 -0
  148. package/src/ports/clock.ts +3 -0
  149. package/src/ports/index.ts +11 -0
  150. package/src/ports/inflight-store.ts +16 -0
  151. package/src/ports/process-registry.ts +75 -0
  152. package/src/ports/work-log.ts +15 -0
  153. package/src/ports/work-sink.ts +35 -0
@@ -0,0 +1,278 @@
1
+ import type { UsageTotals } from "./work-record.ts";
2
+ /**
3
+ * A child-process env marker a {@link SubagentProfile} recognises as
4
+ * confirmation that THIS process is one of its children (never guessed —
5
+ * see `resolveChildProfile`). `value: undefined` means "any non-empty
6
+ * value counts as present" (e.g. pi-subagents' `PI_SUBAGENT_DEPTH`, a
7
+ * recursion-depth counter, not a fixed sentinel); a defined `value`
8
+ * requires an exact match (e.g. gentle-pi's `GENTLE_PI_AGENTS_CHILD=1`).
9
+ */
10
+ export interface ChildEnvMarker {
11
+ name: string;
12
+ value?: string;
13
+ }
14
+ /**
15
+ * How strongly a profile's children can be joined back to their
16
+ * orchestrator (ADR 0021): `"explicit-id"` when the tool result carries a
17
+ * stable id kankaku can use directly (gentle-pi's `taskId` — parent-side
18
+ * only, the child cannot read its own); `"ancestry"` when only the
19
+ * machine-wide process registry/ancestor-chain walk can join it;
20
+ * `"none"` for a profile that offers no join signal at all.
21
+ */
22
+ export type JoinKeyConfidence = "explicit-id" | "ancestry" | "none";
23
+ export interface SubagentLaunchInfo {
24
+ agent?: string;
25
+ mode?: string;
26
+ }
27
+ export interface SubagentResultInfo {
28
+ taskId?: string;
29
+ agent?: string;
30
+ status?: string;
31
+ mode?: string;
32
+ cwd?: string;
33
+ /**
34
+ * Nested LLM usage the subagent tool result reports on itself (pi's
35
+ * documented convention: "a tool making nested LLM calls should return
36
+ * their combined Usage as `usage`" — see `docs/extensions.md`). A
37
+ * profile whose children are ALSO separately tracked and joined via a
38
+ * confirmed child-env marker (ancestry-based `joinKeyConfidence`) must
39
+ * never report this — see `PI_SUBAGENTS_PROFILE` for why.
40
+ */
41
+ usage?: Partial<UsageTotals>;
42
+ }
43
+ /**
44
+ * Declares how kankaku recognises one subagent-launching ecosystem
45
+ * package: which tool call(s) open a subagent span, how to read
46
+ * `agent`/`mode` from the launch args and `taskId`/`status`/`mode`/`cwd`/
47
+ * `usage` from the tool result, which env var(s) confirm a child process of
48
+ * this kind, and how strong a join key it offers. See ADR 0020 and
49
+ * SUBAGENT-REQ-001.
50
+ */
51
+ export interface SubagentProfile {
52
+ id: string;
53
+ toolNames: readonly string[];
54
+ childEnvMarkers: readonly ChildEnvMarker[];
55
+ joinKeyConfidence: JoinKeyConfidence;
56
+ readLaunchArgs(args: Record<string, unknown> | undefined): SubagentLaunchInfo;
57
+ readResult(result: unknown): SubagentResultInfo;
58
+ }
59
+ /**
60
+ * gentle-pi (first-class, ADR 0020): the richest, most robust profile —
61
+ * explicit `taskId` join, live `status`, `mode` (task/background) and
62
+ * cross-worktree `cwd`, all read from `result.details.gentleAgents`
63
+ * exactly as `work-tracker.ts#extractTaskId` did before this module
64
+ * existed. Verified against gentle-pi 3.3.0 source
65
+ * (`extensions/gentle-agents.ts`, `lib/agents-protocol.ts`,
66
+ * `lib/agents-runner.ts`): its tool result never carries a top-level
67
+ * `usage` field (children are separate OS processes, cost tracked
68
+ * independently through the existing ancestry/registry join) — this
69
+ * profile therefore never reports `usage`, so 6c's forwarding never
70
+ * touches gentle-pi's numbers.
71
+ */
72
+ export declare const GENTLE_PI_PROFILE: SubagentProfile;
73
+ /**
74
+ * pi's bundled reference example extension
75
+ * (`examples/extensions/subagent/index.ts`, tool `subagent`). Verified: its
76
+ * `spawn()` call passes no `env` option at all (the child simply inherits
77
+ * the parent's environment unmodified) — so it sets NO child-identifying
78
+ * env marker, and a child of this kind can only ever be recognised through
79
+ * ancestry (ADR 0020: "always starts uncertain"). Because it has no
80
+ * marker, it can never become a *confirmed* `role: "subagent"` record
81
+ * (see `resolveChildProfile`) and therefore can never be double-joined —
82
+ * safe to forward `usage` unconditionally.
83
+ */
84
+ /**
85
+ * C1 investigation note (real-shape disambiguation, verified against the
86
+ * bundled reference example's actual source above): its real tool RESULT
87
+ * never actually sets a top-level `usage` field at all — every `execute()`
88
+ * return statement in `examples/extensions/subagent/index.ts` returns only
89
+ * `{content, details, isError?}`; nested-call usage lives per-result inside
90
+ * `details.results[].usage`, not where pi's documented convention (and
91
+ * `readStandardUsage` below) looks. `pi-subagents` (npm, verified against
92
+ * 0.28.0 `src/runs/foreground/subagent-executor.ts` and
93
+ * `src/runs/foreground/execution.ts`) is the same: no `execute()` return
94
+ * anywhere in that package sets a top-level `usage` either. So for BOTH
95
+ * real packages examined, `readStandardUsage(result)` returns `undefined`
96
+ * today regardless of which one actually answered the call — this
97
+ * profile's generic top-level-`usage` read exists for pi's DOCUMENTED
98
+ * convention (`docs/extensions.md`: "If a tool makes nested LLM calls,
99
+ * return their combined Usage as usage"), which a well-behaved third-party
100
+ * "subagent"-named tool, or a future version of either package, could
101
+ * start following at any time. That forward-looking risk is exactly what
102
+ * C1 guards against — see `safeAmbiguousResultInfo`.
103
+ */
104
+ export declare const PI_REFERENCE_PROFILE: SubagentProfile;
105
+ /**
106
+ * pi-subagents (npm package, tool `subagent`, action-based). Verified
107
+ * against the installed 0.28.0 source (`src/shared/types.ts`
108
+ * `getSubagentDepthEnv`): every child it spawns (foreground AND the
109
+ * detached background runner) carries `PI_SUBAGENT_DEPTH` — NOT
110
+ * `PI_SUBAGENT_PARENT_SESSION`, an earlier, unverified assumption this
111
+ * profile deliberately does not use. Because this marker CAN confirm a
112
+ * child as `role: "subagent"` (ancestry-joined, its own usage/cost already
113
+ * counted through that join), this profile's `readResult` deliberately
114
+ * never forwards `usage` even when present — forwarding it here would risk
115
+ * counting the same nested LLM work twice (once via the join, once via the
116
+ * forwarded figure). See `GENTLE_PI_PROFILE`/`PI_REFERENCE_PROFILE` for the
117
+ * two cases where forwarding is safe.
118
+ */
119
+ export declare const PI_SUBAGENTS_PROFILE: SubagentProfile;
120
+ export declare const BUILTIN_SUBAGENT_PROFILES: readonly SubagentProfile[];
121
+ /**
122
+ * SUBAGENT-REQ-001/002/003: the user-configured profile built from
123
+ * `KANKAKU_SUBAGENT_TOOLS`/`KANKAKU_SUBAGENT_CHILD_ENV` (parsed in
124
+ * `config.ts`, mirroring `KANKAKU_INTERACTIVE_TOOLS`'s tolerant
125
+ * comma-split convention). Always additive to the built-ins, never
126
+ * replacing gentle-pi's own recognition. `undefined` when neither is
127
+ * configured, so `loadConfig` never adds an inert profile. Forwards
128
+ * `result.usage` generically (like `PI_REFERENCE_PROFILE`) — a documented,
129
+ * unavoidable residual risk: kankaku cannot know whether an arbitrary
130
+ * configured child process also runs kankaku itself and would otherwise be
131
+ * ancestry-joined, so a user who configures BOTH a child-env marker AND a
132
+ * tool that forwards `usage` for the same third-party package accepts that
133
+ * narrow double-count risk (see README "Subagents").
134
+ */
135
+ export declare function buildConfiguredProfile(toolNames: readonly string[], childEnvMarkers: readonly ChildEnvMarker[]): SubagentProfile | undefined;
136
+ /** Every profile whose `toolNames` include `toolName`, in the given order. */
137
+ export declare function matchToolProfiles(profiles: readonly SubagentProfile[], toolName: string): SubagentProfile[];
138
+ export interface ToolProfileResolution {
139
+ /** The single matching profile, or `undefined` when there is none or the tool name is ambiguous (never guessed). */
140
+ profile: SubagentProfile | undefined;
141
+ /** `true` when 2+ profiles register this exact tool name (SUBAGENT-REQ-005). */
142
+ ambiguous: boolean;
143
+ candidates: SubagentProfile[];
144
+ }
145
+ /**
146
+ * SUBAGENT-REQ-005: resolve which profile should be used to open/read a
147
+ * subagent span for a given tool name. Exactly one match resolves
148
+ * unambiguously; zero means this is not a recognised subagent tool call at
149
+ * all; two or more (e.g. `"subagent"`, registered by both the pi reference
150
+ * example and pi-subagents) is a genuine name collision — never guessed:
151
+ * `profile` stays `undefined` and `ambiguous` is `true` so the caller can
152
+ * still open a best-effort span (see `readLaunchInfo`/`readResultInfo`)
153
+ * without ever claiming a specific profile matched.
154
+ */
155
+ /**
156
+ * C1 investigation note — real disambiguation was investigated and
157
+ * rejected for the "subagent" name collision between `PI_REFERENCE_PROFILE`
158
+ * and `PI_SUBAGENTS_PROFILE`, both by args/result SHAPE and by pi's own
159
+ * `getAllTools()[].sourceInfo.path`:
160
+ *
161
+ * - Args shape: pi-subagents' `action` field ("list"/"get"/"create"/
162
+ * "update"/"delete"/"status"/"interrupt"/"resume"/"doctor" — verified
163
+ * 0.28.0 `src/extension/schemas.ts`) is absent from pi-reference's schema
164
+ * entirely, so its PRESENCE would be conclusive — but it is only ever
165
+ * set for pi-subagents' management/diagnostic calls, never for the
166
+ * money-affecting single/parallel/chain execution calls (`agent`+`task`,
167
+ * `tasks[]`, `chain[]`) that are the whole point of C1: those look
168
+ * identical in both packages' schemas (`agent`, `task`, `tasks`,
169
+ * `chain`, `cwd` all present in both). Result shape is no better: neither
170
+ * package's real result carries a top-level `usage` at all (see
171
+ * `PI_REFERENCE_PROFILE`'s doc comment) — no distinguishing signal is
172
+ * present in exactly the calls that matter.
173
+ * - `sourceInfo.path`: `pi.getAllTools()` does expose which extension
174
+ * registered a given tool name (`docs/extensions.md` "pi.getAllTools()").
175
+ * But that same doc explicitly warns, for the structurally identical
176
+ * `sourceInfo` on `pi.getCommands()`: "Use sourceInfo as the canonical
177
+ * provenance field. Do not infer ownership from command names or from ad
178
+ * hoc path parsing." Matching a tool's `sourceInfo.path` against a
179
+ * hardcoded substring (a package name, an examples/ path) IS ad hoc path
180
+ * parsing — the path is not guaranteed to contain any stable, portable
181
+ * substring across install layouts (a monorepo, a symlinked/hoisted
182
+ * dependency, a vendored fork). This was rejected as unreliable, not
183
+ * merely inconvenient.
184
+ *
185
+ * Neither route was conclusive, so kankaku stays ambiguous by design
186
+ * (SUBAGENT-REQ-005: never guessed) and instead fixes the CONSEQUENCE of
187
+ * ambiguity — see `safeAmbiguousResultInfo`/`mergeAgreeingLaunchInfo` and
188
+ * `domain/work-tracker.ts#onToolEnd`.
189
+ */
190
+ export declare function resolveToolProfile(profiles: readonly SubagentProfile[], toolName: string): ToolProfileResolution;
191
+ /** Every tool name registered by 2+ profiles at once, with the colliding profile ids — a static property of the active profile set, independent of any record. */
192
+ export declare function findAmbiguousToolNames(profiles: readonly SubagentProfile[]): Array<{
193
+ toolName: string;
194
+ profileIds: string[];
195
+ }>;
196
+ /** Best-effort merge of `readLaunchArgs` across several candidate profiles (an ambiguous tool-name match): first defined field, in profile order, wins. */
197
+ export declare function readLaunchInfo(candidates: readonly SubagentProfile[], args: Record<string, unknown> | undefined): SubagentLaunchInfo;
198
+ /** Best-effort merge of `readResult` across several candidate profiles (an ambiguous tool-name match): first defined field, in profile order, wins — never a profile-specific field none of the candidates actually provided. */
199
+ export declare function readResultInfo(candidates: readonly SubagentProfile[], result: unknown): SubagentResultInfo;
200
+ /**
201
+ * C1 (CRITICAL fix): the launch-args counterpart of `readResultInfo`'s
202
+ * caution, used specifically for a genuinely AMBIGUOUS tool-name match
203
+ * (2+ candidate profiles, none of them the winner — SUBAGENT-REQ-005).
204
+ * Unlike `readLaunchInfo`'s "first defined field wins" merge (kept as-is,
205
+ * still used for the unambiguous single-candidate case, where there is
206
+ * nothing to disagree about), this only keeps a field when every candidate
207
+ * that reports a value for it reports the SAME value — "agent/mode if they
208
+ * read identically, else omitted". Two candidates disagreeing (e.g. one
209
+ * profile reads `mode` from `args.mode`, another from `args.action`, and
210
+ * they differ) means kankaku genuinely does not know which is right, so
211
+ * the field is dropped rather than silently picking one. Never reads
212
+ * anything money- or join-affecting — launch args never carry `usage` or
213
+ * `taskId` in the first place, only descriptive `agent`/`mode`.
214
+ */
215
+ export declare function mergeAgreeingLaunchInfo(candidates: readonly SubagentProfile[], args: Record<string, unknown> | undefined): SubagentLaunchInfo;
216
+ /**
217
+ * C1 (CRITICAL fix): the result-reading counterpart for a genuinely
218
+ * AMBIGUOUS tool-name match. `readResultInfo`'s own best-effort merge stays
219
+ * available (and is still exactly right for the UNAMBIGUOUS single-
220
+ * candidate case), but when 2+ profiles registered the same tool name and
221
+ * neither could be told apart, nothing MONEY- or JOIN-affecting is ever
222
+ * taken from any candidate: `usage` (would silently double-bill the day a
223
+ * package sharing an ambiguous tool name, e.g. "subagent", starts
224
+ * following pi's documented top-level `usage` convention — see
225
+ * `PI_REFERENCE_PROFILE`) and `taskId` (a join key) are always stripped.
226
+ * Purely descriptive fields (`agent`/`status`/`mode`/`cwd`) are kept from
227
+ * the best-effort merge — they affect neither billing nor task/child
228
+ * joining, only how a span/record is labelled for a human reading it.
229
+ * `profile` itself is never part of this shape; the caller already leaves
230
+ * it `undefined` for an ambiguous match (see `resolveToolProfile`).
231
+ */
232
+ export declare function safeAmbiguousResultInfo(candidates: readonly SubagentProfile[], result: unknown): SubagentResultInfo;
233
+ /**
234
+ * Whether any of `markers` is present in `env`: an exact-value marker
235
+ * requires an exact match, a presence-only marker (`value: undefined`)
236
+ * matches any non-empty value. Shared by `profileMarkerMatches` (one
237
+ * profile's own markers) and `config.ts#detectRole` (the full active set,
238
+ * generalised beyond the single hardcoded `GENTLE_PI_AGENTS_CHILD` check).
239
+ */
240
+ export declare function matchesAnyMarker(env: NodeJS.ProcessEnv, markers: readonly ChildEnvMarker[]): boolean;
241
+ /** Whether `profile`'s child-env marker(s) are present in `env`. A profile with no markers at all (e.g. `PI_REFERENCE_PROFILE`) never matches, by construction. */
242
+ export declare function profileMarkerMatches(profile: SubagentProfile, env: NodeJS.ProcessEnv): boolean;
243
+ export interface ChildProfileResolution {
244
+ /** The single profile confirmed by an env marker, or `undefined` when none matched or 2+ matched at once (never guessed). */
245
+ profile: SubagentProfile | undefined;
246
+ matchedProfiles: SubagentProfile[];
247
+ }
248
+ /**
249
+ * SUBAGENT-REQ-005: resolve which profile's child-env marker(s) confirm
250
+ * THIS process as a subagent of a known kind — the child-side counterpart
251
+ * of `resolveToolProfile`. Exactly one profile's marker present resolves
252
+ * unambiguously; none present means this process's role, if any, must come
253
+ * from ancestry instead (see `config.ts#detectRole`); two or more present
254
+ * at once (a genuine marker collision, not expected among the built-ins) is
255
+ * never guessed either — `profile` stays `undefined`, but every match is
256
+ * still reported so `/kankaku doctor` can surface it.
257
+ */
258
+ export declare function resolveChildProfile(profiles: readonly SubagentProfile[], env: NodeJS.ProcessEnv): ChildProfileResolution;
259
+ /** Every distinct child-env marker declared by any of `profiles`, de-duplicated by `name` (first-declared value wins) — used to generalise `detectRole`'s single hardcoded marker check. */
260
+ export declare function allChildMarkers(profiles: readonly SubagentProfile[]): ChildEnvMarker[];
261
+ /**
262
+ * C2 (CRITICAL fix): the "always confirms, regardless of interactivity"
263
+ * tier for `config.ts#detectRole`'s 4th param — every active profile's
264
+ * markers EXCEPT the single user-configured one (`id === "configured"`,
265
+ * built from `KANKAKU_SUBAGENT_CHILD_ENV` in `config.ts#loadConfig`). Only
266
+ * a real subagent runner (gentle-pi, pi-subagents) sets a built-in marker,
267
+ * so this tier keeps today's unconditional precedence.
268
+ */
269
+ export declare function builtinChildMarkers(profiles: readonly SubagentProfile[]): ChildEnvMarker[];
270
+ /**
271
+ * C2 (CRITICAL fix): the "never demotes an interactive session" tier for
272
+ * `config.ts#detectRole`'s 5th param — the user-configured profile's own
273
+ * markers only (empty when no `"configured"` profile is active). Kept
274
+ * separate from `builtinChildMarkers` because kankaku cannot verify an
275
+ * arbitrary configured environment variable name is genuinely child-only
276
+ * (see `config.ts#loadConfig`'s denylist and `detectRole`'s doc comment).
277
+ */
278
+ export declare function configuredChildMarkers(profiles: readonly SubagentProfile[]): ChildEnvMarker[];