@vostride/agent-qa-dashboard 0.2.2 → 0.2.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.
- package/README.md +78 -0
- package/dist/{index-Ds4Lv4mT.d.cts → index-Cxygerok.d.cts} +16 -627
- package/dist/{index-Ds4Lv4mT.d.ts → index-Cxygerok.d.ts} +16 -627
- package/dist/index.cjs +337 -740
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -201
- package/dist/index.d.ts +7 -201
- package/dist/index.js +347 -743
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +311 -573
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +321 -577
- package/dist/server/index.js.map +1 -1
- package/package.json +13 -13
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse, Server } from 'node:http';
|
|
2
2
|
import { RunAttributes, ResolvedWorkspacePaths, ResolvedAppiumExecutable, HookDefinition, AuthStateMetadata } from '@vostride/agent-qa-core';
|
|
3
|
-
import { RunDetailMember, RunDetailStep, RunDetailSubAction, RunDetailRows, RunStatus, RunArtifactKind, RunArtifactStageInput, RunArtifactPayload, RunArtifactFinalizeInput, LiveStreamDeclaration, LiveFrame, LiveFrameEndReason, LiveFrameSubscription, FunctionCaller, RunEventEnvelope, RunStartAcknowledgement, RunSession, RunServiceReadiness, RunsLiveUrlResult,
|
|
3
|
+
import { RunDetailMember, RunDetailStep, RunDetailSubAction, RunDetailRows, RunStatus, RunArtifactKind, RunArtifactStageInput, RunArtifactPayload, RunArtifactFinalizeInput, LiveStreamDeclaration, LiveFrame, LiveFrameEndReason, LiveFrameSubscription, FunctionCaller, RunEventEnvelope, RunStartAcknowledgement, RunSession, RunServiceReadiness, RunsLiveUrlResult, MaskFn, LiveViewSubjectRef, LiveUrlVerdict, EditorLiveUrlResult, ConfigWriteIssue, ConfigChange, ConfigPathSegment, ConfigWriteRefusal, PlannerLimits } from '@vostride/agent-qa-schema';
|
|
4
4
|
import { EventEmitter } from 'node:events';
|
|
5
5
|
import { SecretStore, SecretRedactor, ConsoleLogEntry, NetworkLogEntry, StepAnnotation, StepPhaseEvent, StepResult } from '@vostride/agent-qa-runner';
|
|
6
6
|
import { Node } from 'yaml';
|
|
@@ -45,7 +45,6 @@ interface RunRow {
|
|
|
45
45
|
endedAt: string | null;
|
|
46
46
|
failureSummary: string | null;
|
|
47
47
|
errorLog: string | null;
|
|
48
|
-
memoryLog: string | null;
|
|
49
48
|
testId: string | null;
|
|
50
49
|
suiteId: string | null;
|
|
51
50
|
platform: string;
|
|
@@ -78,15 +77,6 @@ interface RunArtifactRow {
|
|
|
78
77
|
createdAt: string;
|
|
79
78
|
updatedAt: string;
|
|
80
79
|
}
|
|
81
|
-
/**
|
|
82
|
-
* ONE RUN'S ARTIFACT, AND NOTHING ELSE (405-07, D-02).
|
|
83
|
-
*
|
|
84
|
-
* `children` stood here and is gone. It walked the run row's now-deleted parent link for the child
|
|
85
|
-
* rows of a suite parent — a shape nothing has written since 402-09 put ONE `runs` row per run and moved member
|
|
86
|
-
* identity onto `run_members`. A structurally-always-empty array on a response is worse than an
|
|
87
|
-
* absent one: a reader cannot tell "this run has no children" from "children stopped being a fact
|
|
88
|
-
* this product records", so the page renders an empty section forever and nobody notices.
|
|
89
|
-
*/
|
|
90
80
|
interface RunArtifactBundle {
|
|
91
81
|
artifact: RunArtifactRow | null;
|
|
92
82
|
}
|
|
@@ -94,10 +84,6 @@ interface ExecutionLogRow {
|
|
|
94
84
|
id: string;
|
|
95
85
|
runId: string;
|
|
96
86
|
stepId: string | null;
|
|
97
|
-
/**
|
|
98
|
-
* 405 D-01: where in the run tree this hook ran, from `HookFinishedPayload`'s own optional
|
|
99
|
-
* fields. `null` means a RUN-SCOPED hook — a real state, not a missing value.
|
|
100
|
-
*/
|
|
101
87
|
testIndex: number | null;
|
|
102
88
|
stepIndex: number | null;
|
|
103
89
|
type: 'hook' | 'appium-script' | 'runjs';
|
|
@@ -116,7 +102,6 @@ interface InsertExecutionLogInput {
|
|
|
116
102
|
id: string;
|
|
117
103
|
runId: string;
|
|
118
104
|
stepId?: string | null;
|
|
119
|
-
/** 405 D-01: the handle and step this hook belongs to; absent means run-scoped. */
|
|
120
105
|
testIndex?: number | null;
|
|
121
106
|
stepIndex?: number | null;
|
|
122
107
|
type: 'hook' | 'appium-script' | 'runjs';
|
|
@@ -158,15 +143,6 @@ interface InsightsBreakdownRow {
|
|
|
158
143
|
filePath?: string;
|
|
159
144
|
suiteId?: string;
|
|
160
145
|
}
|
|
161
|
-
/**
|
|
162
|
-
* What a run deletion removed (405-07, D-14 · T-405-27).
|
|
163
|
-
*
|
|
164
|
-
* ROWS ONLY. The two path arrays that stood here fed the router's filesystem cleanup, and both the
|
|
165
|
-
* cleanup and the columns it read are gone: refs are the only artifact addressing now, and the run
|
|
166
|
-
* directory under `.agent-qa/runs/` is the run's own record — the event log and the blobs — which
|
|
167
|
-
* the dashboard never owned and must not delete. `deletedRunIds` survives as a one-element list
|
|
168
|
-
* rather than collapsing to a boolean, because it is the shape the response already publishes.
|
|
169
|
-
*/
|
|
170
146
|
interface DeleteRunResult {
|
|
171
147
|
deleted: boolean;
|
|
172
148
|
deletedRunIds: string[];
|
|
@@ -240,7 +216,6 @@ declare class DashboardDatabase {
|
|
|
240
216
|
endedAt?: string;
|
|
241
217
|
failureSummary?: string;
|
|
242
218
|
errorLog?: string;
|
|
243
|
-
memoryLog?: string;
|
|
244
219
|
attributes?: RunAttributes;
|
|
245
220
|
platform?: string;
|
|
246
221
|
testId?: string;
|
|
@@ -270,20 +245,6 @@ declare class DashboardDatabase {
|
|
|
270
245
|
getNextPendingRun(): RunRow | undefined;
|
|
271
246
|
getPendingRuns(): RunRow[];
|
|
272
247
|
updateRunStatus(id: string, status: string): boolean;
|
|
273
|
-
/**
|
|
274
|
-
* Write or refresh ONE member row, keyed by the handle `(run_id, test_index)`.
|
|
275
|
-
*
|
|
276
|
-
* AN UPSERT AND NOT TWO WRITES, because the member row is fed by two events at two times:
|
|
277
|
-
* `testStarted` knows the identity fields and `testFinished` knows the outcome — and D-18
|
|
278
|
-
* requires a member whose stream begins with a terminal event to render anyway, so the second
|
|
279
|
-
* one alone has to be able to create the row.
|
|
280
|
-
*
|
|
281
|
-
* ONLY SUPPLIED FIELDS MOVE. `COALESCE(excluded.x, run_members.x)` on every optional column, so
|
|
282
|
-
* a `testFinished` that carries no name cannot blank the name `testStarted` wrote. `attempts` is
|
|
283
|
-
* excluded from the update entirely: it is the D-17 retry ordinal, owned by
|
|
284
|
-
* `incrementRunMemberAttempts`, and an upsert that reset it would erase the fact the header
|
|
285
|
-
* renders.
|
|
286
|
-
*/
|
|
287
248
|
upsertRunMember(member: {
|
|
288
249
|
runId: string;
|
|
289
250
|
testIndex: number;
|
|
@@ -300,29 +261,8 @@ declare class DashboardDatabase {
|
|
|
300
261
|
retryCount?: number;
|
|
301
262
|
recording?: RunDetailMember['recording'];
|
|
302
263
|
}): void;
|
|
303
|
-
/**
|
|
304
|
-
* Raise ONE member's attempt ordinal (D-17). A no-op when the member row does not exist yet —
|
|
305
|
-
* a retry scheduled before any identity event is a real ordering, and inventing a row here
|
|
306
|
-
* would put a member on the page that nothing has said anything about.
|
|
307
|
-
*/
|
|
308
264
|
incrementRunMemberAttempts(runId: string, testIndex: number): void;
|
|
309
|
-
/**
|
|
310
|
-
* Drop ONE HANDLE's projected step and sub-action rows (D-17).
|
|
311
|
-
*
|
|
312
|
-
* SCOPED TO THE HANDLE, which was the whole change from the v1 run-wide step delete this
|
|
313
|
-
* replaced (deleted outright by 405-07's census): that member wiped every step of the RUN on any
|
|
314
|
-
* member's retry, so in a suite the abandoned attempt of test 3 deleted the completed history of
|
|
315
|
-
* tests 0-2. The member row itself survives — its outcome and its attempt count are facts about
|
|
316
|
-
* the member, not about the attempt. So do its setup and teardown hook rows, which run once per
|
|
317
|
-
* member outside the retry loop; only the attempt's `inline` hook rows go (433-41, CR-01).
|
|
318
|
-
*/
|
|
319
265
|
deleteMemberProjection(runId: string, testIndex: number): void;
|
|
320
|
-
/**
|
|
321
|
-
* Write ONE finalized step row. `INSERT OR REPLACE` because a re-run of the same handle re-emits
|
|
322
|
-
* the same `(test_index, step_index)` and the LAST attempt is the one the page renders (D-17).
|
|
323
|
-
*
|
|
324
|
-
* The three token columns stay NULL when `tokenUsage` is absent — never 0 (D-05).
|
|
325
|
-
*/
|
|
326
266
|
insertRunStep(step: {
|
|
327
267
|
runId: string;
|
|
328
268
|
testIndex: number;
|
|
@@ -359,14 +299,6 @@ declare class DashboardDatabase {
|
|
|
359
299
|
ariaEvidence?: RunDetailSubAction['ariaEvidence'];
|
|
360
300
|
recordingOffsetMs?: RunDetailSubAction['recordingOffsetMs'];
|
|
361
301
|
}): void;
|
|
362
|
-
/**
|
|
363
|
-
* THE run-detail read (D-03). `undefined` when no `runs` row exists — absence is a RESULT here,
|
|
364
|
-
* and turning it into a typed refusal is the `runs.detail` op's job, so the "not found"
|
|
365
|
-
* vocabulary lives in the function layer rather than in this store.
|
|
366
|
-
*
|
|
367
|
-
* A run that exists and projected nothing answers three empty arrays, which is a DIFFERENT fact
|
|
368
|
-
* and stays a different answer.
|
|
369
|
-
*/
|
|
370
302
|
readRunDetailRows(runId: string): RunDetailRows | undefined;
|
|
371
303
|
private appendAttributePredicateConditions;
|
|
372
304
|
private applyRegexAttributePredicates;
|
|
@@ -408,20 +340,6 @@ declare class DashboardDatabase {
|
|
|
408
340
|
limit?: number;
|
|
409
341
|
q?: string;
|
|
410
342
|
}): AttributeValueSuggestion[];
|
|
411
|
-
/**
|
|
412
|
-
* Delete ONE run and everything the schema hangs off it (405-07, D-02/D-14 · T-405-27).
|
|
413
|
-
*
|
|
414
|
-
* ONE ID, AND THE CASCADE DOES THE REST. This used to open with a recursive `run_tree` CTE that
|
|
415
|
-
* walked the child rows of a suite parent, then hand-delete their step and trace rows in a
|
|
416
|
-
* transaction. Nothing has written a child row since 402-09 — one `runs` row per run, member
|
|
417
|
-
* identity on `run_members` — so the walk could only ever return the one row it was seeded with,
|
|
418
|
-
* and the hand-deletes named tables this schema no longer has. Every table that references a run
|
|
419
|
-
* declares `ON DELETE CASCADE`, so the single statement below is the whole deletion.
|
|
420
|
-
*
|
|
421
|
-
* AND IT TOUCHES NO FILE. The two path arrays it used to collect fed the router's artifact
|
|
422
|
-
* cleanup; both are gone. The run's directory under `.agent-qa/runs/` — its event log and its
|
|
423
|
-
* content-addressed blobs — is the run's own record and is not the dashboard's to remove.
|
|
424
|
-
*/
|
|
425
343
|
deleteRun(id: string): DeleteRunResult;
|
|
426
344
|
insertRunArtifact(input: {
|
|
427
345
|
runId: string;
|
|
@@ -432,15 +350,6 @@ declare class DashboardDatabase {
|
|
|
432
350
|
finalizeRunArtifact(runId: string, updates?: RunArtifactFinalizeInput): RunArtifactRow;
|
|
433
351
|
getRunArtifact(runId: string): RunArtifactRow | null;
|
|
434
352
|
getRunArtifactBundle(runId: string): RunArtifactBundle;
|
|
435
|
-
/**
|
|
436
|
-
* The runs a self-heal happened on (405-07, D-02).
|
|
437
|
-
*
|
|
438
|
-
* READ OFF `run_steps.self_heal_occurred`, WHICH IS THE SURVIVING HEALING FACT. This scanned the
|
|
439
|
-
* v1 wide step table for `status = 'healed'`; that table had no producer left and its readers
|
|
440
|
-
* went with it. `selfHealOccurred` is the bus payload's own boolean, projected verbatim by the
|
|
441
|
-
* subscriber — so the flake rate below is now computed from what the runner actually reported
|
|
442
|
-
* rather than from a status word a retired projection wrote.
|
|
443
|
-
*/
|
|
444
353
|
private getHealedRunIds;
|
|
445
354
|
private summarizeAnalyticsRuns;
|
|
446
355
|
private listRunsForInsights;
|
|
@@ -459,14 +368,6 @@ declare class DashboardDatabase {
|
|
|
459
368
|
healed: number;
|
|
460
369
|
duration: number;
|
|
461
370
|
}[];
|
|
462
|
-
memory: {
|
|
463
|
-
runs: number;
|
|
464
|
-
added: number;
|
|
465
|
-
confirmed: number;
|
|
466
|
-
deprecated: number;
|
|
467
|
-
deleted: number;
|
|
468
|
-
curatorTokens: number;
|
|
469
|
-
};
|
|
470
371
|
};
|
|
471
372
|
getCostStats(opts?: StatsOptions): {
|
|
472
373
|
runs: {
|
|
@@ -509,12 +410,6 @@ declare class DashboardDatabase {
|
|
|
509
410
|
};
|
|
510
411
|
testRunUnmeasuredSteps: number;
|
|
511
412
|
};
|
|
512
|
-
/**
|
|
513
|
-
* The window's settled run ids, newest first, capped at `limit`, with their full count, and the
|
|
514
|
-
* count of the window's runs still in flight (433-30, 433-42). A settled run has started and is
|
|
515
|
-
* neither `pending` nor `running`; every other row in the window is in flight. Ids only: the
|
|
516
|
-
* Insights knowledge-change read dispatches each through the agent host.
|
|
517
|
-
*/
|
|
518
413
|
listInsightsWindowRunIds(opts: {
|
|
519
414
|
from?: string;
|
|
520
415
|
to?: string;
|
|
@@ -602,99 +497,19 @@ interface ExecuteOptions {
|
|
|
602
497
|
source: string;
|
|
603
498
|
attributes?: RunAttributes;
|
|
604
499
|
timeout?: number;
|
|
605
|
-
/**
|
|
606
|
-
* The Appium lease URL for a mobile run, AS DATA (401-07, D-01/D-12).
|
|
607
|
-
*
|
|
608
|
-
* The bundled Appium spawn is design-of-record and stays exactly where it is; what changed is the
|
|
609
|
-
* DELIVERY. It used to ride `AGENT_QA_APPIUM_URL` in a child's environment, and a child env is
|
|
610
|
-
* something only a child has. The run happens in this process now, so the lease travels as an
|
|
611
|
-
* argument and is handed to the run through an injected resolver.
|
|
612
|
-
*/
|
|
613
500
|
appiumUrl?: string;
|
|
614
501
|
}
|
|
615
|
-
/**
|
|
616
|
-
* A run has reached a terminal state (401-07, D-04/D-12).
|
|
617
|
-
*
|
|
618
|
-
* THE TYPED SUCCESSOR TO THE CHILD'S `close` EVENT. The host reconciles a db row still reading
|
|
619
|
-
* `running`, releases the run's Appium lease and frees the queue slot off this — exactly what it did
|
|
620
|
-
* off the process exit — but the status is now the bus's own ground truth and the `details` carry
|
|
621
|
-
* the failure's REASON rather than a scraped tail of stderr.
|
|
622
|
-
*
|
|
623
|
-
* `'run-settled'` is now the WHOLE of this emitter's contract. A second event carried the retired
|
|
624
|
-
* live feed's frames and went with it (405-07, D-19).
|
|
625
|
-
*/
|
|
626
502
|
interface RunSettledDetails {
|
|
627
|
-
/**
|
|
628
|
-
* A human-readable reason when the run did not simply finish. 2026-09-30, 432-09 (D-15): a
|
|
629
|
-
* refusal is this plain reason. No remedy list rides the settle; nothing asks the reader to act.
|
|
630
|
-
*/
|
|
631
503
|
readonly reason?: string;
|
|
632
|
-
/**
|
|
633
|
-
* The run NEVER BEGAN — the gate or the host refused it (401-18, G-401-16).
|
|
634
|
-
*
|
|
635
|
-
* A FACT, NOT AN INFERENCE. `settle` has always known this — a rejection with no started session
|
|
636
|
-
* is a denial, a refused request field or an input error — and threw the knowledge away, leaving
|
|
637
|
-
* the host's reconciliation to guess from a regex over the diagnostic lines. It guessed
|
|
638
|
-
* `Process exited before test completed`, which is a sentence about a process, for a run where
|
|
639
|
-
* nothing was ever started to exit.
|
|
640
|
-
*
|
|
641
|
-
* DELIBERATELY A BOOLEAN AND NOT A CLASS. Which refusal it was — `fail-closed-denied`, `blocked`,
|
|
642
|
-
* `session-pin-denied`, an unrecognised request field, a plain input error — is not something the
|
|
643
|
-
* reconciliation branches on, and a prose name for it here would be the same defect one layer
|
|
644
|
-
* down. If a class is ever needed it arrives as a closed-set value owned by `schema`.
|
|
645
|
-
*
|
|
646
|
-
* ABSENT ON A RUN THAT STARTED, including one that started and then failed. That asymmetry is the
|
|
647
|
-
* scope guarantee: every other arm of the reconciliation reads exactly what it read before.
|
|
648
|
-
*/
|
|
649
504
|
readonly refusedBeforeStart?: true;
|
|
650
|
-
/**
|
|
651
|
-
* The refusal said without naming any surface's affordance (401-18, G-401-16).
|
|
652
|
-
*
|
|
653
|
-
* The gate composed two sentences per decision: the canonical one, which named the session trust
|
|
654
|
-
* flag and landed in the execution-audit row, and the neutral one, which stops at the classification and the outcome.
|
|
655
|
-
* A browser reader was being handed the first, so the record's only account of why a run never
|
|
656
|
-
* happened told them to pass a flag to a command they were not running.
|
|
657
|
-
*
|
|
658
|
-
* READ STRUCTURALLY OFF THE REJECTION, and ABSENT where the
|
|
659
|
-
* rejection carries no neutral form — an input error is not a gate decision and has no second
|
|
660
|
-
* phrasing. The consumer then falls back to the rejection's own message, which for those refusals
|
|
661
|
-
* names no surface's affordance either.
|
|
662
|
-
*/
|
|
663
|
-
readonly neutralReason?: string;
|
|
664
505
|
/** Diagnostic lines — a rejection's own message. The typed successor to scraped stderr. */
|
|
665
506
|
readonly output: readonly string[];
|
|
666
507
|
}
|
|
667
508
|
type RunSettledStatus = 'completed' | 'failed' | 'cancelled' | 'timeout';
|
|
668
|
-
/** A trigger's request as the queue would carry it, before anything is recorded (433-34). */
|
|
669
|
-
interface PreflightOptions {
|
|
670
|
-
readonly args: string[];
|
|
671
|
-
readonly source: 'dashboard' | 'suite';
|
|
672
|
-
}
|
|
673
509
|
interface ExecutionBackend extends EventEmitter {
|
|
674
510
|
execute(opts: ExecuteOptions): void;
|
|
675
|
-
/**
|
|
676
|
-
* Ask the run core whether this request may start, before a row is minted or anything enqueued
|
|
677
|
-
* (433-34, G-433-10).
|
|
678
|
-
*
|
|
679
|
-
* The composing host answers with the core's own production rule over the members' declared
|
|
680
|
-
* targets; this package decides nothing about production. A refusal rejects with the core's
|
|
681
|
-
* denial, which carries `neutralReason`. Absent on a backend whose host composes no preflight.
|
|
682
|
-
*/
|
|
683
|
-
preflight?(opts: PreflightOptions): Promise<void>;
|
|
684
511
|
kill(runId: string): boolean;
|
|
685
512
|
killAll(): void;
|
|
686
|
-
/**
|
|
687
|
-
* The runs this backend currently has in flight, as `GET /api/execution/active` serves them.
|
|
688
|
-
*
|
|
689
|
-
* `testName` IS ON THE INTERFACE (405-07, D-19). It used to be produced by scanning a per-run
|
|
690
|
-
* event buffer for a `testStarted` frame — a read that only the concrete class could perform,
|
|
691
|
-
* through a member the interface did not declare. It is now recorded on the run handle by the
|
|
692
|
-
* backend's own bus subscription, so the field is part of the contract every implementation
|
|
693
|
-
* answers rather than a property of one implementation's internal storage.
|
|
694
|
-
*
|
|
695
|
-
* ABSENT MEANS NO MEMBER HAS STARTED YET, which is a real state on a run between its start and
|
|
696
|
-
* its first `testStarted`; it is never filled with the run id or a placeholder.
|
|
697
|
-
*/
|
|
698
513
|
getActiveExecutions(): {
|
|
699
514
|
runId: string;
|
|
700
515
|
status: string;
|
|
@@ -751,110 +566,18 @@ type AgentRegistryHandle = object;
|
|
|
751
566
|
interface AgentHost {
|
|
752
567
|
/** The composed registry every call goes through. Opaque here. */
|
|
753
568
|
readonly registry: AgentRegistryHandle;
|
|
754
|
-
/**
|
|
755
|
-
* The caller this door dispatches as, MINTED by the composition root and never by this package.
|
|
756
|
-
*
|
|
757
|
-
* Attribution and grants both. The composer derives it from the CLI chat door's own mint with
|
|
758
|
-
* only the surface name changed (D-08/Pitfall 9) — a hand-typed scope list here would be the
|
|
759
|
-
* drift vector the parity legs exist to catch, and this package could not type-check one anyway.
|
|
760
|
-
*/
|
|
761
569
|
readonly caller: FunctionCaller;
|
|
762
|
-
/**
|
|
763
|
-
* The agent package's `runs.postprocessing` id (404 D-16/D-18).
|
|
764
|
-
*
|
|
765
|
-
* SUPPLIED BY THE COMPOSITION, NEVER SPELLED HERE. The post-processing read route dispatches
|
|
766
|
-
* chip truth through this door, and the op id is the agent package's constant: a string literal
|
|
767
|
-
* in this package would be a second declaration of a capability's name, free to drift from the
|
|
768
|
-
* spec that answers to it. This package also may not import `@vostride/agent-qa-agent`
|
|
769
|
-
* (validate:arch), so there is nowhere here the real constant could come from.
|
|
770
|
-
*/
|
|
771
570
|
readonly runsPostProcessingFunctionId: string;
|
|
772
|
-
/**
|
|
773
|
-
* The agent package's `runs.events` id, on the line above's footing (404 D-22).
|
|
774
|
-
*
|
|
775
|
-
* A SECOND ID BECAUSE THE READ ROUTE JOINS TWO FACTS from two different records: the chain's
|
|
776
|
-
* chips live in the durable job store, and the run's POSTURE — who was going to drain it — lives
|
|
777
|
-
* on the `runFinished` line of the run's own event log, beside the last per-stage failure text.
|
|
778
|
-
* Reading the log any other way would mean this package opening a file the function layer owns.
|
|
779
|
-
*/
|
|
780
571
|
readonly runsEventsFunctionId: string;
|
|
781
|
-
/**
|
|
782
|
-
* The agent package's `runs.detail` id, on `runsPostProcessingFunctionId`'s exact footing (405
|
|
783
|
-
* D-03).
|
|
784
|
-
*
|
|
785
|
-
* SUPPLIED BY THE COMPOSITION, NEVER SPELLED HERE, for the reason its two neighbours are: the
|
|
786
|
-
* op id is the agent package's constant, a string literal in this package would be a second
|
|
787
|
-
* declaration of a capability's name free to drift from the spec that answers to it, and this
|
|
788
|
-
* package may not import `@vostride/agent-qa-agent` at all (validate:arch) — so there is nowhere
|
|
789
|
-
* here the real constant could come from.
|
|
790
|
-
*
|
|
791
|
-
* WHAT IT REPLACES is worth naming: run detail used to be assembled by reading SQLite from
|
|
792
|
-
* inside the router. Routing it through this id is what makes the same durable read available
|
|
793
|
-
* to the CLI, MCP and chat instead of to the browser alone.
|
|
794
|
-
*/
|
|
795
572
|
readonly runsDetailFunctionId: string;
|
|
796
573
|
/** The evidence op identity supplied by the same composition as the detail reader. */
|
|
797
574
|
readonly runsEvidenceFunctionId: string;
|
|
798
|
-
/**
|
|
799
|
-
* The agent package's `runs.artifact` id, on `runsDetailFunctionId`'s exact footing (405 D-13).
|
|
800
|
-
*
|
|
801
|
-
* SUPPLIED BY THE COMPOSITION, NEVER SPELLED HERE, for the reason its four neighbours are — and
|
|
802
|
-
* for one more that is specific to this route: the artifact arm serves BYTES, and the alternative
|
|
803
|
-
* to dispatching them through the function layer is this package constructing the evidence store
|
|
804
|
-
* and reading a file. That would be a private store read no roster row covers and no audit sink
|
|
805
|
-
* sees, on a path whose two inputs both arrive from a URL. Routing it through an id is what makes
|
|
806
|
-
* the containment rule the store's own and the capability one the CLI, MCP and 408's embed reach
|
|
807
|
-
* the same way.
|
|
808
|
-
*/
|
|
809
575
|
readonly runsArtifactFunctionId: string;
|
|
810
|
-
/**
|
|
811
|
-
* The agent package's `analysis.get` id, on `runsArtifactFunctionId`'s exact footing (406 D-04).
|
|
812
|
-
*
|
|
813
|
-
* SUPPLIED BY THE COMPOSITION, NEVER SPELLED HERE, for the reason its five neighbours are: the
|
|
814
|
-
* op id is the agent package's constant, a string literal in this package would be a second
|
|
815
|
-
* declaration of a capability's name free to drift from the spec that answers to it, and this
|
|
816
|
-
* package may not import `@vostride/agent-qa-agent` at all (validate:arch) — so there is nowhere
|
|
817
|
-
* here the real constant could come from.
|
|
818
|
-
*
|
|
819
|
-
* WHAT IT SERVES is the failure view: the resolved verdicts and rendered sentences a person
|
|
820
|
-
* reads inside each failed member's group, on BOTH doors through one adapter. `analysis.get` is
|
|
821
|
-
* the single producer of those sentences (389 D-11), so routing the page's read through this id
|
|
822
|
-
* is what keeps the browser, the CLI, chat and 408's embed reading one answer.
|
|
823
|
-
*/
|
|
824
576
|
readonly analysisGetFunctionId: string;
|
|
825
|
-
/**
|
|
826
|
-
* The agent package's `runs.knowledge` id, on `analysisGetFunctionId`'s exact footing
|
|
827
|
-
* (2026-08-29, 407-01 D-05).
|
|
828
|
-
*
|
|
829
|
-
* THE SIXTH ID THE RUN-SERVICE ROUTES DISPATCH, supplied by the composition and never spelled
|
|
830
|
-
* here, for the reason its five neighbours are: the op id is the agent package's constant, a
|
|
831
|
-
* string literal in this package would be a second declaration of a capability's name free to
|
|
832
|
-
* drift from the spec that answers to it, and this package may not import
|
|
833
|
-
* `@vostride/agent-qa-agent` at all (validate:arch) — so there is nowhere here the real constant
|
|
834
|
-
* could come from.
|
|
835
|
-
*
|
|
836
|
-
* WHAT IT SERVES is the Knowledge panel: what a run USED (the brief channels served per step,
|
|
837
|
-
* the serve-time trace behind each, procedure replay and hint use, the recorded retrieval rung)
|
|
838
|
-
* and what it LEARNED (curation counts, the record changes attributable to it, canary outcomes).
|
|
839
|
-
* `runs.knowledge` is the single producer of that whole view (407 D-05), so routing the page's
|
|
840
|
-
* read through this id is what keeps the browser, the CLI, MCP and chat reading one answer
|
|
841
|
-
* instead of a page composing it from N per-step calls that can disagree.
|
|
842
|
-
*/
|
|
843
577
|
readonly runsKnowledgeFunctionId: string;
|
|
844
|
-
/** 2026-09-08, 419 D-13: the eighth op id arrives as data, on the knowledge id's footing. */
|
|
845
578
|
readonly runsMarkFunctionId: string;
|
|
846
|
-
/** 2026-09-15, 423-21 D-18: the marks-history read id, supplied as data like its neighbours. */
|
|
847
579
|
readonly runsMarksHistoryFunctionId: string;
|
|
848
|
-
/** 2026-09-15, 423-21 D-18: the read-tier mark consequence preview id. */
|
|
849
580
|
readonly runsMarkPreviewFunctionId: string;
|
|
850
|
-
/**
|
|
851
|
-
* `invokeFunction`, bound by the composer. THE one door call.
|
|
852
|
-
*
|
|
853
|
-
* `input` IS `unknown` (404-05). Every op this seam carries has its own strict input schema.
|
|
854
|
-
* Narrowing here would mean this package describing other packages' input contracts — and the
|
|
855
|
-
* real `invokeFunction` has always taken `unknown`, because the op's own schema is what validates
|
|
856
|
-
* it, once, inside the invocation.
|
|
857
|
-
*/
|
|
858
581
|
invokeFunction(registry: AgentRegistryHandle, functionId: string, input: unknown, caller: FunctionCaller): Promise<unknown>;
|
|
859
582
|
}
|
|
860
583
|
|
|
@@ -878,24 +601,10 @@ interface PostProcessingRelay {
|
|
|
878
601
|
}
|
|
879
602
|
declare function createPostProcessingRelay(): PostProcessingRelay;
|
|
880
603
|
|
|
881
|
-
/**
|
|
882
|
-
* What starting a run needs from the composition, as data rather than as a live handle.
|
|
883
|
-
*
|
|
884
|
-
* 2026-10-01 (432-21, D-12): the matched token's `trustScope` and `clientId` are deleted with the
|
|
885
|
-
* token. A start carries the caller's pattern set and nothing about who the caller is.
|
|
886
|
-
*/
|
|
887
604
|
interface RunServiceStartInput {
|
|
888
605
|
/** The pattern set the caller asked for; absent means the configured default set. */
|
|
889
606
|
readonly patterns?: readonly string[];
|
|
890
607
|
}
|
|
891
|
-
/**
|
|
892
|
-
* Everything this door reaches the world through (D-02).
|
|
893
|
-
*
|
|
894
|
-
* ALL ARE INJECTED, and the injection is what makes the module mountable: the implementations name
|
|
895
|
-
* `invokeFunction`, `runs.start` and a composed local host, all of it vocabulary this package may
|
|
896
|
-
* not import. `InProcessRunStarter` is the shape precedent one directory over. 2026-10-01 (432-21,
|
|
897
|
-
* D-12): `verifyBearer` is deleted; the same-site guard needs no port.
|
|
898
|
-
*/
|
|
899
608
|
interface RunServicePorts {
|
|
900
609
|
/**
|
|
901
610
|
* Start a run and return the acknowledgment.
|
|
@@ -906,36 +615,9 @@ interface RunServicePorts {
|
|
|
906
615
|
invokeRunStart(input: RunServiceStartInput): Promise<RunStartAcknowledgement>;
|
|
907
616
|
/** The started run's session, or nothing if this process never started that run. */
|
|
908
617
|
attach(runId: string): RunSession | undefined;
|
|
909
|
-
/** The measured readiness facts `/ok` reports
|
|
618
|
+
/** The measured readiness facts `/ok` reports. */
|
|
910
619
|
readiness(): RunServiceReadiness;
|
|
911
|
-
/**
|
|
912
|
-
* Mint a live-view URL for one handle of a run (403 D-03).
|
|
913
|
-
*
|
|
914
|
-
* REQUIRED, NOT OPTIONAL, and that is a decision rather than an oversight. An optional member is
|
|
915
|
-
* a member a composition can forget, and the failure mode of forgetting it here is a 404 that
|
|
916
|
-
* reads exactly like "no such route" — which is what a door with no live view is indistinguishable
|
|
917
|
-
* from. A composition that cannot mint supplies a function that REJECTS with a
|
|
918
|
-
* `LiveViewUnavailableError`-named error, which the arm maps to 503 `live_view_unavailable`: an
|
|
919
|
-
* honest host fact, said out loud, once, in the vocabulary the local door already uses.
|
|
920
|
-
*
|
|
921
|
-
* The minted token's own subject (run, handle) and expiry are checked by the live-view validator
|
|
922
|
-
* independently of who asked (D-13). 2026-10-01 (432-21, D-12): the bearer's trust scope this mint
|
|
923
|
-
* used to run under is deleted; the composition supplies the one caller it runs under.
|
|
924
|
-
*/
|
|
925
620
|
mintLiveUrl(input: MintLiveUrlInput): Promise<RunsLiveUrlResult>;
|
|
926
|
-
/**
|
|
927
|
-
* The injected agent host the two READ rows dispatch through (405-05, D-12/D-13).
|
|
928
|
-
*
|
|
929
|
-
* OPTIONAL, unlike `mintLiveUrl` above, and the asymmetry is deliberate rather than an
|
|
930
|
-
* oversight. `mintLiveUrl` is required because a composition that forgot it would answer a 404
|
|
931
|
-
* indistinguishable from an unserved path — but the argument runs the other way here: a host
|
|
932
|
-
* genuinely composed without a function registry (a bare mount, this file's own fixtures) has no
|
|
933
|
-
* capability to reach, and the honest answer is the SAME 503 `agent_host_unavailable` the local
|
|
934
|
-
* door already gives for exactly this state. One word, one meaning, both doors.
|
|
935
|
-
*
|
|
936
|
-
* It is a HANDLE and nothing else — this package may not name the agent packages, so what
|
|
937
|
-
* crosses is the seam `chat/host.ts` declares and the op ids the composition supplies as data.
|
|
938
|
-
*/
|
|
939
621
|
readonly agentHost?: AgentHost;
|
|
940
622
|
}
|
|
941
623
|
/** What minting one `liveUrl` needs from a request, as data: the subject, and nothing else. */
|
|
@@ -955,67 +637,30 @@ interface RunServiceRouteRow {
|
|
|
955
637
|
}
|
|
956
638
|
declare const RUN_SERVICE_START_ROUTE = "/run";
|
|
957
639
|
declare const RUN_SERVICE_EVENTS_TEMPLATE = "/run/:runId/events";
|
|
958
|
-
/**
|
|
959
|
-
* The MINT (403 D-03, Q3) — the remote half of the pair whose local half is
|
|
960
|
-
* `GET /api/runs/:runId/live-url`.
|
|
961
|
-
*
|
|
962
|
-
* SAME SHAPE AS THE EVENTS ROUTE ONE LINE UP, deliberately: a caller addresses a run it started by
|
|
963
|
-
* id and asks this door for one thing about it per route. Since 432-21 the two doors differ in
|
|
964
|
-
* nothing but the path — the same op, the same caller shape, the same result and fragment carriage.
|
|
965
|
-
*/
|
|
966
640
|
declare const RUN_SERVICE_LIVE_URL_TEMPLATE = "/run/:runId/live-url";
|
|
967
641
|
/**
|
|
968
|
-
*
|
|
969
|
-
*
|
|
970
|
-
* An `/ok` that answered before the guard would tell a page on another origin that this process is
|
|
971
|
-
* an agent-qa run service and that it is up. (Until 432-21 the guard here was the bearer verdict,
|
|
972
|
-
* and the preflight was liveness and early token validation in one round-trip.)
|
|
973
|
-
*/
|
|
974
|
-
/**
|
|
975
|
-
* The durable run-detail READ (405-05, D-12 / 402 D-16) — the remote twin of the local door's
|
|
976
|
-
* `GET /api/runs/:id/detail`.
|
|
642
|
+
* The durable run-detail READ — the remote twin of the local door's `GET /api/runs/:id/detail`.
|
|
977
643
|
*
|
|
978
644
|
* IT DISPATCHES THROUGH THE SAME ADAPTER THE LOCAL DOOR CALLS. `serveRunDetailRead` is one
|
|
979
645
|
* function, so the two doors cannot come to disagree about what a run's projection is; a second
|
|
980
646
|
* spelling here would agree on the day it was written and be a wire-contract fork thereafter.
|
|
981
647
|
*
|
|
982
|
-
*
|
|
983
|
-
* — its consumer (the CLI's own `emitHuman`, 408's embed) is where a person meets the text, and
|
|
984
|
-
* that consumer is the display boundary. The alternative would restore declared secrets onto a
|
|
985
|
-
* machine wire, extending the disclosure surface to every client and every intermediary, which is
|
|
986
|
-
* not what "the browser is never the boundary" (400-06) asks for. 405-10
|
|
987
|
-
* applies the unmask seam to the LOCAL door only and enrols this row on the masked side.
|
|
648
|
+
* This row serves the same stored body the local door serves, masked at write.
|
|
988
649
|
*/
|
|
989
650
|
declare const RUN_SERVICE_DETAIL_TEMPLATE = "/run/:runId/detail";
|
|
990
651
|
declare const RUN_SERVICE_EVIDENCE_TEMPLATE = "/run/:runId/evidence";
|
|
991
|
-
/**
|
|
992
|
-
* The ref-resolving artifact READ (405-05, D-12 / 402 D-16) — the remote twin of the local door's
|
|
993
|
-
* `GET /api/runs/:runId/artifacts/:sha`, and the row 402 D-16 named by anticipation.
|
|
994
|
-
*
|
|
995
|
-
* TWO CAPTURES, `[^/]+` ON BOTH. The runId is decoded and the sha is not: a content address is 64
|
|
996
|
-
* characters from `[0-9a-f]`, none of which percent-encoding can represent differently, so a sha
|
|
997
|
-
* segment that needed decoding is already not one.
|
|
998
|
-
*
|
|
999
|
-
* MASKED, LIKE ITS SIBLING AND MORE SO: these are BYTES. The unmask seam never touches an artifact
|
|
1000
|
-
* body on any door (D-09) — a screenshot is not text and there is nothing in it to restore.
|
|
1001
|
-
*/
|
|
1002
652
|
declare const RUN_SERVICE_ARTIFACT_TEMPLATE = "/run/:runId/artifacts/:sha";
|
|
1003
653
|
/**
|
|
1004
|
-
* The run-ANALYSIS read
|
|
1005
|
-
* `GET /api/runs/:id/analysis`.
|
|
654
|
+
* The run-ANALYSIS read — the remote twin of the local door's `GET /api/runs/:id/analysis`.
|
|
1006
655
|
*
|
|
1007
656
|
* IT DISPATCHES THROUGH THE SAME ADAPTER THE LOCAL DOOR CALLS, for the reason its detail sibling
|
|
1008
657
|
* does: `serveRunAnalysisRead` is one function, so the two doors cannot come to disagree about
|
|
1009
658
|
* what a run's analysis is.
|
|
1010
659
|
*
|
|
1011
|
-
*
|
|
1012
|
-
* step's recorded error, which carries declared placeholders at rest; restoring them onto a
|
|
1013
|
-
* machine wire would hand them to every client and every intermediary, and this row's
|
|
1014
|
-
* consumer — the CLI's own emit, 408's embed — is where a person meets the text. The dispatch
|
|
1015
|
-
* below passes no `boundary`, and the option's `'machine'` default is what keeps it masked.
|
|
660
|
+
* This row serves the same stored body the local door serves, masked at write.
|
|
1016
661
|
*/
|
|
1017
662
|
declare const RUN_SERVICE_ANALYSIS_TEMPLATE = "/run/:runId/analysis";
|
|
1018
|
-
/**
|
|
663
|
+
/** runs.marks.history and runs.mark.preview behind the same guard. */
|
|
1019
664
|
declare const RUN_SERVICE_MARKS_TEMPLATE = "/run/:runId/marks";
|
|
1020
665
|
declare const RUN_SERVICE_MARK_PREVIEW_TEMPLATE = "/run/:runId/mark-preview";
|
|
1021
666
|
declare const RUN_SERVICE_OK_ROUTE = "/ok";
|
|
@@ -1040,10 +685,9 @@ declare function matchRunServiceRoute(method: string | undefined, path: string):
|
|
|
1040
685
|
/**
|
|
1041
686
|
* Whether a path belongs to this door — the MOUNT's whole question, and method-blind on purpose.
|
|
1042
687
|
*
|
|
1043
|
-
* A host consults this before its own routing so
|
|
1044
|
-
*
|
|
1045
|
-
* than
|
|
1046
|
-
* its SPA fallback away from this surface.
|
|
688
|
+
* A host consults this before its own routing, so every request to a service path, `OPTIONS` and
|
|
689
|
+
* methods this table has no row for included, gets this router's same-site and media-type checks
|
|
690
|
+
* rather than the host's page arms.
|
|
1047
691
|
*
|
|
1048
692
|
* DERIVED FROM THE TABLE, never a second list: the prefixes are read off the rows, so a route
|
|
1049
693
|
* added above is mounted the same commit.
|
|
@@ -1054,15 +698,6 @@ interface RunServiceRouter {
|
|
|
1054
698
|
/** Live SSE connections — so a host can assert this door leaks none on teardown. */
|
|
1055
699
|
openStreamCount(): number;
|
|
1056
700
|
}
|
|
1057
|
-
/**
|
|
1058
|
-
* Where a stream request asked to resume from. Three arms, and the count is the contract.
|
|
1059
|
-
*
|
|
1060
|
-
* `start` is "the caller has observed nothing", `after` carries the last seq it DID observe, and
|
|
1061
|
-
* `invalid` is a fact about the caller's own input. There is deliberately no fourth arm meaning
|
|
1062
|
-
* "unparseable, serve them from the beginning": silently restarting a resume at seq 1 would
|
|
1063
|
-
* re-deliver every envelope the caller already has, and silently serving from the floor would hide
|
|
1064
|
-
* a gap — the two answers D-13 refuses by name.
|
|
1065
|
-
*/
|
|
1066
701
|
type ResumePoint = {
|
|
1067
702
|
readonly kind: 'start';
|
|
1068
703
|
} | {
|
|
@@ -1071,49 +706,14 @@ type ResumePoint = {
|
|
|
1071
706
|
} | {
|
|
1072
707
|
readonly kind: 'invalid';
|
|
1073
708
|
};
|
|
1074
|
-
/**
|
|
1075
|
-
* The DENIAL this rejection is, if it is one — read structurally, never by class (402-06, T-402-22).
|
|
1076
|
-
*
|
|
1077
|
-
* ON `dashboardNeutralReasonOf`'S EXACT PRECEDENT (`execution/in-process-backend.ts`), and for the
|
|
1078
|
-
* same architectural reason: the rejection is a `RunDeniedError` minted in `agent-local`, and this
|
|
1079
|
-
* package may not import `agent`, `agent-local` or `safety` — `pnpm validate:arch` is the
|
|
1080
|
-
* mechanical proof.
|
|
1081
|
-
*
|
|
1082
|
-
* THE DISCRIMINATOR IS `neutralReason`, DELIBERATELY. Only a run denial carries it: an
|
|
1083
|
-
* unrecognised request field, an input error and "the host was asked to start a run before it was
|
|
1084
|
-
* composed" carry none, and those are exactly the rejections that must stay a 500 with no words on
|
|
1085
|
-
* them. Keying on the class NAME would be a string compare against another package's private
|
|
1086
|
-
* vocabulary.
|
|
1087
|
-
*
|
|
1088
|
-
* 2026-10-01 (432-19, D-15): there is no remedy list to validate or project. The production refusal
|
|
1089
|
-
* never carried one, and the remedy vocabulary left with the execution gate.
|
|
1090
|
-
*/
|
|
1091
|
-
declare function runDenialOf(error: unknown): RunServiceDenialBody | undefined;
|
|
1092
709
|
declare function createRunServiceRoutes(ports: RunServicePorts): RunServiceRouter;
|
|
1093
710
|
|
|
1094
711
|
interface StartServerOptions {
|
|
1095
712
|
db: DashboardDatabase;
|
|
1096
713
|
port?: number;
|
|
1097
|
-
/**
|
|
1098
|
-
* The interface this server binds (402-05, D-07 — INVK-03).
|
|
1099
|
-
*
|
|
1100
|
-
* DEFAULTS TO LOOPBACK, and a non-loopback value is REFUSED before anything listens — with no
|
|
1101
|
-
* exemption. This is BREAKING for anyone who relied on the previous `server.listen(port)`, which
|
|
1102
|
-
* bound every interface, and there is no migration flag: the v2 ethos ships no back-compat shim
|
|
1103
|
-
* for a hole. Remote access goes through an authenticating proxy (432 D-13's forward note).
|
|
1104
|
-
*/
|
|
714
|
+
/** Defaults to loopback; any other value is refused before anything listens. */
|
|
1105
715
|
host?: string;
|
|
1106
716
|
uiDir?: string;
|
|
1107
|
-
/**
|
|
1108
|
-
* Where this workspace writes run artifacts (`services.dashboard.artifactsDir`).
|
|
1109
|
-
*
|
|
1110
|
-
* ACCEPTED AND NOT READ BY THIS SERVER SINCE 405-07 (D-14). It used to be resolved into a
|
|
1111
|
-
* screenshots and a videos root that two path-serving routes and the run-deletion sweep read.
|
|
1112
|
-
* Refs are the only artifact addressing now, and the bytes are reached through the
|
|
1113
|
-
* `runs.artifact` op over the evidence store's own layout. The option stays declared because it
|
|
1114
|
-
* is a user-facing config key the RECORDING path still writes under; the dashboard simply no
|
|
1115
|
-
* longer serves or deletes anything by path.
|
|
1116
|
-
*/
|
|
1117
717
|
artifactsDir?: string;
|
|
1118
718
|
workspacePaths?: ResolvedWorkspacePaths;
|
|
1119
719
|
configPath?: string;
|
|
@@ -1125,112 +725,20 @@ interface StartServerOptions {
|
|
|
1125
725
|
};
|
|
1126
726
|
};
|
|
1127
727
|
authFetch?: typeof globalThis.fetch;
|
|
1128
|
-
/**
|
|
1129
|
-
* The composed agent host the chat door dispatches through (400-01, D-01).
|
|
1130
|
-
*
|
|
1131
|
-
* INJECTED by whoever starts this server — in production `agent-qa dashboard`, which composes the
|
|
1132
|
-
* SAME port set `agent-qa chat` does and hands it over, so the two interactive doors have one
|
|
1133
|
-
* answer to "what can a conversation do" (D-08). Absent leaves the chat routes answering 501 by
|
|
1134
|
-
* name: the door exists, this process was started without a host. See `chat/host.ts`.
|
|
1135
|
-
*/
|
|
1136
728
|
agentHost?: AgentHost;
|
|
1137
|
-
/**
|
|
1138
|
-
* The backend every dashboard run executes through (401-07, D-01/D-09/D-10 — INVK-01).
|
|
1139
|
-
*
|
|
1140
|
-
* INJECTED, ON `agentHost`'s OWN IDIOM AND FOR ITS OWN REASON. The implementation that starts a
|
|
1141
|
-
* run names `runs.start`, `invokeFunction` and the composed local host — all of it
|
|
1142
|
-
* `@vostride/agent-qa-agent*` vocabulary this package may not import (validate:arch). So
|
|
1143
|
-
* `agent-qa dashboard` composes it in the process that runs this server and hands it over, which
|
|
1144
|
-
* is what makes the run button one more caller of the op chat already uses rather than a
|
|
1145
|
-
* dashboard carve-out around the gates.
|
|
1146
|
-
*
|
|
1147
|
-
* ABSENT DEGRADES BY NAME, exactly as it did when the CLI binary could not be resolved: the
|
|
1148
|
-
* execution routes answer 503 and the queue's execute handler does nothing. A dashboard started
|
|
1149
|
-
* without a run door is a dashboard that cannot run tests, and it says so.
|
|
1150
|
-
*/
|
|
1151
729
|
executionBackend?: ExecutionBackend;
|
|
1152
|
-
/**
|
|
1153
|
-
* The run service's ports (402-01, D-02/D-06 — INVK-03).
|
|
1154
|
-
*
|
|
1155
|
-
* INJECTED, ON `agentHost`'s AND `executionBackend`'s OWN IDIOM AND FOR THEIR OWN REASON. The
|
|
1156
|
-
* implementations name `runs.start`, `invokeFunction` and the composed local host — all of it
|
|
1157
|
-
* vocabulary this package may not import (validate:arch). So `agent-qa dashboard` composes them
|
|
1158
|
-
* in the process that runs this server and hands them over, which is what makes the run service
|
|
1159
|
-
* a mountable module rather than a fourth process.
|
|
1160
|
-
*
|
|
1161
|
-
* ABSENT MEANS THE SERVICE IS NOT MOUNTED, and `/run` and its neighbours reach whatever the
|
|
1162
|
-
* static/SPA handling below does with an unknown path. 2026-10-01 (432-21, D-12): `agent-qa
|
|
1163
|
-
* dashboard` supplies it unconditionally now. It used to mount only when a run-service credential
|
|
1164
|
-
* was declared, and those credentials are deleted; the door is guarded by the same-site check
|
|
1165
|
-
* and the loopback bind like every other door here. Absent is a bare in-process mount's posture.
|
|
1166
|
-
*/
|
|
1167
730
|
runService?: RunServicePorts;
|
|
1168
|
-
/**
|
|
1169
|
-
* The run service's readiness predicate, served WITHOUT a token on the local dashboard API
|
|
1170
|
-
* (402-05, D-15 — `GET /api/run-readiness`).
|
|
1171
|
-
*
|
|
1172
|
-
* SEPARATE FROM `runService` ABOVE AND NOT DERIVED FROM IT, because a mount without the service
|
|
1173
|
-
* still has a browser that needs an honest readiness answer rather than a 404. `agent-qa
|
|
1174
|
-
* dashboard` supplies the very same function object it put on `runService.readiness`: one
|
|
1175
|
-
* predicate, two doors. (Until 432-21 the service was absent whenever no credential was declared.)
|
|
1176
|
-
*/
|
|
1177
731
|
runServiceReadiness?: () => RunServiceReadiness;
|
|
1178
|
-
/**
|
|
1179
|
-
* The run id → live `RunSession` lookup, as a FIRST-CLASS option (403 D-14 — WINDOWS #264).
|
|
1180
|
-
*
|
|
1181
|
-
* SEPARATE FROM `runService` AND NOT DERIVED FROM IT, on `runServiceReadiness`'s exact argument
|
|
1182
|
-
* one field up. The derivation `runService?.attach` is what made the local run-stream door
|
|
1183
|
-
* answer 503 about runs this very process was executing: until 432-21 `composeRunServicePorts`
|
|
1184
|
-
* ran only when `runServiceTokens` were declared, so the DEFAULT zero-token dashboard composed no
|
|
1185
|
-
* registry at all and the local door had nothing to attach to. `agent-qa dashboard` supplies this
|
|
1186
|
-
* from a registry hoisted above the door.
|
|
1187
|
-
*
|
|
1188
|
-
* The legacy derivation still applies when this is absent, so an in-process caller that only
|
|
1189
|
-
* passes `runService` keeps working byte-for-byte.
|
|
1190
|
-
*/
|
|
1191
732
|
runServiceAttach?: (runId: string) => RunSession | undefined;
|
|
1192
|
-
/**
|
|
1193
|
-
* The live-view seam (403 D-03/D-06): the function layer's validator, by reference, and the
|
|
1194
|
-
* mint dispatched through the registry.
|
|
1195
|
-
*
|
|
1196
|
-
* ABSENT MEANS NO LIVE VIEW IS SERVED — the embed route is not registered, the frame socket
|
|
1197
|
-
* refuses the upgrade, and `GET /api/runs/:runId/live-url` answers 503 by name. This server
|
|
1198
|
-
* holds NO signing key and NO token parse of its own; both are the function layer's, handed in.
|
|
1199
|
-
*/
|
|
1200
733
|
liveView?: {
|
|
1201
734
|
validate(token: string, expect: {
|
|
1202
735
|
subject: LiveViewSubjectRef;
|
|
1203
736
|
now: number;
|
|
1204
737
|
}): LiveUrlVerdict;
|
|
1205
738
|
mintLiveUrl(runId: string, handle: number): Promise<RunsLiveUrlResult>;
|
|
1206
|
-
/**
|
|
1207
|
-
* The `editor.liveurl` mint, dispatched through the registry (428 D-07). ABSENT MEANS NO
|
|
1208
|
-
* EDITOR VIEW IS MINTED, and `GET /api/live-editor/sessions/:id/live-url` answers 503 by name.
|
|
1209
|
-
*/
|
|
1210
739
|
mintEditorLiveUrl?(sessionId: string): Promise<EditorLiveUrlResult>;
|
|
1211
740
|
};
|
|
1212
|
-
/**
|
|
1213
|
-
* The editor-subject registry (428 D-07): the session manager registers each live editor session
|
|
1214
|
-
* here and the frame socket attaches editor subjects through it.
|
|
1215
|
-
*
|
|
1216
|
-
* ABSENT MEANS NO EDITOR SUBJECT IS SERVED ON THE FRAME SOCKET. `agent-qa dashboard` creates one
|
|
1217
|
-
* registry and hands the same object to the live-view composition and to this server.
|
|
1218
|
-
*/
|
|
1219
741
|
liveEditorSubjects?: LiveEditorSubjects;
|
|
1220
|
-
/**
|
|
1221
|
-
* The in-process post-processing chip relay (404-05, D-16).
|
|
1222
|
-
*
|
|
1223
|
-
* INJECTED, ON `agentHost`'s OWN IDIOM AND FOR ITS OWN REASON. The PUBLISHER is the CLI's
|
|
1224
|
-
* post-run chip emitter, in this same process, and this package may not import it — so
|
|
1225
|
-
* `agent-qa dashboard` creates one relay, hands `relay.publish` to the run door's bridge as the
|
|
1226
|
-
* emitter's second sink and hands the relay itself here. It has to be the SAME object: a relay
|
|
1227
|
-
* built inside this function would be a registry nothing publishes to, and the stream door would
|
|
1228
|
-
* heartbeat forever at a page whose chips are demonstrably moving.
|
|
1229
|
-
*
|
|
1230
|
-
* ABSENT MEANS NO PUSH CHANNEL, and `GET /api/runs/:id/post-processing/stream` answers 503 by
|
|
1231
|
-
* name. The READ route needs none of this and keeps working: polling is the floor the whole
|
|
1232
|
-
* design rests on, and the stream is the optimisation over it.
|
|
1233
|
-
*/
|
|
1234
742
|
postProcessingRelay?: PostProcessingRelay;
|
|
1235
743
|
}
|
|
1236
744
|
declare function startServer(opts: StartServerOptions): Promise<{
|
|
@@ -1303,10 +811,6 @@ type FieldState = {
|
|
|
1303
811
|
present: true;
|
|
1304
812
|
value: unknown;
|
|
1305
813
|
};
|
|
1306
|
-
/**
|
|
1307
|
-
* What one change found and left at the field it touched (429-11 D-24). The nodes are the file's
|
|
1308
|
-
* own, so a restore brings back real secrets and comments rather than anything the page holds.
|
|
1309
|
-
*/
|
|
1310
814
|
type ConfigPrior = {
|
|
1311
815
|
kind: 'entry';
|
|
1312
816
|
array: ConfigPathSegment[];
|
|
@@ -1320,7 +824,7 @@ type ConfigPrior = {
|
|
|
1320
824
|
after: FieldState;
|
|
1321
825
|
};
|
|
1322
826
|
type ConfigPriors = readonly ConfigPrior[];
|
|
1323
|
-
/** A whole-document replacement, checked against the bytes the caller read
|
|
827
|
+
/** A whole-document replacement, checked against the bytes the caller read. */
|
|
1324
828
|
type ReplaceDocumentOutcome = {
|
|
1325
829
|
kind: 'ok';
|
|
1326
830
|
revision: string;
|
|
@@ -1374,10 +878,6 @@ declare function serializeConfigWrite<T>(configPath: string, work: () => Promise
|
|
|
1374
878
|
declare class ConfigFileInvalidError extends Error {
|
|
1375
879
|
constructor(message: string);
|
|
1376
880
|
}
|
|
1377
|
-
/**
|
|
1378
|
-
* The config's values for a reader that only needs them (429-32, Pitfall 3): a missing file reads
|
|
1379
|
-
* as empty, and a file that does not parse is an error rather than the part of it yaml recovers.
|
|
1380
|
-
*/
|
|
1381
881
|
declare function readConfigValues(manager: ConfigManager): Promise<Record<string, unknown>>;
|
|
1382
882
|
declare class ConfigManager {
|
|
1383
883
|
private configPath;
|
|
@@ -1405,7 +905,7 @@ type LiveSessionLLMConfig = DashboardLLMConfig & {
|
|
|
1405
905
|
screenshotSize?: number;
|
|
1406
906
|
effectiveResolution?: number;
|
|
1407
907
|
};
|
|
1408
|
-
/** The model entry's own `vision` flag, when the config sets it
|
|
908
|
+
/** The model entry's own `vision` flag, when the config sets it. */
|
|
1409
909
|
modelVision?: boolean;
|
|
1410
910
|
};
|
|
1411
911
|
interface LiveDraftMetadata {
|
|
@@ -1609,22 +1109,10 @@ interface SessionState {
|
|
|
1609
1109
|
interactive: boolean;
|
|
1610
1110
|
terminalError: string | null;
|
|
1611
1111
|
}
|
|
1612
|
-
/**
|
|
1613
|
-
* What the create door found the current config declares about the session's target (432 D-18).
|
|
1614
|
-
*
|
|
1615
|
-
* It can only add a refusal: `initialize` refuses any name here unless the config it reads itself
|
|
1616
|
-
* opts in. There is deliberately no opt-in field, so nothing a caller passes can allow production.
|
|
1617
|
-
*/
|
|
1618
|
-
interface LiveProductionFinding {
|
|
1619
|
-
readonly productionTargetNames: readonly string[];
|
|
1620
|
-
}
|
|
1621
1112
|
interface LiveSessionConfig {
|
|
1622
1113
|
platform: 'web' | 'android' | 'ios';
|
|
1623
1114
|
targetName?: string;
|
|
1624
|
-
production?: LiveProductionFinding;
|
|
1625
|
-
/** 436 D-03: resolved at the create door from the project config and the edited entity. */
|
|
1626
1115
|
plannerLimits?: PlannerLimits;
|
|
1627
|
-
/** 436 D-03: per executed test, project then suite then the test's own `use`. */
|
|
1628
1116
|
plannerLimitsForTest?: (testId: string) => Promise<PlannerLimits>;
|
|
1629
1117
|
llmConfig: LiveSessionLLMConfig;
|
|
1630
1118
|
authFetch?: typeof globalThis.fetch;
|
|
@@ -1637,6 +1125,8 @@ interface LiveSessionConfig {
|
|
|
1637
1125
|
hookRegistryError?: string;
|
|
1638
1126
|
url?: string;
|
|
1639
1127
|
headless?: boolean;
|
|
1128
|
+
/** The resolved `use.timeout.navigation`; unset leaves the web adapter's default. */
|
|
1129
|
+
navigationTimeoutMs?: number;
|
|
1640
1130
|
useDeviceName?: string;
|
|
1641
1131
|
appState?: 'preserve' | 'reset';
|
|
1642
1132
|
bundleId?: string;
|
|
@@ -1655,17 +1145,7 @@ interface LiveSessionConfig {
|
|
|
1655
1145
|
appiumUrl?: string;
|
|
1656
1146
|
};
|
|
1657
1147
|
}
|
|
1658
|
-
/**
|
|
1659
|
-
* The close code the control socket uses for a session this process does not hold (428 P5), so the
|
|
1660
|
-
* page can say the session ended instead of "Disconnected". The dashboard UI spells the same number;
|
|
1661
|
-
* Plan 23 pins the two equal.
|
|
1662
|
-
*/
|
|
1663
1148
|
declare const LIVE_EDITOR_UNKNOWN_SESSION_CLOSE_CODE = 4404;
|
|
1664
|
-
/**
|
|
1665
|
-
* The close code for a control socket a newer one has replaced (428 WR-01). The session is still
|
|
1666
|
-
* held; this socket no longer drives it, so the page must not reconnect and take it back. The
|
|
1667
|
-
* dashboard UI spells the same number.
|
|
1668
|
-
*/
|
|
1669
1149
|
declare const LIVE_EDITOR_SUPERSEDED_CLOSE_CODE = 4409;
|
|
1670
1150
|
|
|
1671
1151
|
/** Why the session let go of a control socket: a newer one replaced it, or the session ended. */
|
|
@@ -1729,19 +1209,9 @@ declare class LiveSession {
|
|
|
1729
1209
|
/** What the editor-subject registry holds for this session: its hub, read at call time. */
|
|
1730
1210
|
liveAttachment(): LiveEditorAttachment;
|
|
1731
1211
|
private openLiveHub;
|
|
1732
|
-
/**
|
|
1733
|
-
* Make a control socket the current one. `release` is how the session lets go of it later: the
|
|
1734
|
-
* previous attachment's is called with `superseded` here (428 WR-01), so one socket drives the
|
|
1735
|
-
* session at a time.
|
|
1736
|
-
*/
|
|
1737
1212
|
beginAttachment(release?: (reason: LiveAttachmentRelease) => void): number;
|
|
1738
1213
|
isCurrentAttachment(generation: number): boolean;
|
|
1739
1214
|
attachMessageSink(sink: ((message: ServerMessage) => void) | null): void;
|
|
1740
|
-
/**
|
|
1741
|
-
* A command's reply, for whichever control socket is attached now (428 CR-01). A command can
|
|
1742
|
-
* outlive the socket that issued it, and its outcome belongs to the page, not to that socket:
|
|
1743
|
-
* with none attached it is held and flushed to the next one.
|
|
1744
|
-
*/
|
|
1745
1215
|
deliver(message: ServerMessage): void;
|
|
1746
1216
|
private dispatch;
|
|
1747
1217
|
private redact;
|
|
@@ -1968,14 +1438,6 @@ type DashboardVisionConfig = {
|
|
|
1968
1438
|
interface RouterDeps {
|
|
1969
1439
|
db: DashboardDatabase;
|
|
1970
1440
|
workspacePaths?: ResolvedWorkspacePaths;
|
|
1971
|
-
/**
|
|
1972
|
-
* The injected run backend (401-07, D-09).
|
|
1973
|
-
*
|
|
1974
|
-
* TYPED AGAINST THE INTERFACE, AND NOW ACTUALLY SEPARABLE. It always meant to be, and was not:
|
|
1975
|
-
* the retired live-event route reached past the interface for a per-run replay buffer only the
|
|
1976
|
-
* concrete class declared, so the seam had exactly one possible implementation. That route and
|
|
1977
|
-
* that buffer are gone (405-07, D-19); what this router asks of a backend is the interface.
|
|
1978
|
-
*/
|
|
1979
1441
|
executionBackend?: ExecutionBackend;
|
|
1980
1442
|
jobQueue?: JobQueue;
|
|
1981
1443
|
testFileManager?: TestFileManager;
|
|
@@ -1986,75 +1448,11 @@ interface RouterDeps {
|
|
|
1986
1448
|
llmConfig?: DashboardRuntimeLLMConfig;
|
|
1987
1449
|
authFetch?: typeof globalThis.fetch;
|
|
1988
1450
|
sessionManager?: SessionManager;
|
|
1989
|
-
/**
|
|
1990
|
-
* The composed agent host (400-01, D-01). It serves run detail, marks, analysis, knowledge and
|
|
1991
|
-
* post-processing. (The run-confirm pair it also served is deleted, 432-14.)
|
|
1992
|
-
*
|
|
1993
|
-
* INJECTED, and optional because a router built the legacy two-argument way
|
|
1994
|
-
* (`createRouter(db)`) has none. Each arm that needs it then answers by name rather than 404 —
|
|
1995
|
-
* the route exists, this server was started without a host. See `chat/host.ts` for why the
|
|
1996
|
-
* composition happens in the CLI command that starts this server rather than here.
|
|
1997
|
-
*/
|
|
1998
1451
|
agentHost?: AgentHost;
|
|
1999
|
-
/**
|
|
2000
|
-
* The run service's readiness predicate, served on the LOCAL door (402-05, D-15).
|
|
2001
|
-
*
|
|
2002
|
-
* THE SAME FUNCTION THE RUN SERVICE'S `/ok` SERVES — one readiness spelling behind two doors,
|
|
2003
|
-
* which is the whole of D-15. It is passed in rather than computed here for the reason `agentHost`
|
|
2004
|
-
* is: every fact in it (is a host composed) is known only to the process that composed it, and a
|
|
2005
|
-
* copy made here is how the run service and the dashboard start disagreeing about whether this
|
|
2006
|
-
* process can run anything.
|
|
2007
|
-
*
|
|
2008
|
-
* ABSENT IS THE LEGACY MOUNT, NOT AN UNCONFIGURED SERVICE. `agent-qa dashboard` ALWAYS supplies
|
|
2009
|
-
* this, because the browser preflight needs an honest answer and a 404 is not one. A router built the legacy
|
|
2010
|
-
* two-argument way has none, and that arm answers 503 by name on `agentHost`'s idiom.
|
|
2011
|
-
*/
|
|
2012
1452
|
runServiceReadiness?: () => RunServiceReadiness;
|
|
2013
|
-
/**
|
|
2014
|
-
* The started run's session, or nothing — the LOCAL door's attach port (402-08, D-01).
|
|
2015
|
-
*
|
|
2016
|
-
* THE SAME PORT THE AUTHED DOOR USES, and `server.ts` supplies it by reading
|
|
2017
|
-
* `runService.attach` rather than by composing a second lookup: one session registry serves both
|
|
2018
|
-
* doors, so a run the remote door can attach to is a run this door can attach to, and there is
|
|
2019
|
-
* no second retention window to disagree about.
|
|
2020
|
-
*
|
|
2021
|
-
* ABSENT MEANS NO RUN SERVICE WAS MOUNTED, which is the same fact as "this process composed no
|
|
2022
|
-
* session registry" — unlike `runServiceReadiness` above, whose absence is a legacy mount rather
|
|
2023
|
-
* than an unconfigured service. The route then answers 503 BY NAME on the execution routes' own
|
|
2024
|
-
* degradation idiom, never a 404 (the route exists) and never an empty stream (which would look
|
|
2025
|
-
* like a run that emitted nothing).
|
|
2026
|
-
*/
|
|
2027
1453
|
runServiceAttach?: (runId: string) => RunSession | undefined;
|
|
2028
|
-
/**
|
|
2029
|
-
* The `runs.liveurl` mint, DISPATCHED THROUGH THE REGISTRY by the composition root (403 D-03).
|
|
2030
|
-
*
|
|
2031
|
-
* A FUNCTION, not a signer: this router holds no key and mints nothing. What it does is turn one
|
|
2032
|
-
* HTTP shape into one op call and the op's refusals into status codes — which is the whole of a
|
|
2033
|
-
* thin client over the function layer.
|
|
2034
|
-
*
|
|
2035
|
-
* ABSENT MEANS THIS HOST SERVES NO LIVE VIEW, and the route answers 503 BY NAME on
|
|
2036
|
-
* `runServiceReadiness`'s idiom — never a 404 (the route exists) and never a URL to nowhere.
|
|
2037
|
-
*/
|
|
2038
1454
|
mintLiveUrl?: (runId: string, handle: number) => Promise<RunsLiveUrlResult>;
|
|
2039
|
-
/**
|
|
2040
|
-
* The `editor.liveurl` mint, dispatched through the registry by the composition root (428 D-07).
|
|
2041
|
-
* The editor counterpart of `mintLiveUrl`: a function, never a signer. ABSENT MEANS THIS HOST
|
|
2042
|
-
* MINTS NO EDITOR VIEW, and the route answers 503 by name.
|
|
2043
|
-
*/
|
|
2044
1455
|
mintEditorLiveUrl?: (sessionId: string) => Promise<EditorLiveUrlResult>;
|
|
2045
|
-
/**
|
|
2046
|
-
* The in-process chip sink the post-processing stream relays from (404-05, D-16).
|
|
2047
|
-
*
|
|
2048
|
-
* INJECTED ON `agentHost`'s OWN IDIOM. The publisher is the CLI's post-run chip emitter — a
|
|
2049
|
-
* package this one may not import — so `agent-qa dashboard` creates the relay, hands
|
|
2050
|
-
* `relay.publish` to the run door's bridge and hands the relay itself here. One object, two
|
|
2051
|
-
* halves of the same process; a relay composed here instead would be a registry the emitter
|
|
2052
|
-
* never reaches, and the stream would heartbeat forever at a page whose chips do move.
|
|
2053
|
-
*
|
|
2054
|
-
* ABSENT MEANS THIS SERVER HAS NO PUSH CHANNEL and the stream arm answers 503 BY NAME — never a
|
|
2055
|
-
* 404 (the route exists) and never an empty stream, which would look like a chain that never
|
|
2056
|
-
* ticked. The READ route is unaffected: polling works with no relay at all.
|
|
2057
|
-
*/
|
|
2058
1456
|
postProcessingRelay?: PostProcessingRelay;
|
|
2059
1457
|
}
|
|
2060
1458
|
declare function createRouter(deps: RouterDeps): (req: IncomingMessage, res: ServerResponse) => void;
|
|
@@ -2080,15 +1478,6 @@ declare function tryParseRequestUrl(req: Pick<IncomingMessage, 'url'>): URL | un
|
|
|
2080
1478
|
* through the door's own responder can re-enter the fault it was catching.
|
|
2081
1479
|
*/
|
|
2082
1480
|
declare function refuseUnparseableRequest(res: ServerResponse): void;
|
|
2083
|
-
/**
|
|
2084
|
-
* The process-level backstop's answer: a 500 in fixed bytes, or a destroyed socket if it is late.
|
|
2085
|
-
*
|
|
2086
|
-
* THE ERROR IS NOT PRINTED AND NOT SERIALIZED. Phase 395 measured a planted credential leaving this
|
|
2087
|
-
* product through an error's serialization rather than its `message`, so what goes to stderr here
|
|
2088
|
-
* is the error's CONSTRUCTOR NAME and the request METHOD — two values with no attacker- or
|
|
2089
|
-
* secret-derived content — and never the URL, which is attacker-chosen, or the error itself, whose
|
|
2090
|
-
* `cause` chain is exactly the surface that leaked.
|
|
2091
|
-
*/
|
|
2092
1481
|
declare function backstopServerError(res: ServerResponse, req: Pick<IncomingMessage, 'method'>, error: unknown): void;
|
|
2093
1482
|
|
|
2094
|
-
export {
|
|
1483
|
+
export { createRunServiceRoutes as $, type AgentHost as A, type RunServicePorts as B, ConfigFileInvalidError as C, DashboardDatabase as D, type ExecutionBackend as E, type RunServiceRouteHandlerName as F, type RunServiceRouteMatch as G, type RunServiceRouteRow as H, type RunServiceRouter as I, type RunServiceStartInput as J, type RunSettledDetails as K, type LiveEditorAttachment as L, type MintLiveUrlInput as M, type RunSettledStatus as N, RunsDatabaseVersionRefusedError as O, type PostProcessingRelay as P, TestFileManager as Q, RUN_SERVICE_ANALYSIS_TEMPLATE as R, type TestValidationError as S, type TestFileInfo as T, type TestValidationResult as U, backstopServerError as V, classifyRunOwner as W, completeRunOwnership as X, createLiveEditorSubjects as Y, createPostProcessingRelay as Z, createRouter as _, type ExecuteOptions as a, defaultRunOwnership as a0, matchRunServiceRoute as a1, orphanSummary as a2, ownedElsewhere as a3, ownsRunServicePath as a4, readConfigValues as a5, readJsonBody as a6, refuseUnparseableRequest as a7, serializeConfigWrite as a8, startServer as a9, tryParseRequestUrl as aa, type AgentRegistryHandle as b, AppiumManager as c, ConfigManager as d, LIVE_EDITOR_SUPERSEDED_CLOSE_CODE as e, LIVE_EDITOR_UNKNOWN_SESSION_CLOSE_CODE as f, type LiveEditorSubjects as g, type PostProcessingListener as h, RUN_SERVICE_ARTIFACT_TEMPLATE as i, RUN_SERVICE_DETAIL_TEMPLATE as j, RUN_SERVICE_EVENTS_TEMPLATE as k, RUN_SERVICE_EVIDENCE_TEMPLATE as l, RUN_SERVICE_LIVE_URL_TEMPLATE as m, RUN_SERVICE_MARKS_TEMPLATE as n, RUN_SERVICE_MARK_PREVIEW_TEMPLATE as o, RUN_SERVICE_OK_ROUTE as p, RUN_SERVICE_ROUTE_TABLE as q, RUN_SERVICE_START_ROUTE as r, type ReplaceDocumentOutcome as s, type ResumePoint as t, type RunOwner as u, type RunOwnerProbe as v, type RunOwnerState as w, type RunOwnership as x, type RunOwnershipInput as y, type RunRow as z };
|