crewhaus 0.1.8 → 0.2.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.
Files changed (138) hide show
  1. package/README.md +10 -3
  2. package/dist/advice-apply.d.ts +182 -0
  3. package/dist/advice-apply.js +286 -0
  4. package/dist/advise-rules.d.ts +348 -0
  5. package/dist/advise-rules.js +905 -0
  6. package/dist/alert-sink.d.ts +48 -0
  7. package/dist/alert-sink.js +86 -0
  8. package/dist/approval-gate.d.ts +127 -0
  9. package/dist/approval-gate.js +254 -0
  10. package/dist/audit-verify.d.ts +69 -0
  11. package/dist/audit-verify.js +97 -0
  12. package/dist/autodistill.d.ts +113 -0
  13. package/dist/autodistill.js +256 -0
  14. package/dist/channel-provision.d.ts +360 -0
  15. package/dist/channel-provision.js +881 -0
  16. package/dist/ci-scaffold.d.ts +31 -0
  17. package/dist/ci-scaffold.js +343 -0
  18. package/dist/compile-check.d.ts +90 -0
  19. package/dist/compile-check.js +285 -0
  20. package/dist/compliance-schedule.d.ts +35 -0
  21. package/dist/compliance-schedule.js +36 -0
  22. package/dist/context-pressure.d.ts +80 -0
  23. package/dist/context-pressure.js +166 -0
  24. package/dist/dataset-mine.d.ts +173 -0
  25. package/dist/dataset-mine.js +404 -0
  26. package/dist/datasets.d.ts +124 -0
  27. package/dist/datasets.js +260 -0
  28. package/dist/deploy-canary.d.ts +83 -0
  29. package/dist/deploy-canary.js +87 -0
  30. package/dist/doctor-checks.d.ts +33 -0
  31. package/dist/doctor-checks.js +92 -0
  32. package/dist/doctor-detect.d.ts +108 -0
  33. package/dist/doctor-detect.js +214 -0
  34. package/dist/doctor-fix.d.ts +81 -0
  35. package/dist/doctor-fix.js +164 -0
  36. package/dist/egress-triage.d.ts +121 -0
  37. package/dist/egress-triage.js +261 -0
  38. package/dist/eval-bridge.d.ts +114 -0
  39. package/dist/eval-bridge.js +158 -0
  40. package/dist/eval-coverage.d.ts +140 -0
  41. package/dist/eval-coverage.js +428 -0
  42. package/dist/eval-history.d.ts +48 -0
  43. package/dist/eval-history.js +157 -0
  44. package/dist/eval-matrix.d.ts +80 -0
  45. package/dist/eval-matrix.js +182 -0
  46. package/dist/eval-sentinel.d.ts +65 -0
  47. package/dist/eval-sentinel.js +132 -0
  48. package/dist/faq.d.ts +68 -0
  49. package/dist/faq.js +168 -0
  50. package/dist/feedback.d.ts +9 -2
  51. package/dist/feedback.js +17 -7
  52. package/dist/fewshot.d.ts +83 -0
  53. package/dist/fewshot.js +158 -0
  54. package/dist/fleet.d.ts +207 -0
  55. package/dist/fleet.js +488 -0
  56. package/dist/flywheel.d.ts +193 -0
  57. package/dist/flywheel.js +519 -0
  58. package/dist/graders-suggest.d.ts +186 -0
  59. package/dist/graders-suggest.js +658 -0
  60. package/dist/incident.d.ts +99 -0
  61. package/dist/incident.js +217 -0
  62. package/dist/index.d.ts +9 -1
  63. package/dist/index.js +11664 -963
  64. package/dist/init-interactive.d.ts +105 -0
  65. package/dist/init-interactive.js +208 -0
  66. package/dist/intents.d.ts +105 -0
  67. package/dist/intents.js +292 -0
  68. package/dist/judge-calibrate.d.ts +137 -0
  69. package/dist/judge-calibrate.js +247 -0
  70. package/dist/justification-calibrate.d.ts +150 -0
  71. package/dist/justification-calibrate.js +262 -0
  72. package/dist/justification-gate.d.ts +27 -6
  73. package/dist/justification-gate.js +30 -6
  74. package/dist/knowledge-sync.d.ts +179 -0
  75. package/dist/knowledge-sync.js +551 -0
  76. package/dist/lessons.d.ts +87 -0
  77. package/dist/lessons.js +207 -0
  78. package/dist/lint.d.ts +127 -0
  79. package/dist/lint.js +226 -0
  80. package/dist/loadtest.d.ts +114 -0
  81. package/dist/loadtest.js +196 -0
  82. package/dist/marketplace-cli.d.ts +110 -0
  83. package/dist/marketplace-cli.js +250 -0
  84. package/dist/mcp-doctor.d.ts +121 -0
  85. package/dist/mcp-doctor.js +249 -0
  86. package/dist/model-scan.d.ts +116 -0
  87. package/dist/model-scan.js +226 -0
  88. package/dist/onchain-tune.d.ts +164 -0
  89. package/dist/onchain-tune.js +346 -0
  90. package/dist/permissions-suggest.d.ts +126 -0
  91. package/dist/permissions-suggest.js +333 -0
  92. package/dist/pii-tune.d.ts +107 -0
  93. package/dist/pii-tune.js +122 -0
  94. package/dist/propose.d.ts +117 -0
  95. package/dist/propose.js +184 -0
  96. package/dist/refresh-goldens.d.ts +82 -0
  97. package/dist/refresh-goldens.js +221 -0
  98. package/dist/regression-pin.d.ts +160 -0
  99. package/dist/regression-pin.js +281 -0
  100. package/dist/retention.d.ts +193 -0
  101. package/dist/retention.js +607 -0
  102. package/dist/retire.d.ts +118 -0
  103. package/dist/retire.js +291 -0
  104. package/dist/right-size.d.ts +100 -0
  105. package/dist/right-size.js +123 -0
  106. package/dist/route.d.ts +19 -0
  107. package/dist/route.js +90 -0
  108. package/dist/scaffold-evals.d.ts +138 -0
  109. package/dist/scaffold-evals.js +410 -0
  110. package/dist/scope-audit-drift.d.ts +139 -0
  111. package/dist/scope-audit-drift.js +260 -0
  112. package/dist/security-corpus.d.ts +237 -0
  113. package/dist/security-corpus.js +516 -0
  114. package/dist/security-digest.d.ts +174 -0
  115. package/dist/security-digest.js +656 -0
  116. package/dist/sessions-index.d.ts +27 -0
  117. package/dist/sessions-index.js +51 -0
  118. package/dist/slo-doctor.d.ts +67 -0
  119. package/dist/slo-doctor.js +119 -0
  120. package/dist/slo-sink.d.ts +96 -0
  121. package/dist/slo-sink.js +107 -0
  122. package/dist/spec-changelog.d.ts +102 -0
  123. package/dist/spec-changelog.js +237 -0
  124. package/dist/state-backup.d.ts +223 -0
  125. package/dist/state-backup.js +648 -0
  126. package/dist/tools-cli.d.ts +170 -0
  127. package/dist/tools-cli.js +300 -0
  128. package/dist/triage.d.ts +202 -0
  129. package/dist/triage.js +403 -0
  130. package/dist/upgrade.d.ts +57 -0
  131. package/dist/upgrade.js +113 -0
  132. package/dist/version.d.ts +6 -0
  133. package/dist/version.js +27 -0
  134. package/dist/voice-eval.d.ts +138 -0
  135. package/dist/voice-eval.js +309 -0
  136. package/dist/watch.d.ts +58 -0
  137. package/dist/watch.js +97 -0
  138. package/package.json +90 -65
@@ -0,0 +1,348 @@
1
+ /**
2
+ * Item 14 — `crewhaus advise` rule library: the pure, side-effect-free half
3
+ * of the trace-mining spec advisor. Aggregates session JSONLs (including the
4
+ * advisor kinds runtime-core now persists — `recovery`, `tool_stats`,
5
+ * `permission`, `model_meta`) plus `.crewhaus/audit` records into an
6
+ * `AdviceContext`, then runs a library of threshold rules over it. Each rule
7
+ * returns typed findings whose suggestion is either a pre-validated
8
+ * `SpecPatch` (consumable by a future `optimize --from-advice`) or free-form
9
+ * advice text.
10
+ *
11
+ * Everything here is pure so it is unit-testable; all filesystem access
12
+ * lives in `apps/cli/src/index.ts` (mirrors `feedback.ts` / `eval-history.ts`).
13
+ *
14
+ * Old-vintage logs (written before the advisor kinds existed) build an empty
15
+ * context slice for each missing kind and simply produce no findings — the
16
+ * rules only fire where the data now exists.
17
+ */
18
+ import type { Spec } from "@crewhaus/spec";
19
+ import { type SpecPatch } from "@crewhaus/spec-patch";
20
+ export type AdviceSeverity = "info" | "warn";
21
+ export type AdviceSuggestion = {
22
+ readonly kind: "spec-patch";
23
+ readonly patch: SpecPatch;
24
+ } | {
25
+ readonly kind: "advice";
26
+ readonly text: string;
27
+ };
28
+ export type AdviceFinding = {
29
+ /** `<rule>` or `<rule>:<subject>` (e.g. `repeated-tool-failures:Fetch`). */
30
+ readonly id: string;
31
+ readonly severity: AdviceSeverity;
32
+ /** One-line human summary of what tripped. */
33
+ readonly summary: string;
34
+ /** Human-readable evidence lines (counts, rates, example subjects). */
35
+ readonly evidence: ReadonlyArray<string>;
36
+ /** The numeric aggregates the rule fired on. */
37
+ readonly counts: Readonly<Record<string, number>>;
38
+ readonly suggestion: AdviceSuggestion;
39
+ };
40
+ export type ToolCallStats = {
41
+ calls: number;
42
+ errors: number;
43
+ totalDurationMs: number;
44
+ };
45
+ export type AskStats = {
46
+ asks: number;
47
+ approved: number;
48
+ denied: number;
49
+ };
50
+ /** Item 19 — per-errorName recovery aggregate: total occurrences plus the
51
+ * distribution of recovery actions that error drove. */
52
+ export type ErrorRecoveryStats = {
53
+ count: number;
54
+ /** action (`retry`/`compact`/`continue`/`tombstone`/`fail`) → occurrences. */
55
+ actions: Map<string, number>;
56
+ };
57
+ /**
58
+ * Session-derived aggregates the rules consume. Built by
59
+ * `buildAdviceContext` from parsed session-JSONL objects (tolerant of
60
+ * old-vintage logs, malformed lines, and unknown kinds) plus optional
61
+ * `.crewhaus/audit` records.
62
+ */
63
+ export type AdviceContext = {
64
+ readonly sessionIds: ReadonlyArray<string>;
65
+ /** Per-tool aggregate over `tool_stats` lines. */
66
+ readonly toolStats: ReadonlyMap<string, ToolCallStats>;
67
+ /** `recovery` lines grouped by action (`retry`/`compact`/`continue`/…). */
68
+ readonly recoveriesByAction: ReadonlyMap<string, number>;
69
+ /**
70
+ * Item 19 — `recovery` lines grouped by `errorName`, each carrying the
71
+ * action distribution that error drove. The failure-taxonomy rule clusters
72
+ * these into draft `failure_taxonomy` entries (error class → recovery
73
+ * action). Old-vintage logs (no recovery lines) leave this empty.
74
+ */
75
+ readonly recoveriesByErrorName: ReadonlyMap<string, ErrorRecoveryStats>;
76
+ /**
77
+ * `action: "continue"` recoveries — emitted exclusively for
78
+ * `max_output_tokens` truncations (recovery-engine's taxonomy), so this
79
+ * IS the truncation-pressure count.
80
+ */
81
+ readonly truncationContinues: number;
82
+ /**
83
+ * Item 19 — synthetic `[runtime] possible loop detected` nudges mined from
84
+ * `user_message` lines, grouped by tool signature. `matchNamedFailure`
85
+ * matches error.message only, so a loop (which is NOT an error — no
86
+ * exception is thrown) can never be caught by a taxonomy entry; the
87
+ * loop-break rule turns recurring signatures into instructions-addendum
88
+ * advice instead.
89
+ */
90
+ readonly loopSignatures: ReadonlyMap<string, number>;
91
+ /** `compaction` lines per session (any vintage — this kind predates item 14). */
92
+ readonly compactionsBySession: ReadonlyMap<string, number>;
93
+ /** Resolved permission asks per tool, from `permission` lines. */
94
+ readonly asksByTool: ReadonlyMap<string, AskStats>;
95
+ /** Stop-reason distribution over `model_meta` lines. */
96
+ readonly stopReasons: ReadonlyMap<string, number>;
97
+ readonly modelResponses: number;
98
+ /**
99
+ * Item 21 — per-tool total byte spend (tool_use input JSON + the correlated
100
+ * tool_result content), keyed by the PascalCase runtime tool name. The
101
+ * sub-agent-split rule uses the dominance of one tool's byte spend as the
102
+ * per-turn-token-pressure proxy (a tool that dominates context is the one
103
+ * to move behind its own window). Empty on old-vintage logs.
104
+ */
105
+ readonly perToolBytes: ReadonlyMap<string, number>;
106
+ /** Item 21 — total observed tool byte spend across all tools (the
107
+ * denominator for the dominance ratio). */
108
+ readonly totalToolBytes: number;
109
+ /** `.crewhaus/audit` record kinds → counts (report context + future rules). */
110
+ readonly auditKindCounts: ReadonlyMap<string, number>;
111
+ };
112
+ export type SessionEvents = {
113
+ readonly sessionId: string;
114
+ readonly objects: ReadonlyArray<unknown>;
115
+ };
116
+ /** Parse a JSONL blob into objects, skipping blank/malformed lines —
117
+ * a session log must never abort mining over one corrupt line. */
118
+ export declare function parseJsonlObjects(text: string): unknown[];
119
+ /** The fixed prefix the runtime stamps on a loop-detection nudge (a
120
+ * `user_message` with `synthetic: true`). Exported so a fixture/test can
121
+ * build a realistic nudge without hard-coding the string twice. */
122
+ export declare const LOOP_NUDGE_PREFIX = "[runtime] possible loop detected:";
123
+ /**
124
+ * Item 19 — extract a loop signature (the looping tool name) from a
125
+ * `user_message` payload's `content` when it is a runtime loop-detection
126
+ * nudge, else undefined. The nudge content is the fixed string
127
+ * `[runtime] possible loop detected: tool "<name>" has been called …`.
128
+ * Returns `tool:<name>` so recurring loops on the same tool cluster; falls
129
+ * back to a generic `loop` signature when the tool name can't be parsed.
130
+ */
131
+ export declare function loopSignatureOf(content: unknown): string | undefined;
132
+ /** Tolerantly read a session-JSONL line's payload when its `kind` matches —
133
+ * the canonical defensive accessor shared with `context-pressure.ts`
134
+ * (`doctor --context-pressure` folds the same persisted events). */
135
+ export declare function payloadOf(obj: unknown, kind: string): Record<string, unknown> | undefined;
136
+ /**
137
+ * Fold parsed session objects (and optional audit records) into the
138
+ * aggregates the rules consume. Every field access is defensive: missing
139
+ * payloads, wrong-typed fields, and unknown kinds are skipped, so
140
+ * old-vintage logs (no advisor kinds) and future kinds both pass through
141
+ * cleanly.
142
+ */
143
+ export declare function buildAdviceContext(sessions: ReadonlyArray<SessionEvents>, auditObjects?: ReadonlyArray<unknown>): AdviceContext;
144
+ export type AdviceThresholds = {
145
+ /** Minimum calls before a tool's error rate is judged at all. */
146
+ toolFailureMinCalls: number;
147
+ /** Error rate (errors/calls) at/above which the failure rule fires. */
148
+ toolFailureRate: number;
149
+ /** `continue` recoveries at/above which truncation pressure fires. */
150
+ truncationContinues: number;
151
+ /** Compactions in a single session at/above which thrash fires. */
152
+ compactionsPerSession: number;
153
+ /** Resolved asks per tool at/above which churn is judged. */
154
+ asksPerTool: number;
155
+ /** Minimum model responses before stop reasons are judged at all. */
156
+ stopMinResponses: number;
157
+ /** Anomalous-stop rate at/above which the stop rule fires. */
158
+ stopAnomalyRate: number;
159
+ /** Item 19 — occurrences of one error CLASS at/above which a
160
+ * failure_taxonomy entry is drafted. */
161
+ recoveryClusterMin: number;
162
+ /** Item 19 — occurrences of one loop SIGNATURE at/above which loop-break
163
+ * instructions advice fires. */
164
+ loopSignatureMin: number;
165
+ /** Item 21 — sessions that must each compact ≥ compactionsPerSession
166
+ * before a sub-agent restructure is suggested (chronic, not one-off). */
167
+ chronicCompactionSessions: number;
168
+ /** Item 21 — fraction of total tool byte-spend one tool must dominate for a
169
+ * sub-agent split to be suggested on the dominance signal. */
170
+ toolByteDominance: number;
171
+ /** Item 21 — minimum total tool bytes before dominance is judged at all
172
+ * (a handful of tiny calls shouldn't trip a restructure). */
173
+ toolByteMinTotal: number;
174
+ };
175
+ /**
176
+ * Canonical rule thresholds. runtime-core's in-run digest
177
+ * (observability.ts DIGEST_THRESHOLDS) mirrors these — it cannot import
178
+ * them (apps/cli depends on runtime-core, not vice versa), so keep the two
179
+ * in sync when tuning.
180
+ */
181
+ export declare const DEFAULT_ADVICE_THRESHOLDS: AdviceThresholds;
182
+ /** Stop reasons that are part of healthy operation; everything else
183
+ * (max_tokens, refusal, pause_turn, …) counts as anomalous. Mirrored by
184
+ * runtime-core's digest tally. */
185
+ export declare const CLEAN_STOP_REASONS: ReadonlySet<string>;
186
+ export type RuleOptions = {
187
+ /** The cwd spec, when one exists — enables patch suggestions. */
188
+ readonly spec?: Spec;
189
+ readonly thresholds?: Partial<AdviceThresholds>;
190
+ };
191
+ export type AdviceRule = (ctx: AdviceContext, opts?: RuleOptions) => AdviceFinding[];
192
+ /**
193
+ * Repeated tool failures: a tool with ≥ minCalls whose error rate crosses
194
+ * the threshold. Advice-only by design — `tool_config` is not in
195
+ * OPTIMIZABLE_PATHS (the whitelist is the autotune safety floor), so the
196
+ * suggestion points at the spec's `tool_config` block when one exists for
197
+ * the tool instead of emitting a patch. NOTE: `tool_stats.isError` includes
198
+ * permission-denied results; the churn rule covers the ask side of that.
199
+ */
200
+ export declare const ruleRepeatedToolFailures: AdviceRule;
201
+ /**
202
+ * Truncation pressure: `continue` recoveries (always max_output_tokens) at
203
+ * or above the threshold. Suggests a SpecPatch bumping `agent.max_tokens`
204
+ * (whitelisted in OPTIMIZABLE_PATHS): double the spec's current value, or
205
+ * add 16384 (2× the runtime's 8192 default) when the spec doesn't set one.
206
+ */
207
+ export declare const ruleTruncationPressure: AdviceRule;
208
+ /**
209
+ * Compaction thrash: any single session compacting ≥ threshold times.
210
+ * ADVICE-ONLY — no auto-applicable SpecPatch. `compaction.curate` is listed
211
+ * in OPTIMIZABLE_PATHS and lowers to IR (`packages/ir/src/index.ts`,
212
+ * `IrCompaction.curate`), but no target emitter or runtime-core path
213
+ * actually consumes it yet (see the IR field's doc comment). A patch that
214
+ * flips a runtime no-op would pass the `optimize --from-advice` eval gate
215
+ * trivially (inert change → equal pass rate) and get written into the
216
+ * user's spec while changing nothing, so this rule surfaces the finding as
217
+ * a warning with concrete alternatives instead of proposing `curate: true`.
218
+ * `compaction.threshold` is ALSO whitelisted, but the strict spec schema
219
+ * carries no such key today, so a threshold patch could never apply either.
220
+ */
221
+ export declare const ruleCompactionThrash: AdviceRule;
222
+ /**
223
+ * Permission churn: a tool prompting ≥ threshold times with 100% approved
224
+ * outcomes. NEVER a patch — permissions are excluded from OPTIMIZABLE_PATHS
225
+ * by design (an optimizer must not be able to widen its own permissions);
226
+ * the human gets the alwaysAllow one-liner with the evidence instead.
227
+ */
228
+ export declare const rulePermissionChurn: AdviceRule;
229
+ /**
230
+ * Stop-reason anomalies: a high rate of stops outside CLEAN_STOP_REASONS
231
+ * (end_turn / tool_use / stop_sequence are healthy; max_tokens, refusal,
232
+ * pause_turn, … are not). Advice-only — the right fix depends on which
233
+ * reason dominates.
234
+ */
235
+ export declare const ruleStopReasonAnomalies: AdviceRule;
236
+ /** One drafted failure_taxonomy entry (shape = the spec's entry schema:
237
+ * `{ class, pattern, recovery, hint? }`). */
238
+ export type FailureTaxonomyEntry = {
239
+ readonly class: string;
240
+ readonly pattern: string;
241
+ readonly recovery: string;
242
+ readonly hint?: string;
243
+ };
244
+ /**
245
+ * Item 19 — specificity floor for a drafted taxonomy `pattern`. The pattern is
246
+ * `errorName` verbatim, matched by the recovery engine as a case-insensitive
247
+ * SUBSTRING of `error.message`. A very short or generic name (e.g. "Error")
248
+ * drafts a rule that fires on almost every failure — worse than no entry. Such
249
+ * clusters are surfaced as ADVICE (a human should hand-write a precise pattern)
250
+ * rather than drafted into a patch.
251
+ */
252
+ export declare const TAXONOMY_MIN_PATTERN_LEN = 4;
253
+ /** Generic error tokens too broad to auto-draft, regardless of length. */
254
+ export declare const TAXONOMY_GENERIC_TOKENS: ReadonlySet<string>;
255
+ /** True when `errorName` is too broad to draft a taxonomy pattern for
256
+ * (too short, or a generic token). Case-insensitive. */
257
+ export declare function taxonomyPatternTooBroad(errorName: string): boolean;
258
+ /**
259
+ * Item 19 — failure-taxonomy learning. Clusters recurring `recovery` events
260
+ * by `errorName`; each class seen ≥ recoveryClusterMin times (and NOT already
261
+ * covered by the spec's taxonomy) becomes a draft `failure_taxonomy` entry
262
+ * whose `recovery` action is the one the runtime actually took most for that
263
+ * class, and whose `pattern` is a case-insensitive substring of the error
264
+ * name.
265
+ *
266
+ * `failure_taxonomy` IS whitelisted in OPTIMIZABLE_PATHS for every target, so
267
+ * the emitted patch rides the eval-gated `optimize --from-advice` apply. The
268
+ * patch REPLACES the whole `failure_taxonomy` array (existing entries +
269
+ * drafts) when the spec already has one, else ADDS the array — a whole-block
270
+ * edit the whitelist's prefix match allows. Budget caps aren't a field on the
271
+ * strict entry schema (`{ class, pattern, recovery, hint? }`), so the drafted
272
+ * `hint` carries the observed count + the "matches error.message" caveat and
273
+ * the recovery-engine's per-turn budget note.
274
+ */
275
+ export declare const ruleFailureTaxonomy: AdviceRule;
276
+ /**
277
+ * Item 19 — loop-break learning. A `[runtime] possible loop detected` nudge
278
+ * is NOT an error (no exception is thrown), so `matchNamedFailure` — which
279
+ * matches error.message only — can never catch it; a taxonomy entry is the
280
+ * wrong tool. This rule instead drafts an instructions-ADDENDUM as advice
281
+ * text (never a patch: `agent.instructions` IS optimizable, but a
282
+ * mechanically-appended nudge is a prompt edit a human should own, and the
283
+ * optimizer already rewrites instructions on its own signal). Fires per
284
+ * recurring loop signature (same tool looped in ≥ loopSignatureMin sessions/
285
+ * turns).
286
+ */
287
+ export declare const ruleLoopBreak: AdviceRule;
288
+ /**
289
+ * Targets whose AGENT block carries a `sub_agents:` map, so the drafted
290
+ * fragment (which sits under `agent:`) pastes in verbatim: cli and channel.
291
+ * Crew ALSO has sub_agents, but under each ROLE rather than a single `agent`
292
+ * block, so the paste location differs — it's excluded here rather than emit a
293
+ * fragment that lands in the wrong place. Any other target has no sub_agents
294
+ * block at all, so the rule stays silent (nowhere to paste).
295
+ */
296
+ export declare const SUB_AGENT_TARGETS: ReadonlySet<string>;
297
+ /** Draft a ready-to-paste `sub_agents:` YAML fragment moving `toolName`'s
298
+ * concern into its own sub-agent with its own context window. Two-space
299
+ * indented to sit under the spec's `agent:` block (cli/channel) — the CLI
300
+ * prints it verbatim in the advice text. */
301
+ export declare function subAgentFragment(toolName: string): string;
302
+ /**
303
+ * Item 21 — suggest a sub-agent split when context pressure is chronic:
304
+ * either the mined sessions ROUTINELY compact (≥ chronicCompactionSessions
305
+ * sessions each compacting ≥ compactionsPerSession times) OR one tool/concern
306
+ * DOMINATES tool byte-spend (≥ toolByteDominance of ≥ toolByteMinTotal total
307
+ * bytes). Moving the heavy concern behind a sub-agent's own context window
308
+ * relieves the parent.
309
+ *
310
+ * STRICTLY suggest+scaffold — NEVER a patch: a structural change (adding a
311
+ * sub-agent + rewriting instructions) isn't eval-safe to auto-apply, so this
312
+ * emits advice text carrying a ready-to-paste `sub_agents:` fragment (the
313
+ * correct spec key — NOT `agents:`). Gated per target: only cli/channel/crew
314
+ * schemas have a `sub_agents` block; on any other target (or with no spec) the
315
+ * rule stays silent, since there's nowhere to paste it.
316
+ */
317
+ export declare const ruleSubAgentSplit: AdviceRule;
318
+ export declare const ADVICE_RULES: ReadonlyArray<AdviceRule>;
319
+ /**
320
+ * Run every rule and rank the findings: warn before info, then by the
321
+ * magnitude of the primary count, then by id (deterministic output). Each
322
+ * emitted patch was already pre-validated by its rule via `patchOrAdvice`.
323
+ */
324
+ export declare function runAdviceRules(ctx: AdviceContext, opts?: RuleOptions): AdviceFinding[];
325
+ export type SuggestionsFile = {
326
+ readonly generatedAt: string;
327
+ readonly sessionIds: ReadonlyArray<string>;
328
+ /** Only the findings whose suggestion is a validated SpecPatch. */
329
+ readonly suggestions: ReadonlyArray<{
330
+ readonly findingId: string;
331
+ readonly severity: AdviceSeverity;
332
+ readonly summary: string;
333
+ readonly patch: SpecPatch;
334
+ }>;
335
+ };
336
+ /** The `suggestions.json` payload — the SpecPatch list a future
337
+ * `optimize --from-advice` consumes. Advice-only findings are report-only. */
338
+ export declare function buildSuggestionsFile(findings: ReadonlyArray<AdviceFinding>, sessionIds: ReadonlyArray<string>, generatedAt: string): SuggestionsFile;
339
+ export declare function escapeHtml(s: string): string;
340
+ /** Self-contained `report.html` for `crewhaus advise` — ranked findings with
341
+ * evidence and the suggested patch/advice per finding. */
342
+ export declare function renderAdviceHtml(input: {
343
+ readonly findings: ReadonlyArray<AdviceFinding>;
344
+ readonly sessionIds: ReadonlyArray<string>;
345
+ readonly generatedAt: string;
346
+ }): string;
347
+ /** One line per finding for the CLI's text mode. */
348
+ export declare function formatFindingLines(f: AdviceFinding): string[];