@fenglimg/fabric-server 2.2.0-rc.1 → 2.2.0-rc.4

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 (3) hide show
  1. package/dist/index.d.ts +155 -143
  2. package/dist/index.js +3011 -3717
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
- import { AgentsMeta, KnowledgeTestIndex, AgentsLayer, AgentsTopologyType, KnowledgeType, Layer, StableId, AgentsMetaCounters, EventLedgerEventInput, EventLedgerEvent, RuleDescriptionIndexItem, LedgerEntry } from '@fenglimg/fabric-shared';
3
2
  import { FabExtractKnowledgeInput, FabExtractKnowledgeOutput, FabReviewInput, FabReviewOutput } from '@fenglimg/fabric-shared/schemas/api-contracts';
3
+ import { EventLedgerEventInput, EventLedgerEvent, RuleDescriptionIndexItem, LedgerEntry, AgentsMeta } from '@fenglimg/fabric-shared';
4
4
 
5
5
  interface InFlightTracker {
6
6
  enter(requestId: string): void;
@@ -125,6 +125,25 @@ type CiteCoverageReport = {
125
125
  compliant_cites?: number;
126
126
  noncompliant_cites?: number;
127
127
  uncorrelatable_edits?: number;
128
+ recall_backed_edits?: number;
129
+ recall_coverage_rate?: number | null;
130
+ exposed_and_mutated?: {
131
+ count: number;
132
+ ids?: string[];
133
+ };
134
+ mutations_observed?: {
135
+ count: number;
136
+ };
137
+ mutation_pool?: {
138
+ attributed: number;
139
+ unattributed_workspace_dirty: number;
140
+ };
141
+ sessions_closed?: {
142
+ count: number;
143
+ };
144
+ by_store?: Record<string, {
145
+ qualifying_cites: number;
146
+ }>;
128
147
  };
129
148
  per_client?: Record<string, Partial<CiteCoverageReport["metrics"]>>;
130
149
  dismissed_reason_histogram?: Record<string, number>;
@@ -146,6 +165,7 @@ declare function runDoctorCiteCoverage(projectRoot: string, options: {
146
165
  client: "cc" | "codex" | "cursor" | "all";
147
166
  layer?: "team" | "personal" | "all";
148
167
  until?: number;
168
+ recallWindowMs?: number;
149
169
  }): Promise<CiteCoverageReport>;
150
170
  type ArchiveHistoryEntry = {
151
171
  session_id_short: string;
@@ -297,84 +317,131 @@ declare function enrichDescriptions(projectRoot: string, opts?: {
297
317
  dryRun?: boolean;
298
318
  }): Promise<EnrichDescriptionsReport>;
299
319
 
300
- type KnowledgeMetaBuildSource = "doctor_fix" | "sync_meta";
301
- type KnowledgeMetaBuildResult = {
302
- meta: AgentsMeta;
303
- knowledgeTestIndex: KnowledgeTestIndex;
304
- changed: boolean;
305
- };
306
- type WriteKnowledgeMetaOptions = {
307
- source: KnowledgeMetaBuildSource;
308
- };
320
+ interface Bm25Document {
321
+ id: string;
322
+ tokens: string[];
323
+ }
324
+ interface Bm25Model {
325
+ /**
326
+ * BM25 score of document `id` against the (pre-tokenized) query terms.
327
+ * Returns 0 for an unknown id, an empty document, no query terms, or no
328
+ * term overlap. Query-term duplicates are collapsed — repeating a term in
329
+ * the query does not inflate the score (term frequency is a document
330
+ * property, not a query property).
331
+ */
332
+ scoreDoc(id: string, queryTerms: string[]): number;
333
+ }
309
334
  /**
310
- * v2.0-rc.24 TASK-07: Load a Map<stable_id, knowledge_type> from the
311
- * project's `.fabric/agents.meta.json`. Consumed by the doctor cite-coverage
312
- * routing (TASK-08) to dispatch cites to the correct policy bucket
313
- * (decision/pitfall = strict contract / model = reference-only /
314
- * guideline+process = deferred to rc.25 LLM-judge). Cited ids absent from
315
- * this map fall into the `cite_id_unresolved` bucket.
316
- *
317
- * **Plural knowledge_type contract (rc.29 BUG-C1 unification):** the returned
318
- * map values are the PLURAL `KnowledgeType` enum (`"models" | "decisions" |
319
- * "guidelines" | "pitfalls" | "processes"`) — matching disk frontmatter,
320
- * filesystem layout, MCP I/O surface, and the canonical `KnowledgeTypeSchema`
321
- * exported from `@fenglimg/fabric-shared`. Legacy singular frontmatter is
322
- * normalized at parse time (see `SINGULAR_TO_PLURAL` in `parseFrontmatter`);
323
- * downstream callers (TASK-08 doctor) match against the plural enum.
324
- *
325
- * Both team (KT-*) and personal (KP-*) entries are included — they live in
326
- * the same `meta.nodes` map.
327
- *
328
- * Graceful on failure: a missing meta file, malformed JSON, or schema
329
- * validation failure all yield an empty Map (no throw). The doctor will then
330
- * surface every cite as `cite_id_unresolved`, which is the safe degraded
331
- * mode.
335
+ * Build a BM25 model over `docs`. The corpus statistics (document frequency,
336
+ * average document length) are computed once here; `scoreDoc` is then O(query
337
+ * terms) per call.
332
338
  */
333
- declare function loadKbIdTypeMap(projectRootInput: string): Promise<Map<string, KnowledgeType>>;
334
- declare function buildKnowledgeMeta(projectRootInput: string): Promise<KnowledgeMetaBuildResult>;
335
- declare function writeKnowledgeMeta(projectRootInput: string, options: WriteKnowledgeMetaOptions): Promise<KnowledgeMetaBuildResult>;
336
- declare function computeKnowledgeBasedAgentsMeta(projectRootInput: string, existingMeta?: AgentsMeta): Promise<AgentsMeta>;
337
- declare function computeKnowledgeTestIndex(projectRootInput: string, computedMeta: AgentsMeta, previousIndex?: KnowledgeTestIndex): Promise<KnowledgeTestIndex>;
338
- declare function deriveKnowledgeMetaLayer(relativePath: string): AgentsLayer;
339
- declare function deriveKnowledgeMetaTopologyType(relativePath: string): AgentsTopologyType;
340
- declare function isSameKnowledgeTestIndex(left: KnowledgeTestIndex, right: KnowledgeTestIndex): boolean;
341
- declare function stableStringify(value: unknown): string;
339
+ declare function buildBm25Model(docs: Bm25Document[]): Bm25Model;
342
340
 
341
+ interface ConflictEntry {
342
+ stable_id: string;
343
+ /** Plural knowledge_type ("decisions" | "pitfalls" | "guidelines" | "models" | "processes"). */
344
+ knowledge_type: string;
345
+ /** "team" | "personal". Conflicts are only meaningful within one layer. */
346
+ layer: string;
347
+ /** Title + body (or any text used for similarity). */
348
+ text: string;
349
+ }
350
+ type ConflictVerdict = "conflict" | "similar" | "unknown";
351
+ interface ConflictPair {
352
+ a: string;
353
+ b: string;
354
+ knowledge_type: string;
355
+ layer: string;
356
+ /** Symmetric normalized bm25 similarity in [0,1]. */
357
+ similarity: number;
358
+ /**
359
+ * "unknown" until a judge classifies it (cheap pass leaves it unknown =
360
+ * needs-human-review). "conflict" = the judge ruled a real contradiction
361
+ * (escalates to error). "similar" = judged not-a-conflict (stays a warn /
362
+ * possible duplicate).
363
+ */
364
+ verdict: ConflictVerdict;
365
+ rationale?: string;
366
+ }
367
+ type ConflictJudge = (a: ConflictEntry, b: ConflictEntry) => Promise<{
368
+ isConflict: boolean;
369
+ rationale: string;
370
+ }>;
371
+ declare const DEFAULT_CONFLICT_SIMILARITY_THRESHOLD = 0.5;
343
372
  /**
344
- * v2.0 KnowledgeIdAllocator
345
- *
346
- * Wraps the pure `allocateKnowledgeId` allocator with persistence: it reads
347
- * `agents.meta.json`, advances the counter for the requested (layer, type)
348
- * pair, and writes the updated meta atomically (write-to-tmp + rename) so
349
- * concurrent readers always see a consistent file.
373
+ * Symmetric, [0,1]-normalized bm25 similarity between two docs sharing a model.
374
+ * For each direction we measure how much of the target doc's self-relevance the
375
+ * other doc's terms recover (scoreDoc(target, otherTokens) / scoreDoc(target,
376
+ * targetTokens)), then take the MIN of both directions conservative: both
377
+ * entries must strongly overlap, so a short entry incidentally contained in a
378
+ * long one does not over-fire.
379
+ */
380
+ declare function pairSimilarity(model: ReturnType<typeof buildBm25Model>, a: {
381
+ id: string;
382
+ tokens: string[];
383
+ }, b: {
384
+ id: string;
385
+ tokens: string[];
386
+ }): number;
387
+ /**
388
+ * Cheap deterministic pass: candidate conflicting/duplicate pairs. Compares
389
+ * only entries sharing (type, layer), via bm25 similarity ≥ threshold. Returns
390
+ * pairs sorted by similarity descending (stable_id-tie-broken for determinism).
391
+ * Every returned pair has verdict "unknown" — the cheap pass cannot tell a
392
+ * conflict from a benign duplicate; that is the judge's job.
350
393
  *
351
- * Counters are MONOTONIC across the lifetime of the meta file: deleting a
352
- * knowledge entry does NOT free its counter slot, so previously-allocated
353
- * stable_ids remain unique even after their files are removed.
394
+ * O(G · n_g²) where G = groups and n_g = entries per group. Conflicts only make
395
+ * sense within one (type, layer), so the quadratic stays bounded to small
396
+ * same-bucket sets, not the whole corpus.
397
+ */
398
+ declare function findConflictCandidates(entries: ConflictEntry[], opts?: {
399
+ threshold?: number;
400
+ }): ConflictPair[];
401
+ /**
402
+ * Full lint. Always runs the cheap pass; when `judge` is supplied (deep mode)
403
+ * each candidate is classified into conflict/similar. A judge throw leaves the
404
+ * pair as "unknown" (degrade-safe — a flaky judge never crashes doctor).
354
405
  *
355
- * Key invariants:
356
- * - Counters envelope is initialized to zeros if absent (v1.x meta compat).
357
- * - Each allocate() call performs read → mutate → atomic-write in sequence.
358
- * - The returned id is guaranteed to differ from every previously-returned
359
- * id for the same meta path.
406
+ * Entry lookup for the judge is by stable_id from the same `entries` array.
360
407
  */
361
- declare class KnowledgeIdAllocator {
362
- private readonly metaPath;
363
- constructor(metaPath: string);
364
- /**
365
- * Allocate the next stable_id for the given (layer, type) pair and persist
366
- * the advanced counter to `agents.meta.json`.
367
- */
368
- allocate(layer: Layer, type: KnowledgeType): Promise<StableId>;
369
- /**
370
- * Returns the current counters envelope, defaulting to all-zero slots when
371
- * the meta file is absent or pre-v2.0 (counters key missing).
372
- */
373
- getCounters(): Promise<AgentsMetaCounters>;
374
- private readMeta;
375
- private normalizeCounters;
376
- private writeMetaAtomic;
408
+ declare function lintConflicts(entries: ConflictEntry[], opts?: {
409
+ threshold?: number;
410
+ judge?: ConflictJudge;
411
+ }): Promise<ConflictPair[]>;
412
+
413
+ interface ConflictLintReport {
414
+ status: "ok";
415
+ threshold: number;
416
+ deep: boolean;
417
+ /** Total candidate pairs (similarity threshold). */
418
+ candidate_count: number;
419
+ /** Subset judged a real contradiction (deep mode only). */
420
+ conflict_count: number;
421
+ pairs: ConflictPair[];
377
422
  }
423
+ /**
424
+ * v2.2 W5 R6 (读侧 cutover): load canonical knowledge entries with bodies from
425
+ * the read-set STORES (cross-store on-the-fly) instead of the retired
426
+ * co-location agents.meta node index. Skips pending/draft staging entries
427
+ * (conflict detection targets the curated corpus) and any entry missing a
428
+ * knowledge_type. collectStoreCanonicalEntries already reads each store entry's
429
+ * body + parsed frontmatter and degrades to [] when no store is in the read-set.
430
+ */
431
+ declare function loadConflictEntries(projectRoot: string): Promise<ConflictEntry[]>;
432
+ /**
433
+ * Run the knowledge-conflict lint. Always runs the cheap bm25 candidate pass;
434
+ * when `deep` is set AND a judge is supplied, escalates candidates to
435
+ * conflict/similar verdicts via the injected LLM judge.
436
+ *
437
+ * threshold resolution: opts.threshold → fabric-config
438
+ * conflict_lint_similarity_threshold → DEFAULT_CONFLICT_SIMILARITY_THRESHOLD.
439
+ */
440
+ declare function runDoctorConflictLint(projectRoot: string, opts?: {
441
+ threshold?: number;
442
+ deep?: boolean;
443
+ judge?: ConflictJudge;
444
+ }): Promise<ConflictLintReport>;
378
445
 
379
446
  /**
380
447
  * Append-evidence-on-collision service for fab_extract_knowledge.
@@ -460,6 +527,8 @@ type PlanContextInput = {
460
527
  correlation_id?: string;
461
528
  session_id?: string;
462
529
  target_paths?: string[];
530
+ layer_filter?: "team" | "personal" | "both";
531
+ include_related?: boolean;
463
532
  };
464
533
  type RequirementProfile = {
465
534
  target_path: string;
@@ -489,6 +558,7 @@ type PlanContextResult = {
489
558
  auto_healed?: boolean;
490
559
  previous_revision_hash?: string;
491
560
  redirects?: Record<string, string>;
561
+ related_appended?: Record<string, string>;
492
562
  };
493
563
  type SelectionTokenState = {
494
564
  token: string;
@@ -529,10 +599,13 @@ type RecallResult = PlanContextResult & {
529
599
  level: "L0" | "L1" | "L2";
530
600
  path: string;
531
601
  body: string;
602
+ store?: {
603
+ alias: string;
604
+ };
532
605
  }>;
533
606
  selected_stable_ids: string[];
534
607
  diagnostics: Array<{
535
- code: "missing_knowledge_metadata";
608
+ code: "missing_knowledge_metadata" | "unresolved_selected_id";
536
609
  severity: "warn";
537
610
  stable_id: string;
538
611
  message: string;
@@ -612,16 +685,15 @@ interface KnowledgeSyncOptions {
612
685
  /** When true, invalid frontmatter throws RuleValidationError (default: false — collect as warning). */
613
686
  throwOnInvalidFrontmatter?: boolean;
614
687
  /**
615
- * v2.0.0-rc.29 TASK-005 (BUG-G1): when true, `ensureKnowledgeFresh`
616
- * synchronously follows a drift detection with a `reconcileKnowledge`
617
- * call to materialize the auto-heal (rewrite agents.meta.json + emit a
618
- * paired `knowledge_meta_auto_healed` event). Default false preserves
619
- * the rc.28 hot-path semantics where drift detection never blocks the
620
- * MCP read on a meta rebuild. Opt-in is intended for callers that can
621
- * tolerate ~tens-of-ms extra latency in exchange for the invariant
622
- * "every knowledge_drift_detected has a paired heal event in the same
623
- * tail window." Audit (BUG-G1) found 5/72 drifts healed on this repo
624
- * (~7%) because the hot path emitted detect-only events.
688
+ * v2.0.0-rc.29 TASK-005 (BUG-G1): originally opted the hot path into a
689
+ * follow-up `reconcileKnowledge` (rewrite agents.meta.json) so every
690
+ * detected drift got a paired heal event.
691
+ *
692
+ * v2.2 W5 R2 (agents.meta decolo): retained as a NO-OP for backward
693
+ * compatibility the co-location agents.meta.json it used to rebuild no
694
+ * longer exists (knowledge lives in stores; read paths cut over to the
695
+ * cross-store model). MCP tool call sites still pass `autoHealOnDrift: true`;
696
+ * it is now ignored.
625
697
  */
626
698
  autoHealOnDrift?: boolean;
627
699
  }
@@ -666,32 +738,6 @@ declare function invalidateKnowledgeSyncCooldown(projectRoot: string): void;
666
738
  * hot-path consumers (MCP tools).
667
739
  */
668
740
  declare function ensureKnowledgeFresh(projectRoot: string, opts?: KnowledgeSyncOptions): Promise<KnowledgeSyncReport>;
669
- interface ReconcileKnowledgeOptions {
670
- /**
671
- * Identifies who triggered the reconcile; controls which summary ledger event is written.
672
- *
673
- * v2.0.0-rc.23 TASK-005 (a-B): `auto-heal-description` added so plan_context
674
- * can drive a full reconcile when it detects nodes with `description === undefined`
675
- * (legacy meta drift the revision-hash gate cannot detect).
676
- *
677
- * v2.0.0-rc.27 TASK-001 (§2.9 root): `post-approve` / `post-modify` added so
678
- * `fab_review` approve/modify-layer-flip can drive an immediate meta rebuild
679
- * — without this the new entry's `nodes[id]` stays empty until the next
680
- * plan_context call's auto-heal, which leaves the entry undiscoverable in
681
- * the description_index window between approve and the next hint call.
682
- */
683
- trigger?: "startup" | "doctor" | "manual" | "auto-heal-description" | "auto-heal-after-drift" | "post-approve" | "post-modify";
684
- }
685
- /**
686
- * Full scan + rewrites agents.meta.json with ground-truth disk state + emits
687
- * ledger events. Used by startup (TASK-022) and doctor repair (TASK-023).
688
- * Returns reconciled_files listing all paths whose meta was updated.
689
- *
690
- * When `opts.trigger` is `'startup'`, a `meta_reconciled_on_startup` summary
691
- * ledger event is appended after per-file drift events. Other trigger values
692
- * append a `meta_reconciled` event. Omitting the trigger skips the summary.
693
- */
694
- declare function reconcileKnowledge(projectRoot: string, opts?: ReconcileKnowledgeOptions): Promise<KnowledgeSyncReport>;
695
741
 
696
742
  type LedgerSourceFilter = "ai" | "human";
697
743
  type StoredLedgerEntry = LedgerEntry & {
@@ -727,40 +773,6 @@ type RehydratedAgentsMetaSnapshot = {
727
773
  };
728
774
  declare function rehydrateAgentsMetaAt(projectRoot: string, target: RehydrateTarget): Promise<RehydratedAgentsMetaSnapshot>;
729
775
 
730
- declare function readAgentsMeta(projectRoot: string): Promise<AgentsMeta>;
731
-
732
- type KnowledgeEntryItem = {
733
- path: string;
734
- content: string;
735
- };
736
- type DescriptionStub = {
737
- path: string;
738
- description: string;
739
- };
740
- type HumanLockedNearby = {
741
- file: string;
742
- excerpt: string;
743
- };
744
- type KnowledgePayload = {
745
- L0: string;
746
- L1: KnowledgeEntryItem[];
747
- L2: KnowledgeEntryItem[];
748
- human_locked_nearby: HumanLockedNearby[];
749
- description_stubs?: DescriptionStub[];
750
- };
751
- type GetKnowledgeInput = {
752
- path: string;
753
- client_hash?: string;
754
- correlation_id?: string;
755
- session_id?: string;
756
- };
757
- type GetKnowledgeResult = {
758
- revision_hash: string;
759
- stale: boolean;
760
- rules: KnowledgePayload;
761
- };
762
- declare function getKnowledge(projectRoot: string, input: GetKnowledgeInput): Promise<GetKnowledgeResult>;
763
-
764
776
  /**
765
777
  * Shared constants used across the server package.
766
778
  */
@@ -803,4 +815,4 @@ interface ShutdownHandlerDeps {
803
815
  */
804
816
  declare function createShutdownHandler(deps: ShutdownHandlerDeps): () => void;
805
817
 
806
- export { AGENTS_MD_RESOURCE_URI, type ArchiveHistoryEntry, type ArchiveHistoryReport, type CiteCoverageReport, type DoctorApplyLintMutation, type DoctorApplyLintMutationKind, type DoctorApplyLintReport, type DoctorFixReport, type DoctorIssue, type DoctorReport, EVENT_LEDGER_PATH, type EnrichDescriptionsCandidate, type EnrichDescriptionsMode, type EnrichDescriptionsReport, FABRIC_SERVER_INSTRUCTIONS, type HistoryAllReport, type HistoryDayRow, type InFlightTracker, KnowledgeIdAllocator, type KnowledgeMetaBuildResult, type KnowledgeMetaBuildSource, type KnowledgeSyncLedgerEvent, type KnowledgeSyncOptions, type KnowledgeSyncReport, LEDGER_PATH, LEGACY_LEDGER_PATH, type LedgerEvent, METRICS_LEDGER_PATH, METRIC_COUNTER_NAMES, type MetricCounterName, type MetricsRow, type PlanContextInput, type PlanContextResult, type RecallInput, type RecallResult, type ReconcileKnowledgeOptions, type RequirementProfile, type SelectionTokenState, type ShutdownHandlerDeps, type StructuredWarning, type WriteKnowledgeMetaOptions, appendEventLedgerEvent, buildKnowledgeMeta, bumpCounter, computeKnowledgeBasedAgentsMeta, computeKnowledgeTestIndex, contextCache, createFabricServer, createInFlightTracker, createShutdownHandler, deriveKnowledgeMetaLayer, deriveKnowledgeMetaTopologyType, drainCounters, enrichDescriptions, ensureKnowledgeFresh, extractKnowledge, flushAndSyncEventLedger, flushMetrics, formatPreexistingRootMessage, getEventLedgerPath, getKnowledge, getLedgerPath, getLegacyLedgerPath, getMetricsLedgerPath, invalidateKnowledgeSyncCooldown, isSameKnowledgeTestIndex, loadKbIdTypeMap, planContext, readAgentsMeta, readEventLedger, readLedger, readMetrics, readSelectionToken, recall, reconcileKnowledge, rehydrateAgentsMetaAt, resolveLedgerPaths, reviewKnowledge, runDoctorApplyLint, runDoctorArchiveHistory, runDoctorCiteCoverage, runDoctorFix, runDoctorHistoryAll, runDoctorReport, stableStringify, startMetricsFlush, startRotationTick, startStdioServer, stopMetricsFlush, stopRotationTick, writeKnowledgeMeta };
818
+ export { AGENTS_MD_RESOURCE_URI, type ArchiveHistoryEntry, type ArchiveHistoryReport, type CiteCoverageReport, type ConflictEntry, type ConflictJudge, type ConflictLintReport, type ConflictPair, type ConflictVerdict, DEFAULT_CONFLICT_SIMILARITY_THRESHOLD, type DoctorApplyLintMutation, type DoctorApplyLintMutationKind, type DoctorApplyLintReport, type DoctorFixReport, type DoctorIssue, type DoctorReport, EVENT_LEDGER_PATH, type EnrichDescriptionsCandidate, type EnrichDescriptionsMode, type EnrichDescriptionsReport, FABRIC_SERVER_INSTRUCTIONS, type HistoryAllReport, type HistoryDayRow, type InFlightTracker, type KnowledgeSyncLedgerEvent, type KnowledgeSyncOptions, type KnowledgeSyncReport, LEDGER_PATH, LEGACY_LEDGER_PATH, type LedgerEvent, METRICS_LEDGER_PATH, METRIC_COUNTER_NAMES, type MetricCounterName, type MetricsRow, type PlanContextInput, type PlanContextResult, type RecallInput, type RecallResult, type RequirementProfile, type SelectionTokenState, type ShutdownHandlerDeps, type StructuredWarning, appendEventLedgerEvent, bumpCounter, contextCache, createFabricServer, createInFlightTracker, createShutdownHandler, drainCounters, enrichDescriptions, ensureKnowledgeFresh, extractKnowledge, findConflictCandidates, flushAndSyncEventLedger, flushMetrics, formatPreexistingRootMessage, getEventLedgerPath, getLedgerPath, getLegacyLedgerPath, getMetricsLedgerPath, invalidateKnowledgeSyncCooldown, lintConflicts, loadConflictEntries, pairSimilarity, planContext, readEventLedger, readLedger, readMetrics, readSelectionToken, recall, rehydrateAgentsMetaAt, resolveLedgerPaths, reviewKnowledge, runDoctorApplyLint, runDoctorArchiveHistory, runDoctorCiteCoverage, runDoctorConflictLint, runDoctorFix, runDoctorHistoryAll, runDoctorReport, startMetricsFlush, startRotationTick, startStdioServer, stopMetricsFlush, stopRotationTick };