/** * The run→ad-hoc-group index (wicked-studio#27; api-types 0.19.0). * * Ad-hoc sibling runs launched via `POST /runs` can be filed onto a grouping surface at launch: * `campaignId` attaches the run to an EXISTING engine campaign (validated loudly — an unknown id * fails the launch), `groupLabel` puts it in a label group created on first use. Either way the * attach is daemon-side PROVENANCE only: the engine's run record carries no such field (the run * executes byte-identically to an ungrouped launch, and the campaign scheduler never learns of * it), so — exactly like retry lineage (CREW-UX-3) and the actor trail (task #88) — the durable * record is the `run.launched` audit entry (`detail.campaignId` / `detail.groupLabel`), and this * map is the read-side latency layer that lets `GET /runs` echo `campaign_id`/`group_label` and * `GET /campaigns` serve `attached_runs` + the `groups` rows without a trail scan per request. * * Mirrors `RetryIndex`'s posture: hydrated once at server start (best-effort — a missing or * unreadable trail leaves prior runs ungrouped, the pre-0.19 behavior, not an error) and updated * at the same post-commit point that writes the audit entry, so the map can only lag by a failed * hydrate, never diverge silently. * * SCAN BUDGET: this index consumes the SAME `run.launched` entries `RetryIndex` already scans, * so it exposes {@link GroupIndex.hydrateFromLaunchEntries} and `createServer` feeds both * indexes from ONE `readAll({ action: 'run.launched' })` — boot stays at three full-file trail * scans, not four (the delivery-index consolidation note, crew#321). */ import type { AuditLog } from './audit.js'; import type { AuditEntry } from '../core/types.js'; /** One launch's group attach: exactly one of the two forms (the launch route enforces it). */ export type GroupAttach = { campaignId: string; } | { label: string; }; export declare class GroupIndex { private readonly runToAttach; /** campaignId → attached run ids, launch order. */ private readonly campaignRuns; /** label → member run ids, launch order. */ private readonly labelRuns; /** * Consume pre-read `run.launched` entries (NEWEST FIRST, `AuditLog.readAll`'s order — * exhaustive, per BRIEF-UX-002 C5). The first entry seen per run wins, like the sibling * indexes; member lists come out in LAUNCH order because insertion happens on a reversed * walk. Idempotent per boot (called once). */ hydrateFromLaunchEntries(entries: AuditEntry[]): void; /** Standalone hydrate (tests / direct use) — production shares the scan via `createServer`. */ hydrate(audit: AuditLog, log?: (msg: string) => void): Promise; /** Record one launch's attach (post-commit, beside the audit write). */ set(runId: string, attach: GroupAttach): void; /** This run's attach, or `undefined` (the DTO spells that as ABSENT fields). */ attachOf(runId: string): GroupAttach | undefined; /** Run ids attached to this campaign, launch order (`[]` when none). */ attachedTo(campaignId: string): string[]; /** Every label group: `{ label, runIds }` in first-use order, members in launch order. */ labelGroups(): Array<{ label: string; runIds: string[]; }>; } //# sourceMappingURL=group-index.d.ts.map