@quantiya/codevibe-claude-plugin 1.0.36 → 1.0.37
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/.claude-plugin/plugin.json +1 -1
- package/dist/server.js +13 -13
- package/node_modules/@quantiya/codevibe-core/dist/appsync/__tests__/appsync-client.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.d.ts +139 -1
- package/node_modules/@quantiya/codevibe-core/dist/appsync/queries.d.ts +5 -0
- package/node_modules/@quantiya/codevibe-core/dist/audit-keys/__tests__/audit-keys-parity.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/audit-keys/index.d.ts +41 -0
- package/node_modules/@quantiya/codevibe-core/dist/auth/__tests__/auth-telemetry.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/auth/auth-telemetry.d.ts +29 -8
- package/node_modules/@quantiya/codevibe-core/dist/index.d.ts +4 -0
- package/node_modules/@quantiya/codevibe-core/dist/index.js +194 -33
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-bootstrap.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-failure-recourse.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-save.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-seat-picker.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-telemetry.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-test-agents.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-types.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/setup-wizard.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/__tests__/v1-options.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/detect-agents.d.ts +56 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/index.d.ts +3 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/orchestration-cli.d.ts +12 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-bootstrap.d.ts +146 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-failure-recourse.d.ts +23 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-save.d.ts +47 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-seat-picker.d.ts +72 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-telemetry.d.ts +54 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-test-agents.d.ts +108 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-types.d.ts +140 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/setup-wizard.d.ts +57 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration/v1-options.d.ts +108 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/integration.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/mocks.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/output-parser.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/registry.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/__tests__/subprocess.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/index.d.ts +15 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/mocks.d.ts +80 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/output-parser.d.ts +95 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/provider.d.ts +153 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/claude-live-smoke.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/claude.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/codex-live-smoke.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/codex.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/gemini-live-smoke.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/__tests__/gemini.test.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/claude.d.ts +59 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/codex.d.ts +67 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/common.d.ts +25 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/providers/gemini.d.ts +108 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/registry.d.ts +87 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/subprocess.d.ts +117 -0
- package/node_modules/@quantiya/codevibe-core/dist/reviewer/types.d.ts +101 -0
- package/node_modules/@quantiya/codevibe-core/dist/types/index.d.ts +2 -0
- package/node_modules/@quantiya/codevibe-core/dist/types/orchestration.d.ts +57 -0
- package/node_modules/@quantiya/codevibe-core/dist/types/reviewer.d.ts +67 -0
- package/node_modules/@quantiya/codevibe-core/dist/types/session.d.ts +16 -0
- package/package.json +1 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { ReviewerRole as PolicyReviewerRole } from '../reviewer/types.js';
|
|
2
|
+
import type { AgentKind } from '../reviewer/types.js';
|
|
3
|
+
import { AgentType } from '../types/session.js';
|
|
4
|
+
import { ReviewerRole as SchemaReviewerRole } from '../types/reviewer.js';
|
|
5
|
+
/**
|
|
6
|
+
* Tier returned by `getSubscriptionStatus`. Drives seat budget +
|
|
7
|
+
* tier-gate at bootstrap.
|
|
8
|
+
*
|
|
9
|
+
* UPPERCASE wire format matches `codevibe-backend/graphql/schema.graphql:209`
|
|
10
|
+
* (`enum SubscriptionTier { FREE PRO MAX }`).
|
|
11
|
+
*/
|
|
12
|
+
export type WizardTier = 'FREE' | 'PRO' | 'MAX';
|
|
13
|
+
/**
|
|
14
|
+
* Tier-aware seat budget. Mirrors
|
|
15
|
+
* `codevibe-backend/lambda/user-management/index.ts:184-188`'s
|
|
16
|
+
* `REVIEWER_SEAT_COUNT` map. Free has no seats — orchestration is not
|
|
17
|
+
* permitted at that tier; the wizard short-circuits at bootstrap with
|
|
18
|
+
* the §6 upgrade interstitial.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SEAT_BUDGET: Record<WizardTier, number | null>;
|
|
21
|
+
/**
|
|
22
|
+
* The 3-role lock from PHASE-3-A-DESIGN.md: the wizard offers ONLY
|
|
23
|
+
* `architecture` / `correctness` / `security`. The schema's
|
|
24
|
+
* `ReviewerRole` enum at `codevibe-backend/graphql/schema.graphql:167-177`
|
|
25
|
+
* still has 9 variants for backward compat / 2.0.x custom-roles
|
|
26
|
+
* (#80) — but the wizard NEVER sends a non-3-role seat to
|
|
27
|
+
* `updateReviewerPolicy`.
|
|
28
|
+
*
|
|
29
|
+
* snake_case matches `codevibe-core/src/reviewer/types.ts:52-61` (the
|
|
30
|
+
* reviewer-module wire). The wizard converts to AppSync UPPERCASE at
|
|
31
|
+
* the save boundary via `roleToAppSync()`.
|
|
32
|
+
*/
|
|
33
|
+
export declare const WIZARD_ROLES: readonly ["architecture", "correctness", "security"];
|
|
34
|
+
export type WizardRole = (typeof WIZARD_ROLES)[number];
|
|
35
|
+
/**
|
|
36
|
+
* Tier-aware default role for each seat (§1 "Default-role fallback").
|
|
37
|
+
* Seat 0 = architecture, Seat 1 = correctness, Seat 2 = security.
|
|
38
|
+
* When the canonical default is already taken by a previous seat, the
|
|
39
|
+
* wizard falls back to the first remaining role in canonical order.
|
|
40
|
+
*/
|
|
41
|
+
export declare const DEFAULT_ROLE_BY_SEAT: WizardRole[];
|
|
42
|
+
/**
|
|
43
|
+
* Canonical agent ordering used for wizard defaults. The first
|
|
44
|
+
* installed agent in this order is the default for each seat unless
|
|
45
|
+
* the user picks otherwise.
|
|
46
|
+
*/
|
|
47
|
+
export declare const AGENT_PRIORITY: AgentKind[];
|
|
48
|
+
/**
|
|
49
|
+
* The wizard's terminal outcomes. Drives `wizard_completed` /
|
|
50
|
+
* `wizard_aborted` GA4 events and the exit code.
|
|
51
|
+
*/
|
|
52
|
+
export type WizardOutcome = {
|
|
53
|
+
kind: 'ok';
|
|
54
|
+
saved: true;
|
|
55
|
+
seats: ReadonlyArray<WizardSeatPick>;
|
|
56
|
+
} | {
|
|
57
|
+
kind: 'saved_after_test_warning';
|
|
58
|
+
saved: true;
|
|
59
|
+
seats: ReadonlyArray<WizardSeatPick>;
|
|
60
|
+
} | {
|
|
61
|
+
kind: 'aborted';
|
|
62
|
+
reason: WizardAbortReason;
|
|
63
|
+
lastStep: WizardStep;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Reasons the wizard exited without saving. Mirror the
|
|
67
|
+
* `wizard_aborted.reason` taxonomy in PHASE-3-A-DESIGN.md §7.
|
|
68
|
+
*/
|
|
69
|
+
export type WizardAbortReason = 'ctrl_c' | 'tier_gate_free' | 'no_clis' | 'step_user_exit' | 'step_save_failed_exit' | 'auth_expired' | 'bootstrap_failure';
|
|
70
|
+
/**
|
|
71
|
+
* Wizard step taxonomy — used for `wizard_step_started`/`completed`/
|
|
72
|
+
* `failed` and `wizard_aborted.last_step`.
|
|
73
|
+
*/
|
|
74
|
+
export type WizardStep = 'bootstrap' | 'seat_assignment' | 'test_my_agents' | 'save';
|
|
75
|
+
/**
|
|
76
|
+
* Per-step `wizard_step_failed.reason` codes. Mirror the table in
|
|
77
|
+
* PHASE-3-A-DESIGN.md §7. Each step has its own bounded reason set;
|
|
78
|
+
* `seat_assignment` has no failure modes (the picker filters out
|
|
79
|
+
* invalid choices UI-side).
|
|
80
|
+
*/
|
|
81
|
+
export type WizardStepFailureReason = 'tier_gate_free' | 'not_signed_in' | 'subscription_status_network' | 'no_clis_installed' | 'test_revise' | 'test_reject' | 'test_escalate' | 'test_parse_failure' | 'test_spawn_failure' | 'test_timeout' | 'update_policy_network' | 'update_policy_5xx' | 'update_policy_throttle' | 'auth_token_expired';
|
|
82
|
+
/**
|
|
83
|
+
* One seat the user picked in Step 1. The wizard converts these to
|
|
84
|
+
* `ReviewerAgentSpecInput[]` at save time by uppercase-mapping role +
|
|
85
|
+
* agent (the schema's wire form).
|
|
86
|
+
*/
|
|
87
|
+
export interface WizardSeatPick {
|
|
88
|
+
seatId: number;
|
|
89
|
+
agent: AgentKind;
|
|
90
|
+
role: WizardRole;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Latency bucket for GA4 `latency_bucket_s` / `total_latency_bucket_s`
|
|
94
|
+
* dimensions. Bounded set — keeps GA4 cardinality tractable per R2
|
|
95
|
+
* round-1 MEDIUM (PHASE-3-A-DESIGN.md §7).
|
|
96
|
+
*/
|
|
97
|
+
export type LatencyBucket = '<2' | '2-5' | '5-10' | '10-30' | '30+';
|
|
98
|
+
/**
|
|
99
|
+
* Categorical bucket for "how many agents are installed" /
|
|
100
|
+
* "how many seats". Locked at "1" / "2" / "3" — there is no "4+"
|
|
101
|
+
* because Max is the ceiling.
|
|
102
|
+
*/
|
|
103
|
+
export type CountBucket = '1' | '2' | '3';
|
|
104
|
+
/**
|
|
105
|
+
* Entry point identifier — distinguishes meta CLI invocation from
|
|
106
|
+
* each plugin's alias (`codevibe-{claude,gemini,codex} orchestration setup`).
|
|
107
|
+
*/
|
|
108
|
+
export type WizardEntry = 'meta_cli' | 'claude_alias' | 'gemini_alias' | 'codex_alias';
|
|
109
|
+
/**
|
|
110
|
+
* Bucket a wall-clock duration into one of the 5 latency-bucket values.
|
|
111
|
+
* Used by telemetry for per-step + total-wizard timing dimensions.
|
|
112
|
+
*/
|
|
113
|
+
export declare function bucketLatencySeconds(seconds: number): LatencyBucket;
|
|
114
|
+
/**
|
|
115
|
+
* Bucket an integer count into "1" / "2" / "3", clamping anything
|
|
116
|
+
* higher to "3". Used for `seats_bucket`, `agents_distinct_bucket`,
|
|
117
|
+
* `roles_distinct_bucket`, `installed_agents_bucket`.
|
|
118
|
+
*/
|
|
119
|
+
export declare function bucketCount(n: number): CountBucket;
|
|
120
|
+
/**
|
|
121
|
+
* Map a wizard role (snake_case) to the reviewer-module's snake_case
|
|
122
|
+
* `ReviewerRole` literal type — used when building a `ReviewerSpec`
|
|
123
|
+
* for `createSubprocessReviewerRegistry().evaluate()`. Pass-through
|
|
124
|
+
* because `WizardRole` is a strict subset of `PolicyReviewerRole`.
|
|
125
|
+
*/
|
|
126
|
+
export declare function roleToReviewerSpec(role: WizardRole): PolicyReviewerRole;
|
|
127
|
+
/**
|
|
128
|
+
* Map a wizard role (snake_case) to the AppSync schema's UPPERCASE
|
|
129
|
+
* `ReviewerRole` enum — used when building a `ReviewerAgentSpecInput`
|
|
130
|
+
* for the `updateReviewerPolicy` mutation. The wizard locks to 3
|
|
131
|
+
* roles, so this mapping is exhaustive over `WizardRole` and never
|
|
132
|
+
* produces one of the 6 non-3-role variants.
|
|
133
|
+
*/
|
|
134
|
+
export declare function roleToAppSync(role: WizardRole): SchemaReviewerRole;
|
|
135
|
+
/**
|
|
136
|
+
* Map AgentKind (lowercase reviewer-module wire) to the AppSync
|
|
137
|
+
* `AgentType` enum (UPPERCASE). Used at save time when building the
|
|
138
|
+
* `ReviewerAgentSpecInput[]` for `updateReviewerPolicy`.
|
|
139
|
+
*/
|
|
140
|
+
export declare function agentToAppSync(agent: AgentKind): AgentType;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { DetectableAgent } from './detect-agents.js';
|
|
2
|
+
import { WizardEntry } from './setup-types.js';
|
|
3
|
+
import { PickerIO } from './setup-seat-picker.js';
|
|
4
|
+
import { AppSyncClient } from '../appsync/appsync-client.js';
|
|
5
|
+
import type { ReviewerSpec, ReviewerVerdict } from '../reviewer/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Parse `--entry=<value>` from argv. Defaults to `meta_cli` if absent
|
|
8
|
+
* or invalid. Plugin wrappers pass `--entry=claude_alias` /
|
|
9
|
+
* `gemini_alias` / `codex_alias` per the §4 alias contract.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseEntry(argv: string[]): WizardEntry;
|
|
12
|
+
/**
|
|
13
|
+
* Injectable dependencies for `runSetupWizardWithDeps`. Factored out
|
|
14
|
+
* so unit tests can drive the whole state machine deterministically
|
|
15
|
+
* (no real readline, no real subprocess spawn, no real network).
|
|
16
|
+
*
|
|
17
|
+
* Production callers use `runSetupWizard`, which wires the production
|
|
18
|
+
* deps + calls `process.exit(result.exitCode)`.
|
|
19
|
+
*/
|
|
20
|
+
export interface SetupWizardDeps {
|
|
21
|
+
/** Builds an authenticated AppSyncClient or returns null if unauthenticated. */
|
|
22
|
+
clientFactory: () => Promise<AppSyncClient | null>;
|
|
23
|
+
/** Returns the subset of agents present on PATH. */
|
|
24
|
+
agentDetector: () => DetectableAgent[];
|
|
25
|
+
/** Optional reviewer registry (Step 2). Default: real subprocess registry. */
|
|
26
|
+
registryFactory?: () => {
|
|
27
|
+
evaluate: (spec: ReviewerSpec, gateId: string) => Promise<ReviewerVerdict>;
|
|
28
|
+
};
|
|
29
|
+
/** Output writer — writes the line as-is (caller controls newlines). */
|
|
30
|
+
write: (line: string) => void;
|
|
31
|
+
/** Build a fresh PickerIO + close handle for the next interactive prompt. */
|
|
32
|
+
createPickerIO: () => {
|
|
33
|
+
io: PickerIO;
|
|
34
|
+
close: () => void;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Result of the wizard's state machine. The public `runSetupWizard`
|
|
39
|
+
* wrapper translates this to a `process.exit(exitCode)`.
|
|
40
|
+
*/
|
|
41
|
+
export interface SetupWizardResult {
|
|
42
|
+
exitCode: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Production entry point. Called from `runOrchestrationCli` when
|
|
46
|
+
* `argv[3] === 'setup'`. Builds production deps + calls process.exit
|
|
47
|
+
* with the wizard's exit code. Drives the full state machine via
|
|
48
|
+
* `runSetupWizardWithDeps`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function runSetupWizard(argv: string[]): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Testable wizard core. Exits with code 0 on success or any user-
|
|
53
|
+
* initiated abort; exit 1 on a failure the user couldn't recover
|
|
54
|
+
* from in the recourse loop. SIGINT is registered + cleaned up
|
|
55
|
+
* around the call (no-op for tests when SIGINT is never fired).
|
|
56
|
+
*/
|
|
57
|
+
export declare function runSetupWizardWithDeps(argv: string[], deps: SetupWizardDeps): Promise<SetupWizardResult>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discriminator value emitted by the engine on
|
|
3
|
+
* `metadata.prompt_kind` for orchestration-escalated gate prompts.
|
|
4
|
+
*
|
|
5
|
+
* Sources of truth (any drift breaks the V1 bridge):
|
|
6
|
+
* - Engine emit: codevibe-core-rs `appsync_emit.rs:847-862`
|
|
7
|
+
* (`build_metadata_json` — emits exactly 5 keys: `tool_name`,
|
|
8
|
+
* `payload`, `prompt_kind`, `summary`, `timeline`).
|
|
9
|
+
* - iOS branch: MessageBubble.swift `extractInteractivePromptOptions`.
|
|
10
|
+
* - Android branch: MessageBubble.kt `extractOptions`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const V1_ORCHESTRATION_PROMPT_KIND: "orchestration_escalated_gate";
|
|
13
|
+
/**
|
|
14
|
+
* V1 user-decision kind (3-position subset of the 5-kind enum).
|
|
15
|
+
*
|
|
16
|
+
* Lowercase snake_case matches `@quantiya/quorum-core`'s `UserDecisionKind`
|
|
17
|
+
* caller-facing type at `codevibe-core-rs/packages/quorum-core/src/types.ts:232-238`.
|
|
18
|
+
* The quorum-core SDK's `applyUserDecision` mutator accepts this lowercase
|
|
19
|
+
* form and internally uppercases via `toWireEnum` before AppSync wire-send
|
|
20
|
+
* (`client.ts:244-246` + line 474). Plugins pass lowercase; the SDK is the
|
|
21
|
+
* conversion layer.
|
|
22
|
+
*
|
|
23
|
+
* iOS + Android pin UPPERCASE in their own enums because they call AppSync
|
|
24
|
+
* GraphQL directly via Amplify (no SDK conversion layer in their path).
|
|
25
|
+
* Both are correct at their respective layers.
|
|
26
|
+
*
|
|
27
|
+
* The two `_WITH_NOTES` variants from the full 5-kind enum are V2 — they
|
|
28
|
+
* require a `notes: EncryptedPayloadInput` value alongside the kind, and
|
|
29
|
+
* V1's "type a number" UX has no notes-input surface. They are deliberately
|
|
30
|
+
* EXCLUDED from this union; `mapOptionNumberToUserDecisionKind` cannot
|
|
31
|
+
* return them.
|
|
32
|
+
*/
|
|
33
|
+
export type V1UserDecisionKind = 'accept' | 'reject_restart' | 'abort_task';
|
|
34
|
+
/**
|
|
35
|
+
* One row of the V1 orchestration option table.
|
|
36
|
+
*
|
|
37
|
+
* `number` is a string (`"1"` / `"2"` / `"3"`) to match iOS' tuple shape
|
|
38
|
+
* `(number: String, text: String)` and the existing
|
|
39
|
+
* `InteractivePromptOption` shape elsewhere in the mobile renderers.
|
|
40
|
+
*/
|
|
41
|
+
export interface V1OrchestrationOption {
|
|
42
|
+
readonly number: string;
|
|
43
|
+
readonly label: string;
|
|
44
|
+
readonly kind: V1UserDecisionKind;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The V1 hardcoded 3-position option table.
|
|
48
|
+
*
|
|
49
|
+
* Order is LOAD-BEARING — `V1_ORCHESTRATION_OPTIONS[i].kind` is the kind
|
|
50
|
+
* sent to the server when the user types option-number `i+1`. Drift from
|
|
51
|
+
* iOS / Android = wrong `UserDecisionKind` on the wire (engine has no
|
|
52
|
+
* server-side validation).
|
|
53
|
+
*
|
|
54
|
+
* position 1 -> accept -> "Accept"
|
|
55
|
+
* position 2 -> reject_restart -> "Reject (restart proposal)"
|
|
56
|
+
* position 3 -> abort_task -> "Abort task"
|
|
57
|
+
*
|
|
58
|
+
* (Kind values are lowercase to match the SDK caller-facing type — see
|
|
59
|
+
* the header comment on the SDK conversion layer. iOS + Android pin
|
|
60
|
+
* UPPERCASE in their own constant tables because they hit AppSync
|
|
61
|
+
* directly without the SDK.)
|
|
62
|
+
*
|
|
63
|
+
* Frozen with `as const` so callers cannot mutate the array nor swap
|
|
64
|
+
* entries in place at runtime.
|
|
65
|
+
*/
|
|
66
|
+
export declare const V1_ORCHESTRATION_OPTIONS: readonly [
|
|
67
|
+
V1OrchestrationOption,
|
|
68
|
+
V1OrchestrationOption,
|
|
69
|
+
V1OrchestrationOption
|
|
70
|
+
];
|
|
71
|
+
/**
|
|
72
|
+
* Map a 1-based option number typed by the user to the matching V1
|
|
73
|
+
* `UserDecisionKind`. Returns `null` for ANY number outside 1..3 —
|
|
74
|
+
* callers MUST surface an error and abort the submit on null (the
|
|
75
|
+
* engine would reject `_WITH_NOTES` kinds without a notes payload in
|
|
76
|
+
* V1, and ANY out-of-range number means the user hit a typo, an
|
|
77
|
+
* accidental keystroke, or a malformed prompt).
|
|
78
|
+
*
|
|
79
|
+
* Out-of-range MUST return null — NOT fall back to `ACCEPT` or any
|
|
80
|
+
* default. A silent fallback would silently destroy or accept the
|
|
81
|
+
* user's work without their consent. Pinned by the
|
|
82
|
+
* `out-of-range returns null` test.
|
|
83
|
+
*
|
|
84
|
+
* @param optionNumber 1-based option position as typed by the user.
|
|
85
|
+
* @returns The matching `V1UserDecisionKind`, or `null` when out of range.
|
|
86
|
+
*/
|
|
87
|
+
export declare function mapOptionNumberToUserDecisionKind(optionNumber: number): V1UserDecisionKind | null;
|
|
88
|
+
/**
|
|
89
|
+
* Shorter alias of `mapOptionNumberToUserDecisionKind`. Matches the helper
|
|
90
|
+
* name used in `PHASE-3-B-MOBILE-V1-BRIDGE-DESIGN.md` §3.1 + §6 Test 9 +
|
|
91
|
+
* §8 source-map row (`mapOptionToUserDecisionKind`). Both names point at
|
|
92
|
+
* the same function — pick whichever reads cleaner at the call site.
|
|
93
|
+
*
|
|
94
|
+
* Plugins can `import { mapOptionToUserDecisionKind }` per the design
|
|
95
|
+
* doc's call-site example at §3.1.
|
|
96
|
+
*/
|
|
97
|
+
export declare const mapOptionToUserDecisionKind: typeof mapOptionNumberToUserDecisionKind;
|
|
98
|
+
/**
|
|
99
|
+
* Lowercase-to-uppercase conversion: `V1UserDecisionKind` (caller-facing,
|
|
100
|
+
* matches `@quantiya/quorum-core` SDK) → `UserDecisionKind` wire enum
|
|
101
|
+
* (matches AppSync schema). Plugins that call `AppSyncClient.applyUserDecision`
|
|
102
|
+
* directly (no SDK in path) use this helper to bridge the V1 option table's
|
|
103
|
+
* lowercase kind to the wire form.
|
|
104
|
+
*
|
|
105
|
+
* Total over the 3 V1 kinds — never returns null for a valid
|
|
106
|
+
* `V1UserDecisionKind` input.
|
|
107
|
+
*/
|
|
108
|
+
export declare function mapV1KindToWire(kind: V1UserDecisionKind): 'ACCEPT' | 'REJECT_RESTART' | 'ABORT_TASK';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type { AgentKind, ReviewerRole, ReviewerVerdict, VerdictId, VerdictKind, } from './types.js';
|
|
2
|
+
export type { ReviewerError, ReviewerProvider, ReviewerSpec, } from './provider.js';
|
|
3
|
+
export { ReviewerErrorClass } from './provider.js';
|
|
4
|
+
export type { ParseResult, ParsedVerdict, VerdictParseError, } from './output-parser.js';
|
|
5
|
+
export { parseVerdictOutput, VerdictParseErrorClass } from './output-parser.js';
|
|
6
|
+
export type { RunReviewerOptions, SubprocessError, SubprocessOutcome, } from './subprocess.js';
|
|
7
|
+
export { runReviewer, SubprocessErrorClass } from './subprocess.js';
|
|
8
|
+
export type { ClaudeReviewerProviderOptions } from './providers/claude.js';
|
|
9
|
+
export { ClaudeReviewerProvider } from './providers/claude.js';
|
|
10
|
+
export type { GeminiEnvelope, GeminiModelStats, GeminiReviewerProviderOptions, GeminiStats, } from './providers/gemini.js';
|
|
11
|
+
export { GeminiReviewerProvider } from './providers/gemini.js';
|
|
12
|
+
export type { CodexReviewerProviderOptions } from './providers/codex.js';
|
|
13
|
+
export { CodexReviewerProvider } from './providers/codex.js';
|
|
14
|
+
export { ReviewerRegistry, createSubprocessReviewerRegistry, } from './registry.js';
|
|
15
|
+
export { MockReviewerSpawner, StaticReviewerMock } from './mocks.js';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type ReviewerProvider, type ReviewerSpec } from './provider.js';
|
|
2
|
+
import type { AgentKind, ReviewerVerdict, VerdictKind } from './types.js';
|
|
3
|
+
import { type ReviewerError } from './provider.js';
|
|
4
|
+
/**
|
|
5
|
+
* Scripted `ReviewerProvider` for tests. Each `evaluate(spec, gateId)`
|
|
6
|
+
* pops the next response from the FIFO queue keyed by
|
|
7
|
+
* `(spec.agent, gateId)`. If no script remains, returns a SpawnFailed
|
|
8
|
+
* error with a diagnostic so test setup bugs surface loudly.
|
|
9
|
+
*
|
|
10
|
+
* Use the `script_*` methods to queue responses before tests call
|
|
11
|
+
* `evaluate`.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MockReviewerSpawner implements ReviewerProvider {
|
|
14
|
+
private readonly scripts;
|
|
15
|
+
private static key;
|
|
16
|
+
/**
|
|
17
|
+
* Script a verdict (with empty `suggested_changes`) for the next
|
|
18
|
+
* `evaluate(agent, gateId)` call. Use `scriptVerdictWithChanges`
|
|
19
|
+
* when `kind === 'REVISE'` (the parser-locked invariant requires
|
|
20
|
+
* non-empty changes for REVISE).
|
|
21
|
+
*/
|
|
22
|
+
scriptVerdict(agent: AgentKind, gateId: string, kind: VerdictKind, reasoning: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Script a verdict with explicit `suggested_changes`. Required when
|
|
25
|
+
* `kind === 'REVISE'`.
|
|
26
|
+
*/
|
|
27
|
+
scriptVerdictWithChanges(agent: AgentKind, gateId: string, kind: VerdictKind, reasoning: string, suggested_changes: string[]): void;
|
|
28
|
+
/** Script an error to return on the next `evaluate(agent, gateId)` call. */
|
|
29
|
+
scriptError(agent: AgentKind, gateId: string, error: ReviewerError): void;
|
|
30
|
+
/**
|
|
31
|
+
* How many scripted responses remain for the given key. Useful for
|
|
32
|
+
* test post-conditions ("all scripts were consumed").
|
|
33
|
+
*/
|
|
34
|
+
remaining(agent: AgentKind, gateId: string): number;
|
|
35
|
+
evaluate(spec: ReviewerSpec, gateId: string): Promise<ReviewerVerdict>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Stateless `ReviewerProvider` for engine-level integration tests and
|
|
39
|
+
* smoke tests. Ignores `gateId`; returns a fixed verdict per agent
|
|
40
|
+
* (or a global default).
|
|
41
|
+
*
|
|
42
|
+
* Construct via static factories:
|
|
43
|
+
* - `StaticReviewerMock.allApprove()` / `.allReject()` / `.allRevise(changes)`
|
|
44
|
+
* / `.allEscalate()` — global default, every agent returns the same.
|
|
45
|
+
* - `StaticReviewerMock.allError(err)` — every agent returns the same error.
|
|
46
|
+
*
|
|
47
|
+
* Stack per-agent overrides on top:
|
|
48
|
+
* - `.withAgentVerdict(agent, kind)` — override one agent's verdict.
|
|
49
|
+
* - `.withAgentError(agent, err)` — override one agent's error.
|
|
50
|
+
*
|
|
51
|
+
* Stacking models mixed-verdict scenarios: e.g.
|
|
52
|
+
* `StaticReviewerMock.allApprove().withAgentVerdict('gemini', 'REJECT')`
|
|
53
|
+
* → Claude approves + Gemini rejects + Codex approves → engine escalates.
|
|
54
|
+
*/
|
|
55
|
+
export declare class StaticReviewerMock implements ReviewerProvider {
|
|
56
|
+
private defaultResponse;
|
|
57
|
+
private readonly perAgent;
|
|
58
|
+
/** Empty mock. Returns SpawnFailed with a diagnostic on every
|
|
59
|
+
* `evaluate` call until a default or per-agent override is set. */
|
|
60
|
+
static new(): StaticReviewerMock;
|
|
61
|
+
/** All reviewers return APPROVE. */
|
|
62
|
+
static allApprove(): StaticReviewerMock;
|
|
63
|
+
/** All reviewers return REJECT. */
|
|
64
|
+
static allReject(): StaticReviewerMock;
|
|
65
|
+
/** All reviewers return REVISE with the given suggested changes.
|
|
66
|
+
* Empty `changes` falls back to a placeholder. */
|
|
67
|
+
static allRevise(changes: string[]): StaticReviewerMock;
|
|
68
|
+
/** All reviewers return ESCALATE. */
|
|
69
|
+
static allEscalate(): StaticReviewerMock;
|
|
70
|
+
/** All reviewers return the given error. */
|
|
71
|
+
static allError(err: ReviewerError): StaticReviewerMock;
|
|
72
|
+
/**
|
|
73
|
+
* Override the response for one agent. Stacks on top of whatever
|
|
74
|
+
* default was configured. Returns `this` for fluent chaining.
|
|
75
|
+
*/
|
|
76
|
+
withAgentVerdict(agent: AgentKind, kind: VerdictKind): this;
|
|
77
|
+
/** Override to return an error for one specific agent. */
|
|
78
|
+
withAgentError(agent: AgentKind, err: ReviewerError): this;
|
|
79
|
+
evaluate(spec: ReviewerSpec, gateId: string): Promise<ReviewerVerdict>;
|
|
80
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { VerdictKind } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Successfully parsed reviewer reply. The engine's fan-out layer lifts
|
|
4
|
+
* these fields into a `ReviewerVerdict` alongside telemetry (agent, tokens,
|
|
5
|
+
* latency, model) supplied by the subprocess layer.
|
|
6
|
+
*/
|
|
7
|
+
export interface ParsedVerdict {
|
|
8
|
+
/** The verdict the reviewer returned. */
|
|
9
|
+
kind: VerdictKind;
|
|
10
|
+
/**
|
|
11
|
+
* Free-form reasoning text (joined with blank-line paragraph separators
|
|
12
|
+
* preserved). Never empty by the time we reach here — reviewers that
|
|
13
|
+
* return only a verdict line fail parsing via `reasoning_missing`.
|
|
14
|
+
*/
|
|
15
|
+
reasoning: string;
|
|
16
|
+
/**
|
|
17
|
+
* Ordered list of specific changes. Always non-empty when
|
|
18
|
+
* `kind === 'REVISE'`; always empty otherwise (enforced by the parser
|
|
19
|
+
* via `revise_missing_changes` / `suggested_changes_require_revise`).
|
|
20
|
+
*/
|
|
21
|
+
suggested_changes: string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Why a reviewer's reply failed the locked-format check. Discriminated
|
|
25
|
+
* union; the subprocess layer maps any of these into `ReviewerError` with
|
|
26
|
+
* `kind: 'parse_failure'` and the raw output attached.
|
|
27
|
+
*
|
|
28
|
+
* Mirrors Rust's `VerdictParseError` enum 1:1.
|
|
29
|
+
*/
|
|
30
|
+
export type VerdictParseError = {
|
|
31
|
+
/** The entire reply was whitespace or empty. A reviewer that wrote
|
|
32
|
+
* nothing has effectively timed out. */
|
|
33
|
+
kind: 'empty_output';
|
|
34
|
+
} | {
|
|
35
|
+
/**
|
|
36
|
+
* The first non-blank line did not start with one of the four
|
|
37
|
+
* verdict keywords (case-insensitive). Includes any leading markdown
|
|
38
|
+
* formatting, quotation, or `VERDICT:` prefix that makes the line
|
|
39
|
+
* diverge from the locked contract.
|
|
40
|
+
*
|
|
41
|
+
* Also fired when a non-blank, non-indented line of prose appears
|
|
42
|
+
* after the bullet section starts (the format reserves post-bullet
|
|
43
|
+
* lines for blank lines or indented continuations only).
|
|
44
|
+
*/
|
|
45
|
+
kind: 'invalid_verdict';
|
|
46
|
+
/** The offending line, trimmed but otherwise verbatim. */
|
|
47
|
+
found: string;
|
|
48
|
+
} | {
|
|
49
|
+
/** Verdict was parsed but no reasoning followed. The locked contract
|
|
50
|
+
* requires reasoning text so the audit record and user-facing
|
|
51
|
+
* disagreement UI have something to show; a bare APPROVE / REJECT
|
|
52
|
+
* line is a parse failure. */
|
|
53
|
+
kind: 'reasoning_missing';
|
|
54
|
+
} | {
|
|
55
|
+
/** Verdict was REVISE but no bulleted suggested-changes list followed.
|
|
56
|
+
* Design-locked: REVISE requires at least one concrete change. */
|
|
57
|
+
kind: 'revise_missing_changes';
|
|
58
|
+
} | {
|
|
59
|
+
/** A non-REVISE verdict was followed by a bulleted list, which the
|
|
60
|
+
* locked contract reserves for REVISE only. */
|
|
61
|
+
kind: 'suggested_changes_require_revise';
|
|
62
|
+
/** The non-REVISE verdict that erroneously had bullets. */
|
|
63
|
+
found: VerdictKind;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Class wrapper around a `VerdictParseError` so callers can `throw`/`catch`
|
|
67
|
+
* structured errors via JS idioms. `.detail` carries the discriminated
|
|
68
|
+
* union; `Error.message` is a human-readable formatting.
|
|
69
|
+
*/
|
|
70
|
+
export declare class VerdictParseErrorClass extends Error {
|
|
71
|
+
readonly detail: VerdictParseError;
|
|
72
|
+
constructor(detail: VerdictParseError);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Result type for `parseVerdictOutput`. Discriminated by `ok`. Mirrors
|
|
76
|
+
* Rust's `Result<ParsedVerdict, VerdictParseError>` without forcing TS
|
|
77
|
+
* callers to `try/catch` — most call sites want to inspect failure types
|
|
78
|
+
* directly to feed the audit log.
|
|
79
|
+
*/
|
|
80
|
+
export type ParseResult = {
|
|
81
|
+
ok: true;
|
|
82
|
+
verdict: ParsedVerdict;
|
|
83
|
+
} | {
|
|
84
|
+
ok: false;
|
|
85
|
+
error: VerdictParseError;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Parse a reviewer reply. Strict: any deviation from the locked format
|
|
89
|
+
* returns `{ ok: false, error: ... }` which the subprocess layer routes to
|
|
90
|
+
* a parse-failure `ReviewerError`.
|
|
91
|
+
*
|
|
92
|
+
* Mirrors Rust's `parse_verdict_output` byte-for-byte. Test coverage
|
|
93
|
+
* matches the Rust unit-test set verbatim.
|
|
94
|
+
*/
|
|
95
|
+
export declare function parseVerdictOutput(raw: string): ParseResult;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { AgentKind, ReviewerRole, ReviewerVerdict } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Spec for spawning one reviewer at one gate. Constructed by the engine
|
|
4
|
+
* from `ReviewerAgentSpec` (from `PolicySnapshot`) + the context bundle for
|
|
5
|
+
* the gate.
|
|
6
|
+
*
|
|
7
|
+
* # Identity
|
|
8
|
+
*
|
|
9
|
+
* Per the 2026-04-23 seat/role pivot, the spec's primary identity is
|
|
10
|
+
* `seat_id` — position in the review panel — NOT `agent`. `agent` may
|
|
11
|
+
* repeat across seats within a single gate (single-vendor case: two Claude
|
|
12
|
+
* seats with different roles). Downstream consensus + verdict validation
|
|
13
|
+
* dedup on `seat_id`, never on `agent`. Providers echo `seat_id` + `role`
|
|
14
|
+
* back on the returned `ReviewerVerdict` so the audit trail can attribute
|
|
15
|
+
* verdicts by lens rather than by agent kind.
|
|
16
|
+
*/
|
|
17
|
+
export interface ReviewerSpec {
|
|
18
|
+
/**
|
|
19
|
+
* Position in the review panel, 0-indexed. For an N-seat policy this is
|
|
20
|
+
* in `0..N`. The primary identity key for this reviewer across the
|
|
21
|
+
* engine, audit log, and FFI — providers MUST echo this value back on
|
|
22
|
+
* the produced `ReviewerVerdict.seat_id`.
|
|
23
|
+
*/
|
|
24
|
+
seat_id: number;
|
|
25
|
+
/**
|
|
26
|
+
* The lens this seat reviews through — Architecture / Correctness /
|
|
27
|
+
* Security for code; Accuracy / Clarity / Completeness for docs;
|
|
28
|
+
* composites for mixed. Drives the role-specific prompt prefix and is
|
|
29
|
+
* echoed back on the verdict for audit attribution. Unique within a
|
|
30
|
+
* policy (a duplicate role defeats the orthogonality purpose).
|
|
31
|
+
*/
|
|
32
|
+
role: ReviewerRole;
|
|
33
|
+
/**
|
|
34
|
+
* Which agent to spawn. MAY repeat across seats when roles differ — the
|
|
35
|
+
* single-vendor case the 2026-04-23 pivot enables.
|
|
36
|
+
*/
|
|
37
|
+
agent: AgentKind;
|
|
38
|
+
/**
|
|
39
|
+
* Tool names the reviewer is allowed to invoke. Typically
|
|
40
|
+
* `["Read", "Grep", "Glob"]` per the read-only reviewer invariant. Shape
|
|
41
|
+
* is agent-agnostic here; each provider enforces the sandbox in its own
|
|
42
|
+
* way:
|
|
43
|
+
* - Claude: `--allowed-tools Read,Grep,Glob` CLI flag.
|
|
44
|
+
* - Gemini: `--approval-mode plan` (Gemini's first-class read-only mode).
|
|
45
|
+
* The `tool_allowlist` is intentionally unused by the Gemini provider;
|
|
46
|
+
* plan mode is the sandbox contract. 2.0.x task #62 tracks adding
|
|
47
|
+
* `--policy <tempfile>` as defense-in-depth.
|
|
48
|
+
* - Codex: `--sandbox read-only --skip-git-repo-check` flags + per-spawn
|
|
49
|
+
* ephemeral output file.
|
|
50
|
+
*/
|
|
51
|
+
tool_allowlist: string[];
|
|
52
|
+
/**
|
|
53
|
+
* Pre-rendered reviewer prompt. Engine renders per artifact type
|
|
54
|
+
* (code / docs / mixed) with a role-specific prefix prepended before
|
|
55
|
+
* calling `evaluate`.
|
|
56
|
+
*/
|
|
57
|
+
prompt_template: string;
|
|
58
|
+
/**
|
|
59
|
+
* Wall-clock timeout for one reviewer's verdict. After this elapses the
|
|
60
|
+
* provider should throw `ReviewerError` with `kind: 'timeout'` and
|
|
61
|
+
* cancel the underlying process.
|
|
62
|
+
*/
|
|
63
|
+
timeout_ms: number;
|
|
64
|
+
/**
|
|
65
|
+
* Optional per-reviewer model preference. `null` defers to the agent's
|
|
66
|
+
* CLI default.
|
|
67
|
+
*/
|
|
68
|
+
model_hint: string | null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Typed error thrown by `ReviewerProvider.evaluate`. Discriminated union
|
|
72
|
+
* matching Rust's `#[serde(tag = "kind", rename_all = "snake_case")]` enum.
|
|
73
|
+
*
|
|
74
|
+
* The engine's consensus path treats any thrown error as equivalent to a
|
|
75
|
+
* `VerdictKind::Escalate` for routing (so safety-defaults-to-escalation
|
|
76
|
+
* holds), but the distinct variants matter for the audit log and the
|
|
77
|
+
* user-facing error message.
|
|
78
|
+
*/
|
|
79
|
+
export type ReviewerError = {
|
|
80
|
+
/** Reviewer exceeded its `timeout_ms` budget. */
|
|
81
|
+
kind: 'timeout';
|
|
82
|
+
/** Which agent timed out (carried so the audit entry can attribute
|
|
83
|
+
* cost / reliability back to the specific agent). */
|
|
84
|
+
agent: AgentKind;
|
|
85
|
+
/** Wall-clock ms elapsed before timeout fired. */
|
|
86
|
+
elapsed_ms: number;
|
|
87
|
+
} | {
|
|
88
|
+
/** Reviewer process could not be launched (CLI missing, spawn syscall
|
|
89
|
+
* failed, etc.). */
|
|
90
|
+
kind: 'spawn_failed';
|
|
91
|
+
agent: AgentKind;
|
|
92
|
+
/** Human-readable cause. */
|
|
93
|
+
reason: string;
|
|
94
|
+
} | {
|
|
95
|
+
/** Reviewer returned but its output couldn't be parsed into a valid
|
|
96
|
+
* verdict. Raw output is preserved for the audit log. */
|
|
97
|
+
kind: 'parse_failure';
|
|
98
|
+
agent: AgentKind;
|
|
99
|
+
/** Raw output (truncated to a reasonable length by the caller if
|
|
100
|
+
* needed). */
|
|
101
|
+
raw_output: string;
|
|
102
|
+
} | {
|
|
103
|
+
/** Reviewer was cancelled by the engine before completing (e.g.,
|
|
104
|
+
* user abort, a sibling reviewer already hard-rejected). No
|
|
105
|
+
* per-agent attribution because cancellation can fire on any
|
|
106
|
+
* reviewer in flight. */
|
|
107
|
+
kind: 'cancelled';
|
|
108
|
+
} | {
|
|
109
|
+
/** A reviewer's task panicked or was aborted before returning a
|
|
110
|
+
* verdict. Mirror of the Rust `InternalJoinFailure` variant. The
|
|
111
|
+
* variant deliberately has no `agent` field — attributing a panic
|
|
112
|
+
* to a specific agent would be a telemetry lie. */
|
|
113
|
+
kind: 'internal_join_failure';
|
|
114
|
+
reason: string;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Class wrapper around a `ReviewerError` so callers can `throw` typed
|
|
118
|
+
* errors and `try { ... } catch (e) { if (e instanceof ReviewerErrorClass) {
|
|
119
|
+
* /* type-narrow on e.detail.kind *\/ } }` from JS-idiom code paths.
|
|
120
|
+
*
|
|
121
|
+
* The `.detail` property carries the discriminated union; `Error.message`
|
|
122
|
+
* is a human-readable formatting matching Rust's `#[error(...)]` strings.
|
|
123
|
+
*/
|
|
124
|
+
export declare class ReviewerErrorClass extends Error {
|
|
125
|
+
/** The structured error detail. Use `.kind` to narrow. */
|
|
126
|
+
readonly detail: ReviewerError;
|
|
127
|
+
constructor(detail: ReviewerError);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Engine's contract with reviewer implementations.
|
|
131
|
+
*
|
|
132
|
+
* **Engine owns lifecycle:** implementations must spawn, await verdict,
|
|
133
|
+
* enforce timeout, cancel, and capture logs internally. The engine calls
|
|
134
|
+
* `evaluate` and awaits — it never holds a handle that could outlive the
|
|
135
|
+
* call.
|
|
136
|
+
*
|
|
137
|
+
* Errors are thrown as `ReviewerErrorClass` instances; callers narrow via
|
|
138
|
+
* the `.detail.kind` discriminator.
|
|
139
|
+
*/
|
|
140
|
+
export interface ReviewerProvider {
|
|
141
|
+
/**
|
|
142
|
+
* Spawn one reviewer per the spec, collect its verdict, enforce timeout.
|
|
143
|
+
*
|
|
144
|
+
* @param spec - the reviewer to spawn (seat_id + role + agent + prompt + timeout)
|
|
145
|
+
* @param gateId - the `ReviewGate` UUID this verdict attaches to. Stored
|
|
146
|
+
* on the returned `ReviewerVerdict.gate_id`.
|
|
147
|
+
* @returns the parsed `ReviewerVerdict` on success.
|
|
148
|
+
* @throws `ReviewerErrorClass` on timeout, spawn failure, parse failure,
|
|
149
|
+
* cancellation, or internal join failure. Use `e.detail.kind` to
|
|
150
|
+
* narrow.
|
|
151
|
+
*/
|
|
152
|
+
evaluate(spec: ReviewerSpec, gateId: string): Promise<ReviewerVerdict>;
|
|
153
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|