@harness-engineering/orchestrator 0.8.4 → 0.9.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.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _harness_engineering_types from '@harness-engineering/types';
2
- import { Issue, AgentEvent, WorkflowConfig, TokenUsage, ConcernSignal, ScopeTier, EscalationConfig, IssueRoutingDecision, Result, WorkflowDefinition, BackendDef, RoutingConfig, WorkspaceConfig, HooksConfig, AgentBackend, SessionStartParams, AgentSession, AgentError, TurnParams, TurnResult, CheckScriptDefinition, OutputRetentionConfig, RoutingDecision, RoutingUseCase, ContainerConfig, SecretConfig, AgentConfig, LocalModelStatus, CustomTaskDefinition, TokenScope, AuthToken, AuthTokenPublic, IndexedFileKind, SessionSearchResult, ReindexStats, SessionSummarizationConfig, SessionSummary, SessionSummaryMeta, SessionsConfig, GatewayEvent, NotificationEnvelope, NotificationDeliveryResult, NotificationSinkConfig, NotificationsConfig } from '@harness-engineering/types';
3
- import { IssueTrackerClient, Issue as Issue$1, TrackerConfig, CacheMetricsRecorder, ArchiveHooks, SkillProposal, ProposalGateFinding } from '@harness-engineering/core';
2
+ import { Issue, AgentEvent, WorkflowConfig, TokenUsage, ConcernSignal, ScopeTier, EscalationConfig, IssueRoutingDecision, Result, WorkflowDefinition, BackendDef, RoutingConfig, WorkspaceConfig, HooksConfig, AgentBackend, SessionStartParams, AgentSession, AgentError, TurnParams, TurnResult, CheckScriptDefinition, OutputRetentionConfig, RoutingDecision, RoutingUseCase, ContainerConfig, SecretConfig, AgentConfig, LocalModelStatus, CustomTaskDefinition, MaintenanceConfig, TokenScope, AuthToken, AuthTokenPublic, IndexedFileKind, SessionSearchResult, ReindexStats, SessionSummarizationConfig, SessionSummary, SessionSummaryMeta, SessionsConfig, GatewayEvent, NotificationEnvelope, NotificationDeliveryResult, NotificationSinkConfig, NotificationsConfig } from '@harness-engineering/types';
3
+ import { IssueTrackerClient, Issue as Issue$1, TrackerConfig, eventSourcing, CacheMetricsRecorder, ArchiveHooks, SkillProposal, ProposalGateFinding } from '@harness-engineering/core';
4
4
  import { EnrichedSpec, ComplexityScore, SimulationResult, IntelligencePipeline, WeightedRecommendation, AnalysisProvider } from '@harness-engineering/intelligence';
5
5
  import { GraphStore } from '@harness-engineering/graph';
6
6
  import { execFile } from 'node:child_process';
@@ -1044,6 +1044,15 @@ declare class RoadmapTrackerAdapter implements IssueTrackerClient {
1044
1044
  * state and clearing the assignee field.
1045
1045
  */
1046
1046
  releaseIssue(issueId: string): Promise<Result<void, Error>>;
1047
+ /**
1048
+ * Resolve the roadmap store anchored on the configured aggregate file path.
1049
+ * The shard backend is chosen when a sibling `roadmap.d/` exists next to the
1050
+ * file; otherwise the monolith file is read/written whole. Callers guard
1051
+ * `this.config.filePath` before invoking.
1052
+ */
1053
+ private resolveStore;
1054
+ /** Load the roadmap via the store (sharded or monolith), returning a Result. */
1055
+ private loadRoadmap;
1047
1056
  private findFeatureById;
1048
1057
  /**
1049
1058
  * Fetches full issue details for a list of identifiers.
@@ -1062,12 +1071,53 @@ declare class RoadmapTrackerAdapter implements IssueTrackerClient {
1062
1071
  }
1063
1072
 
1064
1073
  /**
1065
- * Interface for Linear GraphQL tool extension.
1066
- * This is a stub implementation for Phase 4.
1074
+ * Interface for a Linear GraphQL tool extension — a thin authenticated client
1075
+ * over Linear's GraphQL API (https://linear.app/developers/graphql).
1067
1076
  */
1068
1077
  interface LinearGraphQLExtension {
1078
+ /**
1079
+ * Execute a GraphQL operation. Resolves to `Ok(data)` (the `data` object of
1080
+ * the GraphQL envelope) on success, or `Err` on a transport failure, a non-2xx
1081
+ * HTTP status, or a GraphQL `errors` array.
1082
+ */
1069
1083
  query(query: string, variables?: Record<string, unknown>): Promise<Result<unknown, Error>>;
1070
1084
  }
1085
+ interface LinearGraphQLClientOptions {
1086
+ /**
1087
+ * Linear authentication token. A personal API key is sent verbatim in the
1088
+ * `Authorization` header; an OAuth access token must be passed already prefixed
1089
+ * with `Bearer ` (Linear's two supported schemes).
1090
+ */
1091
+ apiKey: string;
1092
+ /** Override the GraphQL endpoint (e.g. a proxy). Defaults to Linear's API. */
1093
+ endpoint?: string;
1094
+ /** Injectable fetch for tests; defaults to the global `fetch`. */
1095
+ fetchFn?: typeof fetch;
1096
+ }
1097
+ /**
1098
+ * Real Linear GraphQL client. Replaces {@link LinearGraphQLStub}, which only
1099
+ * logged the query and returned an empty object. POSTs the operation to Linear's
1100
+ * GraphQL endpoint with the API key, and normalizes the three failure modes
1101
+ * (transport throw, non-2xx HTTP, GraphQL `errors`) into a single `Err`.
1102
+ */
1103
+ declare class LinearGraphQLClient implements LinearGraphQLExtension {
1104
+ private readonly apiKey;
1105
+ private readonly endpoint;
1106
+ private readonly fetchFn;
1107
+ constructor(opts: LinearGraphQLClientOptions);
1108
+ query(query: string, variables?: Record<string, unknown>): Promise<Result<unknown, Error>>;
1109
+ /** POST the operation to Linear, normalizing transport throws into an `Err`. */
1110
+ private sendRequest;
1111
+ /** Build the error for a non-2xx HTTP response, including a truncated body. */
1112
+ private httpError;
1113
+ /** Parse the JSON envelope, normalizing parse failures into an `Err`. */
1114
+ private parseEnvelope;
1115
+ }
1116
+ /**
1117
+ * @deprecated Phase-4 placeholder retained for backward compatibility. It logs
1118
+ * the query and returns an empty object; use {@link LinearGraphQLClient} for a
1119
+ * real authenticated client.
1120
+ */
1071
1121
  declare class LinearGraphQLStub implements LinearGraphQLExtension {
1072
1122
  query(query: string, _variables?: Record<string, unknown>): Promise<Result<unknown, Error>>;
1073
1123
  }
@@ -1264,6 +1314,15 @@ type RunOrigin = 'cron' | 'cli' | {
1264
1314
  kind: 'chain';
1265
1315
  upstreamTaskId: string;
1266
1316
  };
1317
+ /**
1318
+ * Run mode for a maintenance task (on-demand pipeline, D4).
1319
+ *
1320
+ * - 'fix' — current cron behavior: mechanical-ai dispatches on findings,
1321
+ * pure-ai always dispatches, PRs may be opened. Default.
1322
+ * - 'report' — read-only sweep: run the check step, record findings, and take
1323
+ * the no-dispatch branch — never dispatch a fix agent or open a PR.
1324
+ */
1325
+ type RunMode = 'report' | 'fix';
1267
1326
  /**
1268
1327
  * Per-task cost ceiling (Hermes Phase 5).
1269
1328
  *
@@ -1325,6 +1384,15 @@ interface TaskDefinition {
1325
1384
  outputRetention?: OutputRetentionConfig;
1326
1385
  /** Hermes Phase 2 — Marks tasks originating from `customTasks` config. */
1327
1386
  isCustom?: boolean;
1387
+ /**
1388
+ * On-demand maintenance pipeline (D5). When `true`, the task is excluded
1389
+ * from the human "overdue" sweep computed by `selectTasks` — used for
1390
+ * git-mutating housekeeping (`main-sync`, `perf-baselines`,
1391
+ * `session-cleanup`) and one-shot backfills (`proposal-provenance-backfill`)
1392
+ * that are infra hygiene, not developer-facing health signals.
1393
+ * `undefined` (default) → sweep-eligible.
1394
+ */
1395
+ excludeFromHumanSweep?: boolean;
1328
1396
  }
1329
1397
  /**
1330
1398
  * Result of a single maintenance task run.
@@ -1533,6 +1601,13 @@ declare class BackendRouter {
1533
1601
  private validateReferences;
1534
1602
  }
1535
1603
 
1604
+ /**
1605
+ * The lanes projection shape, re-exported so the orchestrator can hold a
1606
+ * read-back snapshot without importing the core `eventSourcing` namespace
1607
+ * directly — keeping this module the single orchestrator<->core lane coupling.
1608
+ */
1609
+ type PersistedLanes = eventSourcing.LanesProjection;
1610
+
1536
1611
  /**
1537
1612
  * Derives the worktree seed paths from a workflow config when
1538
1613
  * {@link WorkspaceConfig.seedPaths} is not set explicitly.
@@ -1545,6 +1620,20 @@ declare class BackendRouter {
1545
1620
  * otherwise miss it.
1546
1621
  */
1547
1622
  declare function deriveSeedPaths(config: WorkflowConfig): string[];
1623
+ /**
1624
+ * Resolve a maintenance `checkCommand` (or housekeeping command) into a runnable
1625
+ * argv. Built-in maintenance task definitions store the command as harness
1626
+ * SUBCOMMAND argv (e.g. `['check-arch']`, `['graph','scan']`); `main-sync`
1627
+ * carries an explicit leading `'harness'` literal. Either way the command must
1628
+ * be executed through the `harness` binary, so:
1629
+ * - `['check-arch']` → `['harness', 'check-arch']`
1630
+ * - `['harness','sync-main']` → `['harness', 'sync-main']` (no double-prefix)
1631
+ * - `[]` → `[]`
1632
+ *
1633
+ * The cron daemon resolves `harness` from PATH (the pre-existing assumption that
1634
+ * `main-sync` already relied on).
1635
+ */
1636
+ declare function normalizeHarnessCommand(command: string[]): string[];
1548
1637
  /**
1549
1638
  * The central orchestrator that manages the lifecycle of coding agents.
1550
1639
  *
@@ -1656,6 +1745,11 @@ declare class Orchestrator extends EventEmitter {
1656
1745
  private abortControllers;
1657
1746
  /** Guards against overlapping ticks when a tick takes longer than the polling interval */
1658
1747
  private tickInProgress;
1748
+ /** Phase 4 (DLane-5): lanes read back from the durable log on first tick, for
1749
+ * observability only — NOT fed into reconciliation. Empty until the first tick. */
1750
+ private persistedLanes;
1751
+ /** Ensures the lane read-back diagnostic runs at most once (first tick). */
1752
+ private laneReadbackDone;
1659
1753
  /** Timestamp of the last stale branch sweep (at most once per hour) */
1660
1754
  private lastBranchSweepMs;
1661
1755
  /** Current tick-phase activity visible to the dashboard */
@@ -1672,6 +1766,24 @@ declare class Orchestrator extends EventEmitter {
1672
1766
  backend?: AgentBackend;
1673
1767
  execFileFn?: ExecFileFn$1;
1674
1768
  });
1769
+ /**
1770
+ * Phase 5: construct the OTLP/HTTP trace exporter and wire telemetry fanout.
1771
+ * Only fires when the operator configures `telemetry.export.otlp` in
1772
+ * harness.config.json. Extracted from the server-init block in the
1773
+ * constructor to keep that block's cyclomatic complexity under threshold.
1774
+ */
1775
+ private setupTelemetryExport;
1776
+ /**
1777
+ * Deprecated alias for /api/v1/local-model/status (Spec 1 endpoint retained
1778
+ * as a compat shim per spec line 35; superseded by getLocalModelStatuses for
1779
+ * the multi-local UI). Returns the first-registered resolver's status.
1780
+ */
1781
+ private getFirstLocalModelStatus;
1782
+ /**
1783
+ * SC38: build NamedLocalModelStatus[] from each registered resolver, tagged
1784
+ * with its backendName + endpoint from the config.
1785
+ */
1786
+ private buildLocalModelStatuses;
1675
1787
  private createTracker;
1676
1788
  /**
1677
1789
  * Creates a TaskRunner for the maintenance scheduler.
@@ -1698,6 +1810,25 @@ declare class Orchestrator extends EventEmitter {
1698
1810
  * @param effect - The effect to handle
1699
1811
  */
1700
1812
  private handleEffect;
1813
+ /**
1814
+ * Phase 4 (DLane-5): persist an orchestrator lane transition to the durable
1815
+ * core event log at the effect boundary. NEVER throws — `persistLane` returns
1816
+ * an `Err` Result on failure, which is logged and swallowed here so a
1817
+ * lane-persistence failure can never break orchestrator dispatch.
1818
+ */
1819
+ private persistLaneSafe;
1820
+ /**
1821
+ * Phase 4 (DLane-5): read persisted task lanes back from the durable log and
1822
+ * log a one-line summary. Stores the projection on `this.persistedLanes` for
1823
+ * observability. Read-only — never feeds reconciliation, never throws.
1824
+ */
1825
+ private readBackPersistedLanes;
1826
+ /**
1827
+ * Phase 4 (DLane-5): the task lanes most recently read back from the durable
1828
+ * log on startup, exposed for external observability. Read-only — a fresh
1829
+ * `{ tasks: {} }` until the first tick's read-back has run.
1830
+ */
1831
+ getPersistedLanes(): PersistedLanes;
1701
1832
  /**
1702
1833
  * Guards workspace cleanup by checking whether the agent pushed a branch
1703
1834
  * that does not yet have a pull request. If so, the worktree is preserved
@@ -1980,6 +2111,30 @@ interface CreateBackendOptions {
1980
2111
  */
1981
2112
  declare function createBackend(def: BackendDef, options?: CreateBackendOptions): AgentBackend;
1982
2113
 
2114
+ /**
2115
+ * Maintenance backend resolver: map a configured backend NAME to a live
2116
+ * {@link AgentBackend}, or `null` when the name is absent from the loaded
2117
+ * `agent.backends` map. `null` lets the real agent dispatcher no-op honestly
2118
+ * (graceful degradation on a plain checkout) instead of throwing.
2119
+ */
2120
+ type BackendResolver = (backendName: string) => AgentBackend | null;
2121
+ /**
2122
+ * Build a {@link BackendResolver} from a synthesized `agent.backends` map.
2123
+ *
2124
+ * This is the ONE shared implementation of "resolve a backend name against a
2125
+ * backends map via `createBackend`, else null". It is consumed by BOTH:
2126
+ * - the cron orchestrator (`createMaintenanceTaskRunner`), passing
2127
+ * `this.getBackends()`, and
2128
+ * - the on-demand CLI (`harness maintenance run --fix` →
2129
+ * `makeResolveBackend`), passing the config it loaded from
2130
+ * `harness.orchestrator.md`.
2131
+ *
2132
+ * Keeping it in the orchestrator package (next to `createBackend`) avoids the
2133
+ * two call sites drifting. A `null`/`undefined`/empty map yields a resolver
2134
+ * that always returns `null` — the nothing-configured degradation case.
2135
+ */
2136
+ declare function makeBackendResolver(backends: Record<string, BackendDef> | null | undefined): BackendResolver;
2137
+
1983
2138
  /**
1984
2139
  * Zod schema for `BackendDef` (Spec 2 — multi-backend routing).
1985
2140
  *
@@ -2426,6 +2581,520 @@ interface CustomTaskValidatorDeps {
2426
2581
  */
2427
2582
  declare function validateCustomTasks(customTasks: Record<string, CustomTaskDefinition> | undefined, builtIns: readonly TaskDefinition[], deps?: CustomTaskValidatorDeps): Result<void, CustomTaskValidationError[]>;
2428
2583
 
2584
+ /** Selection filter for `selectTasks`. `now` is injected for determinism. */
2585
+ interface TaskSelectionFilter {
2586
+ mode: 'overdue' | 'all' | 'ids';
2587
+ /** Required when `mode === 'ids'`; ignored otherwise. */
2588
+ ids?: string[];
2589
+ /** Reference instant — never read from the wall clock internally. */
2590
+ now: Date;
2591
+ }
2592
+ /**
2593
+ * Select the maintenance tasks to run for an on-demand sweep (D3/D5).
2594
+ * Operates only on sweep-eligible tasks (`excludeFromHumanSweep !== true`)
2595
+ * in every mode. Deterministic under the injected `filter.now`.
2596
+ *
2597
+ * - `overdue`: eligible tasks with no satisfying run since their previous fire.
2598
+ * - `all`: every eligible task.
2599
+ * - `ids`: the eligible subset named in `filter.ids` (a named excluded id
2600
+ * is dropped, honoring "excluded tasks never run in either path").
2601
+ * `filter.ids` is treated as a SET membership test, not an ordered
2602
+ * request list: results preserve the input `tasks` array order, not
2603
+ * the order ids appear in `filter.ids`. Duplicate ids are collapsed
2604
+ * and a task is returned at most once. Callers that need request
2605
+ * order must reorder the result themselves.
2606
+ */
2607
+ declare function selectTasks(tasks: TaskDefinition[], history: RunResult[], filter: TaskSelectionFilter): TaskDefinition[];
2608
+
2609
+ /**
2610
+ * Hermes Phase 2 — Result of running an arbitrary check script.
2611
+ *
2612
+ * Structurally compatible with `CheckCommandResult` (`task-runner.ts`) so
2613
+ * `TaskRunner` can consume it through the same interface, plus a parsed
2614
+ * structured envelope and the captured stderr stream. `structured` is
2615
+ * `null` when no JSON status line was found on stdout. The shape is
2616
+ * declared locally (not imported from `task-runner.ts`) to keep the
2617
+ * module dependency one-way: `task-runner.ts` depends on
2618
+ * `check-script-runner.ts`, never the reverse.
2619
+ */
2620
+ interface CheckScriptResult {
2621
+ passed: boolean;
2622
+ findings: number;
2623
+ /** Raw stdout. Field name matches `CheckCommandResult.output` for compatibility. */
2624
+ output: string;
2625
+ stderr: string;
2626
+ structured: CheckScriptStatusEnvelope | null;
2627
+ }
2628
+ interface CheckScriptStatusEnvelope {
2629
+ status: 'ok' | 'findings' | 'skip' | 'error';
2630
+ findings?: number;
2631
+ wakeAgent?: boolean;
2632
+ message?: string;
2633
+ outputs?: Record<string, unknown>;
2634
+ }
2635
+ /**
2636
+ * Spawns an arbitrary executable for the mechanical/report/housekeeping
2637
+ * check step. Honors the structured JSON status envelope (last non-empty
2638
+ * stdout line) per Hermes Phase 2 D6. Falls back to the legacy heuristic
2639
+ * regex when no JSON envelope is present.
2640
+ *
2641
+ * The runner is intentionally simple and shells out via `execFile` (no
2642
+ * shell, no `sh -c`) — `args` are passed verbatim to avoid argument
2643
+ * injection from operator-supplied config.
2644
+ */
2645
+ declare class CheckScriptRunner {
2646
+ private cwd;
2647
+ constructor(cwd: string);
2648
+ run(spec: CheckScriptDefinition, cwd?: string): Promise<CheckScriptResult>;
2649
+ }
2650
+
2651
+ /**
2652
+ * Hermes Phase 2 — Reads an inline-skill body by name. Wraps the host's
2653
+ * skill registry; absent skills resolve to `null` so the resolver can
2654
+ * warn-and-skip instead of throwing.
2655
+ */
2656
+ interface InlineSkillReader {
2657
+ read(skillName: string): Promise<string | null>;
2658
+ }
2659
+ interface ContextResolverOptions {
2660
+ outputStore: TaskOutputStore;
2661
+ skillReader?: InlineSkillReader;
2662
+ logger?: MaintenanceLogger;
2663
+ /** Per-upstream truncation bound. Default: 2000 chars. */
2664
+ perUpstreamMaxChars?: number;
2665
+ }
2666
+ /**
2667
+ * Resolves Hermes Phase 2 prompt-context inputs for a maintenance task:
2668
+ *
2669
+ * - `resolveContextFrom(taskIds, opts)`: pulls each upstream's latest
2670
+ * output from the store, applies stale/missing markers, and emits a
2671
+ * `## Upstream context` markdown block.
2672
+ *
2673
+ * - `resolveInlineSkills(skillNames, budgetTokens)`: pulls each skill's
2674
+ * markdown body via the registry, applies a per-skill char-count
2675
+ * budget (4 chars ≈ 1 token), warns-then-truncates on overflow, and
2676
+ * emits a `## Reference skills` markdown block.
2677
+ *
2678
+ * Both methods return an empty string when their inputs are absent so
2679
+ * callers can `prompt = skills + upstream + base` without conditional
2680
+ * scaffolding.
2681
+ */
2682
+ declare class ContextResolver {
2683
+ private outputStore;
2684
+ private skillReader;
2685
+ private logger;
2686
+ private perUpstreamMaxChars;
2687
+ constructor(options: ContextResolverOptions);
2688
+ resolveContextFrom(upstreamTaskIds: string[] | undefined, options?: {
2689
+ maxAgeMinutes?: number;
2690
+ }): Promise<string>;
2691
+ resolveInlineSkills(skillNames: string[] | undefined, budgetTokens?: number): Promise<string>;
2692
+ private formatUpstream;
2693
+ }
2694
+
2695
+ /**
2696
+ * Interface for running CLI check commands in-process.
2697
+ * Each method returns a structured result with a findings count.
2698
+ */
2699
+ interface CheckCommandRunner {
2700
+ /**
2701
+ * Runs a check command and returns its structured output.
2702
+ * @param command - CLI command args (e.g., ['check-arch'])
2703
+ * @param cwd - Working directory
2704
+ * @returns Object with findings count and whether the check passed
2705
+ */
2706
+ run(command: string[], cwd: string): Promise<CheckCommandResult>;
2707
+ }
2708
+ interface CheckCommandResult {
2709
+ passed: boolean;
2710
+ findings: number;
2711
+ /** Raw output for logging/reporting */
2712
+ output: string;
2713
+ /**
2714
+ * True when the check command could NOT be executed to a usable result —
2715
+ * the process failed to spawn (ENOENT), the subcommand was unknown, or it
2716
+ * crashed with no parseable findings count. This is distinct from a check
2717
+ * that ran fine and legitimately reported findings (`passed: false`,
2718
+ * `findings > 0`). The TaskRunner maps `executionFailed` onto
2719
+ * `status: 'failure'` so an un-runnable check is never masked as a
2720
+ * successful 1-finding run (ADR 0050 — exit-1-on-check-crash). Omitted /
2721
+ * `undefined` is treated as `false` for backward compatibility with runners
2722
+ * that predate this field.
2723
+ */
2724
+ executionFailed?: boolean;
2725
+ }
2726
+ /**
2727
+ * Interface for dispatching an AI agent to fix issues.
2728
+ * Wraps AgentRunner.runSession() with maintenance-specific parameters.
2729
+ */
2730
+ interface AgentDispatcher {
2731
+ /**
2732
+ * Dispatch an AI agent to fix issues on a branch.
2733
+ * @param skill - Skill name to dispatch (e.g., 'harness-arch-fix')
2734
+ * @param branch - Branch to work on
2735
+ * @param backendName - Backend name to use (e.g., 'local', 'claude')
2736
+ * @param cwd - Working directory (worktree path)
2737
+ * @param options - Hermes Phase 2: optional `promptContext` prepended to
2738
+ * the agent's system prompt (inlined skills + upstream
2739
+ * outputs). The dispatcher MAY ignore this field on
2740
+ * backends that don't support context injection; the
2741
+ * TaskRunner persists it independently for observability.
2742
+ * @returns Whether the agent produced any commits
2743
+ */
2744
+ dispatch(skill: string, branch: string, backendName: string, cwd: string, options?: AgentDispatchOptions): Promise<AgentDispatchResult>;
2745
+ }
2746
+ interface AgentDispatchOptions {
2747
+ /** Hermes Phase 2 — prompt context (inlined skills + upstream outputs). */
2748
+ promptContext?: string;
2749
+ }
2750
+ interface AgentDispatchResult {
2751
+ producedCommits: boolean;
2752
+ fixed: number;
2753
+ }
2754
+ /**
2755
+ * Interface for running housekeeping commands directly.
2756
+ */
2757
+ interface CommandExecutor {
2758
+ /**
2759
+ * Executes a command directly (no AI). Returns captured stdout so
2760
+ * housekeeping tasks emitting a JSON status line (e.g. `sync-main --json`)
2761
+ * can be parsed by the runner.
2762
+ *
2763
+ * @param command - Command args (e.g., ['cleanup-sessions'])
2764
+ * @param cwd - Working directory
2765
+ */
2766
+ exec(command: string[], cwd: string): Promise<CommandExecResult>;
2767
+ }
2768
+ interface CommandExecResult {
2769
+ /** Captured stdout. May be empty for legacy housekeeping commands. */
2770
+ stdout: string;
2771
+ }
2772
+ /**
2773
+ * Interface for managing branches and PRs for maintenance tasks.
2774
+ * Matches PRManager's public API shape for DI.
2775
+ */
2776
+ interface PRLifecycleManager {
2777
+ ensureBranch(branchName: string, baseBranch: string): Promise<{
2778
+ created: boolean;
2779
+ recreated: boolean;
2780
+ }>;
2781
+ ensurePR(task: TaskDefinition, runSummary: string): Promise<{
2782
+ prUrl: string;
2783
+ prUpdated: boolean;
2784
+ }>;
2785
+ }
2786
+ interface TaskRunnerOptions {
2787
+ config: MaintenanceConfig;
2788
+ checkRunner: CheckCommandRunner;
2789
+ agentDispatcher: AgentDispatcher;
2790
+ commandExecutor: CommandExecutor;
2791
+ /** Project root directory for running commands */
2792
+ cwd: string;
2793
+ /** Optional PR lifecycle manager for branch/PR operations */
2794
+ prManager?: PRLifecycleManager;
2795
+ /** Base branch for PR operations (defaults to 'main') */
2796
+ baseBranch?: string;
2797
+ /**
2798
+ * Hermes Phase 2 — Optional check-script runner. When a task declares
2799
+ * `checkScript`, the runner consults this instead of `checkRunner`.
2800
+ * Required for any custom task that uses `checkScript`; tests that don't
2801
+ * exercise custom tasks may omit it.
2802
+ */
2803
+ checkScriptRunner?: CheckScriptRunner;
2804
+ /**
2805
+ * Hermes Phase 2 — Optional context resolver providing `contextFrom`
2806
+ * upstream injection and `inlineSkills` payload assembly.
2807
+ */
2808
+ contextResolver?: ContextResolver;
2809
+ /**
2810
+ * Hermes Phase 2 — Persists per-task outputs (stdout / structured /
2811
+ * resolved context) at the end of each run.
2812
+ */
2813
+ outputStore?: TaskOutputStore;
2814
+ }
2815
+ /**
2816
+ * TaskRunner executes a single maintenance task based on its type.
2817
+ *
2818
+ * Execution paths:
2819
+ * - mechanical-ai: run check -> if findings, dispatch AI agent
2820
+ * - pure-ai: always dispatch AI agent
2821
+ * - report-only: run check, record findings, no AI
2822
+ * - housekeeping: run command directly, no AI
2823
+ */
2824
+ declare class TaskRunner {
2825
+ private config;
2826
+ private checkRunner;
2827
+ private agentDispatcher;
2828
+ private commandExecutor;
2829
+ private cwd;
2830
+ private prManager;
2831
+ private baseBranch;
2832
+ private checkScriptRunner;
2833
+ private contextResolver;
2834
+ private outputStore;
2835
+ constructor(options: TaskRunnerOptions);
2836
+ /**
2837
+ * Run a maintenance task and return the result.
2838
+ * Dispatches to the appropriate execution path based on task type.
2839
+ * Never throws -- errors are captured in the RunResult.
2840
+ *
2841
+ * @param task - Resolved task definition.
2842
+ * @param origin - Hermes Phase 2 trigger-source tag; defaults to `'cron'`
2843
+ * when called from the scheduler path.
2844
+ */
2845
+ run(task: TaskDefinition, origin?: RunOrigin, mode?: RunMode): Promise<RunResult>;
2846
+ private persistOutput;
2847
+ /**
2848
+ * Run the check step using whichever runner the task asks for. Custom
2849
+ * tasks that declare `checkScript` go through the Hermes Phase 2
2850
+ * `CheckScriptRunner`; built-ins (and customs that use the legacy
2851
+ * `checkCommand` shape) go through the original heuristic runner.
2852
+ */
2853
+ private runCheckStep;
2854
+ /**
2855
+ * Hermes Phase 2 — Compose the agent prompt-context block from inlined
2856
+ * skills + upstream task outputs. Returns an empty string when nothing
2857
+ * is configured (or when the resolver is absent), which is the safe
2858
+ * no-op default.
2859
+ */
2860
+ private composePromptContext;
2861
+ /**
2862
+ * Mechanical-AI: run check (legacy or Phase 2 script), dispatch AI agent
2863
+ * only if fixable findings exist; persist captured stdout/stderr/context
2864
+ * via the output store on the way out.
2865
+ */
2866
+ private runMechanicalAI;
2867
+ /**
2868
+ * Pure-AI: always dispatch agent with configured skill.
2869
+ */
2870
+ private runPureAI;
2871
+ /**
2872
+ * Report-only: run check (legacy or Phase 2 script), record metrics, no AI dispatch.
2873
+ *
2874
+ * Honors the JSON status contract emitted by Phase 4/5 CLIs (`harness pulse run`
2875
+ * and `harness compound scan-candidates` in `--non-interactive` mode):
2876
+ * {"status":"success"|"skipped"|"failure"|"no-issues",
2877
+ * "candidatesFound"?: number, "error"?: string, "reason"?: string}
2878
+ *
2879
+ * Legacy report-only tasks emit free-form output and fall through to 'success'.
2880
+ */
2881
+ private runReportOnly;
2882
+ /**
2883
+ * Housekeeping: run command directly, no AI, no PR.
2884
+ *
2885
+ * Captures stdout and parses a trailing JSON status line if present.
2886
+ * Recognized contracts:
2887
+ * - Phase 4/5 status contract (e.g., harness pulse run): success/skipped/failure/no-issues
2888
+ * - sync-main contract: updated/no-op/skipped/error → mapped onto the run-result status
2889
+ * Legacy housekeeping commands that emit no JSON keep the prior behavior:
2890
+ * status: 'success', findings: 0.
2891
+ *
2892
+ * Hermes Phase 2: a `checkScript` may replace `checkCommand` for housekeeping
2893
+ * tasks; the runner falls through to the same JSON-status parsing path.
2894
+ */
2895
+ private runHousekeeping;
2896
+ /**
2897
+ * Resolve which AI backend name to use for a given task.
2898
+ * Priority: per-task override > global config > 'local' default.
2899
+ */
2900
+ private resolveBackend;
2901
+ private failureResult;
2902
+ /**
2903
+ * A precondition-gated check (e.g. `predict` with <3 snapshots, or a
2904
+ * graph-backed check before `harness scan`). The command is correctly
2905
+ * configured; the repo just lacks the state it needs. Reported as `skipped`
2906
+ * — distinct from a hard `failure` — carrying the refusal line as the reason
2907
+ * (surfaced in the run-report summary column). ADR 0050.
2908
+ */
2909
+ private skippedResult;
2910
+ }
2911
+ /**
2912
+ * Classification of a check that a `CheckCommandRunner` flagged
2913
+ * `executionFailed` (non-zero exit / spawn error with no parseable finding
2914
+ * count). The runners cannot tell these three cases apart with a single
2915
+ * boolean, so the TaskRunner re-classifies the captured output here — keeping
2916
+ * the logic in ONE shared place consumed by BOTH the cron orchestrator and the
2917
+ * on-demand CLI (they each own a thin `CheckCommandRunner` but share this
2918
+ * `TaskRunner`). See ADR 0050 (report-first / execution-honesty).
2919
+ *
2920
+ * - `unrunnable` → the subcommand could not execute at all (unknown command,
2921
+ * ENOENT, missing module, empty output). Maps to `failure`.
2922
+ * - `precondition`→ the subcommand ran but refused because required state is
2923
+ * absent in this repo (e.g. `predict` needs ≥3 snapshots;
2924
+ * graph-backed checks need `harness scan` first). This is NOT
2925
+ * a misconfiguration or a breakage — maps to `skipped` with a
2926
+ * reason so dashboards/cron don't cry wolf.
2927
+ * - `ran-no-count`→ the subcommand ran and exited non-zero to SIGNAL drift but
2928
+ * emitted no machine-parseable count (e.g. `cleanup`,
2929
+ * `check-docs`). A check that ran and flagged work is not an
2930
+ * execution failure — maps to a real (recovered or assumed)
2931
+ * finding count, never `failure`.
2932
+ */
2933
+ type CheckFailureKind = 'unrunnable' | 'precondition' | 'ran-no-count';
2934
+ interface CheckFailureClassification {
2935
+ kind: CheckFailureKind;
2936
+ /** Human-readable reason, populated for `precondition` (the refusal line). */
2937
+ reason?: string;
2938
+ }
2939
+ /**
2940
+ * Parse an EXPLICIT finding count from output the primary `N keyword` parser in
2941
+ * the `CheckCommandRunner` missed — it only matches "45 issues", not the
2942
+ * "Entropy issues: 32264" (count-after-keyword) shape. Returns `null` when no
2943
+ * explicit count is present (vs `recoverFindingsCount`, which defaults to 1).
2944
+ *
2945
+ * A recoverable explicit count is the strongest possible signal that a check
2946
+ * actually RAN and produced findings, so the classifier trusts it over any
2947
+ * scary-looking words ("ENOENT", "not found") buried in the findings body.
2948
+ */
2949
+ declare function explicitFindingsCount(output: string): number | null;
2950
+ /**
2951
+ * Recover a finding count from a `ran-no-count` output, falling back to 1 — the
2952
+ * check ran and flagged something, exact count unknown.
2953
+ */
2954
+ declare function recoverFindingsCount(output: string): number;
2955
+ declare function classifyCheckExecutionFailure(output: string): CheckFailureClassification;
2956
+
2957
+ /**
2958
+ * Dependencies for {@link createAgentDispatcher}. All side-effecting collaborators
2959
+ * are injected so the dispatcher is unit-testable with a MockBackend and a fake
2960
+ * git seam (no real agent process, no real repository).
2961
+ */
2962
+ interface AgentDispatcherDeps {
2963
+ /**
2964
+ * Resolve a configured backend by name (e.g. `'local'`, `'claude'`). Returns
2965
+ * `null` when the name is unknown/unconfigured — the dispatcher then no-ops
2966
+ * rather than throwing, so a misconfigured maintenance task degrades to
2967
+ * "produced nothing" instead of crashing the scheduler.
2968
+ */
2969
+ resolveBackend: (backendName: string) => AgentBackend | null;
2970
+ /** Run `git <args>` in `cwd`, returning trimmed stdout (throws on failure). */
2971
+ git: (args: string[], cwd: string) => string;
2972
+ /** Max agent turns per dispatch. Defaults to 10. */
2973
+ maxTurns?: number;
2974
+ logger: {
2975
+ info: (message: string, meta?: Record<string, unknown>) => void;
2976
+ warn: (message: string, meta?: Record<string, unknown>) => void;
2977
+ };
2978
+ }
2979
+ /**
2980
+ * Wire the maintenance {@link AgentDispatcher} to a real agent session.
2981
+ *
2982
+ * Replaces the previous stub (which only logged and returned `producedCommits:
2983
+ * false`). Resolves the named backend, drives a multi-turn {@link AgentRunner}
2984
+ * session over the skill prompt in the worktree, then measures whether the agent
2985
+ * actually committed anything by diffing `HEAD` before/after. Commit count — not
2986
+ * the agent's self-report — is the source of truth for `fixed`.
2987
+ */
2988
+ declare function createAgentDispatcher(deps: AgentDispatcherDeps): AgentDispatcher;
2989
+
2990
+ /**
2991
+ * Options for the MaintenanceReporter.
2992
+ */
2993
+ interface MaintenanceReporterOptions {
2994
+ /** Directory where history.json is persisted (default: '.harness/maintenance/') */
2995
+ persistDir?: string;
2996
+ /** Logger for structured error/info output. Falls back to console if not provided. */
2997
+ logger?: MaintenanceLogger;
2998
+ }
2999
+ declare class MaintenanceReporter {
3000
+ private persistDir;
3001
+ private logger;
3002
+ private history;
3003
+ constructor(options?: MaintenanceReporterOptions);
3004
+ /**
3005
+ * Load history from disk. Creates the persist directory if it does not exist.
3006
+ * Errors in persistence are logged to stderr, not thrown.
3007
+ */
3008
+ load(): Promise<void>;
3009
+ /**
3010
+ * Record a run result. Appends to in-memory history (most recent first),
3011
+ * caps at MAX_HISTORY, and writes to disk asynchronously.
3012
+ */
3013
+ record(result: RunResult): Promise<void>;
3014
+ /**
3015
+ * Returns a paginated slice of the run history (most recent first).
3016
+ */
3017
+ getHistory(limit: number, offset: number): RunResult[];
3018
+ /**
3019
+ * Write history to disk. Errors are logged, not thrown.
3020
+ */
3021
+ private persist;
3022
+ }
3023
+
3024
+ /**
3025
+ * Generous stdout/stderr capture ceiling for spawned maintenance checks. The
3026
+ * Node `execFile` default (1 MB) is far too small for verbose checks — e.g.
3027
+ * `harness cleanup` on a large repo emits ~8 MB — and an exceeded buffer
3028
+ * rejects with EMPTY stdout/stderr, which the runner would misread as a check
3029
+ * that produced no output (a false execution failure). 64 MB leaves ample
3030
+ * headroom while still bounding memory.
3031
+ */
3032
+ declare const MAINTENANCE_CHECK_MAX_BUFFER: number;
3033
+ /**
3034
+ * Per-check wall-clock budget. Raised from the original 120 s because heavy
3035
+ * whole-repo checks legitimately need longer on large monorepos — `harness
3036
+ * cleanup` (all entropy types) takes ~165 s here — and a too-tight timeout
3037
+ * SIGTERMs the child, yielding empty output that the runner can only read as a
3038
+ * (false) execution failure. 300 s keeps a bound while letting real checks
3039
+ * finish.
3040
+ */
3041
+ declare const MAINTENANCE_CHECK_TIMEOUT_MS = 300000;
3042
+ /** A resolved child-process invocation: the file to spawn and its argv. The two
3043
+ * callers build this differently (CLI: `process.execPath` + the CLI's own entry
3044
+ * script; cron: the `harness` binary on PATH) but the spawn/parse core is one. */
3045
+ interface HarnessSpawn {
3046
+ file: string;
3047
+ args: string[];
3048
+ }
3049
+ /** The shape of an `execFile` rejection the timeout/classification logic reads. */
3050
+ interface ExecFileError {
3051
+ stdout?: string | Buffer;
3052
+ stderr?: string | Buffer;
3053
+ killed?: boolean;
3054
+ signal?: string | null;
3055
+ code?: string | number | null;
3056
+ }
3057
+ /** Injectable `execFile` (promisified) so tests can drive the spawn-error,
3058
+ * clean-run, findings, and timeout branches without real subprocesses. */
3059
+ type ExecFileAsyncFn = (file: string, args: string[], options: {
3060
+ cwd: string;
3061
+ timeout: number;
3062
+ maxBuffer: number;
3063
+ }) => Promise<{
3064
+ stdout: string | Buffer;
3065
+ stderr?: string | Buffer;
3066
+ }>;
3067
+ interface RunHarnessCheckOptions {
3068
+ /** Injected for tests; defaults to the real promisified `execFile`. */
3069
+ execFileAsync?: ExecFileAsyncFn;
3070
+ /** Per-check wall-clock budget (default {@link MAINTENANCE_CHECK_TIMEOUT_MS}). */
3071
+ timeoutMs?: number;
3072
+ /** stdout/stderr capture ceiling (default {@link MAINTENANCE_CHECK_MAX_BUFFER}). */
3073
+ maxBuffer?: number;
3074
+ }
3075
+ /** Best-effort detection of a child killed by the `execFile` timeout (SIGTERM /
3076
+ * ETIMEDOUT / killed flag). */
3077
+ declare function isCheckTimeoutError(e: ExecFileError): boolean;
3078
+ /**
3079
+ * Spawn a resolved harness check invocation and classify its result into a
3080
+ * {@link CheckCommandResult}. Behavior (shared by cron + CLI):
3081
+ *
3082
+ * - clean exit, parseable count → `{ findings: N }` (or 0 on a parse-miss; a
3083
+ * check that ran and said nothing is clean, not "1 finding").
3084
+ * - non-zero exit WITH a parseable count → real findings (`executionFailed:
3085
+ * false`) — e.g. `check-arch` exits 1 with "45 issues".
3086
+ * - non-zero exit / spawn error with NO parseable count → `executionFailed:
3087
+ * true`, findings 0 (a broken check is not "1 finding"; ADR 0050).
3088
+ * - TIMEOUT (SIGTERM/ETIMEDOUT) → `executionFailed: true`, findings 0, with a
3089
+ * distinct "check timed out after Nms" marker APPENDED to whatever the child
3090
+ * flushed. A timed-out check did not complete: even partial parseable output
3091
+ * ("5 issues") it flushed before SIGTERM is truncated and untrustworthy, so
3092
+ * the timeout is classified ahead of any finding count — never a "ran-no-
3093
+ * count" success. {@link import('./task-runner').classifyCheckExecutionFailure}
3094
+ * matches this marker before `explicitFindingsCount`.
3095
+ */
3096
+ declare function runHarnessCheck(spawn: HarnessSpawn, cwd: string, opts?: RunHarnessCheckOptions): Promise<CheckCommandResult>;
3097
+
2429
3098
  interface CreateTokenInput {
2430
3099
  name: string;
2431
3100
  scopes: TokenScope[];
@@ -2875,4 +3544,4 @@ declare function emitProposalCreated(bus: EventEmitter, proposal: SkillProposal)
2875
3544
  declare function emitProposalApproved(bus: EventEmitter, proposal: SkillProposal): void;
2876
3545
  declare function emitProposalRejected(bus: EventEmitter, proposal: SkillProposal): void;
2877
3546
 
2878
- export { type AgentUpdateEvent, AnalysisArchive, type AnalysisRecord, type ApplyEventResult, type ArtifactPresence, type AttemptStats, BUILT_IN_TASKS, BackendDefSchema, BackendRouter, type BackendRouterOptions, type BaseRefFallbackEvent, type BuildArchiveHooksOptions, ClaimManager, type ClaimManagerConfig, type CleanWorkspaceEffect, type CreateTokenInput, type CreateTokenResult, type CustomTaskValidationError, type DispatchEffect, type EmitLogEffect, type EscalateEffect, type ExecFileFn$1 as ExecFileFn, type FromConfigOptions, GateNotReadyError, type GateResult, GateRunError, type Highlight, type HighlightsInfo, type IndexedDoc, InteractionQueue, type LinearGraphQLExtension, LinearGraphQLStub, type LiveSession, LocalModelResolver, type LocalModelResolverOptions, MAX_ATTEMPTS, type MigrationResult, MockBackend, type NotificationSink, type NotificationSinkDeliverInput, ORCHESTRATOR_IDENTITY_FILE, Orchestrator, OrchestratorBackendFactory, type OrchestratorBackendFactoryOptions, type OrchestratorContext, type OrchestratorEvent, type OrchestratorState, PRDetector, type PRDetectorLogger, type PendingInteraction, type PersistedOutputEntry, PromotionError, type PromotionResult, PromptRenderer, type ProposalApprovedData, type ProposalCreatedData, type ProposalRejectedData, type PublishedIndex, type QueueInsertInput, type QueueRow, type QueueStats, RETRY_DELAYS_MS, type RateLimitSnapshot as RateLimitComputeSnapshot, type RateLimitConfig, type RateLimitSnapshot$1 as RateLimitSnapshot, type RegistryEntry, type ReleaseClaimEffect, type ResolverLogger, type RetryEntry, type RetryFiredEvent, RoadmapTrackerAdapter, RoutingConfigSchema, RoutingValueSchema, type RunAttemptPhase, type RunOrigin, type RunningEntry, type ScheduleRetryEffect, type SearchOptions, type SideEffect, SinkConfigError, SinkRegistry, type SkillCatalogEntry, SlackSink, type SlackSinkOptions, SqliteSearchIndex, type StallDetectedEvent, type StopEffect, type StreamManifest, StreamRecorder, type SummarizeContext, type SummarizeResult, type SyncMainOptions, type SyncMainResult, type SyncSkipReason, type TaskDefinition, TaskOutputStore, type TaskType, type TickEvent, TokenStore, type TokenTotals, type TriageConfig, type TriageDecision, type TriageSignals, type TriageSkill, type UpdateTokensEffect, type ValidateWorkflowConfigOptions, type ValidatedWorkflowConfig, WebhookQueue, type WorkerExitEvent, WorkflowLoader, WorkspaceHooks, WorkspaceManager, type WorkspaceManagerOptions, applyEvent, artifactPresenceFromIssue, buildArchiveHooks, calculateRetryDelay, canDispatch, computeRateLimitDelay, createBackend, createEmptyState, crossFieldRoutingIssues, defaultFetchModels, deriveSeedPaths, detectScopeTier, discoverSkillCatalog, discoverSkillCatalogNames, emitProposalApproved, emitProposalCreated, emitProposalRejected, extractHighlights, extractTitlePrefix, getAvailableSlots, getDefaultConfig, getPerStateCount, indexSessionDirectory, isEligible, isSummaryEnabled, launchTUI, loadPublishedIndex, migrateAgentConfig, normalizeFts5Query, normalizeLocalModel, openSearchIndex, promote, reconcile, reindexFromArchive, renderAnalysisComment, renderLlmSummaryMarkdown, renderPRComment, resolveEscalationConfig, resolveOrchestratorId, routeIssue, routingWarnings, runGate, savePublishedIndex, searchIndexPath, selectCandidates, sortCandidates, summarizeArchivedSession, syncMain, triageIssue, truncateForBudget, validateCustomTasks, validateWorkflowConfig, wireNotificationSinks, wrapAsEnvelope };
3547
+ export { type AgentDispatchResult, type AgentDispatcher, type AgentDispatcherDeps, type AgentUpdateEvent, AnalysisArchive, type AnalysisRecord, type ApplyEventResult, type ArtifactPresence, type AttemptStats, BUILT_IN_TASKS, BackendDefSchema, type BackendResolver, BackendRouter, type BackendRouterOptions, type BaseRefFallbackEvent, type BuildArchiveHooksOptions, type CheckCommandResult, type CheckCommandRunner, type CheckFailureClassification, type CheckFailureKind, CheckScriptRunner, ClaimManager, type ClaimManagerConfig, type CleanWorkspaceEffect, type CommandExecResult, type CommandExecutor, type CreateTokenInput, type CreateTokenResult, type CustomTaskValidationError, type DispatchEffect, type EmitLogEffect, type EscalateEffect, type ExecFileAsyncFn, type ExecFileError, type ExecFileFn$1 as ExecFileFn, type FromConfigOptions, GateNotReadyError, type GateResult, GateRunError, type HarnessSpawn, type Highlight, type HighlightsInfo, type IndexedDoc, InteractionQueue, LinearGraphQLClient, type LinearGraphQLClientOptions, type LinearGraphQLExtension, LinearGraphQLStub, type LiveSession, LocalModelResolver, type LocalModelResolverOptions, MAINTENANCE_CHECK_MAX_BUFFER, MAINTENANCE_CHECK_TIMEOUT_MS, MAX_ATTEMPTS, MaintenanceReporter, type MaintenanceReporterOptions, type MigrationResult, MockBackend, type NotificationSink, type NotificationSinkDeliverInput, ORCHESTRATOR_IDENTITY_FILE, Orchestrator, OrchestratorBackendFactory, type OrchestratorBackendFactoryOptions, type OrchestratorContext, type OrchestratorEvent, type OrchestratorState, PRDetector, type PRDetectorLogger, type PRLifecycleManager, type PendingInteraction, type PersistedOutputEntry, PromotionError, type PromotionResult, PromptRenderer, type ProposalApprovedData, type ProposalCreatedData, type ProposalRejectedData, type PublishedIndex, type QueueInsertInput, type QueueRow, type QueueStats, RETRY_DELAYS_MS, type RateLimitSnapshot as RateLimitComputeSnapshot, type RateLimitConfig, type RateLimitSnapshot$1 as RateLimitSnapshot, type RegistryEntry, type ReleaseClaimEffect, type ResolverLogger, type RetryEntry, type RetryFiredEvent, RoadmapTrackerAdapter, RoutingConfigSchema, RoutingValueSchema, type RunAttemptPhase, type RunHarnessCheckOptions, type RunMode, type RunOrigin, type RunResult, type RunningEntry, type ScheduleRetryEffect, type SearchOptions, type SideEffect, SinkConfigError, SinkRegistry, type SkillCatalogEntry, SlackSink, type SlackSinkOptions, SqliteSearchIndex, type StallDetectedEvent, type StopEffect, type StreamManifest, StreamRecorder, type SummarizeContext, type SummarizeResult, type SyncMainOptions, type SyncMainResult, type SyncSkipReason, type TaskDefinition, TaskOutputStore, TaskRunner, type TaskRunnerOptions, type TaskSelectionFilter, type TaskType, type TickEvent, TokenStore, type TokenTotals, type TriageConfig, type TriageDecision, type TriageSignals, type TriageSkill, type UpdateTokensEffect, type ValidateWorkflowConfigOptions, type ValidatedWorkflowConfig, WebhookQueue, type WorkerExitEvent, WorkflowLoader, WorkspaceHooks, WorkspaceManager, type WorkspaceManagerOptions, applyEvent, artifactPresenceFromIssue, buildArchiveHooks, calculateRetryDelay, canDispatch, classifyCheckExecutionFailure, computeRateLimitDelay, createAgentDispatcher, createBackend, createEmptyState, crossFieldRoutingIssues, defaultFetchModels, deriveSeedPaths, detectScopeTier, discoverSkillCatalog, discoverSkillCatalogNames, emitProposalApproved, emitProposalCreated, emitProposalRejected, explicitFindingsCount, extractHighlights, extractTitlePrefix, getAvailableSlots, getDefaultConfig, getPerStateCount, indexSessionDirectory, isCheckTimeoutError, isEligible, isSummaryEnabled, launchTUI, loadPublishedIndex, makeBackendResolver, migrateAgentConfig, normalizeFts5Query, normalizeHarnessCommand, normalizeLocalModel, openSearchIndex, promote, reconcile, recoverFindingsCount, reindexFromArchive, renderAnalysisComment, renderLlmSummaryMarkdown, renderPRComment, resolveEscalationConfig, resolveOrchestratorId, routeIssue, routingWarnings, runGate, runHarnessCheck, savePublishedIndex, searchIndexPath, selectCandidates, selectTasks, sortCandidates, summarizeArchivedSession, syncMain, triageIssue, truncateForBudget, validateCustomTasks, validateWorkflowConfig, wireNotificationSinks, wrapAsEnvelope };