@wrenai/genbi 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +141 -0
- package/bin/genbi.mjs +31 -0
- package/dist/assets/echarts-LTFC-ysd.js +40 -0
- package/dist/assets/index-Bo--QMUN.js +441 -0
- package/dist/assets/index-Xs4q7pNo.css +1 -0
- package/dist/index.html +14 -0
- package/dist/wrenai_logo.png +0 -0
- package/dist/wrenai_logo_white.png +0 -0
- package/dist-server/harness/auth/detect.d.ts +18 -0
- package/dist-server/harness/auth/detect.js +37 -0
- package/dist-server/harness/auth/index.d.ts +4 -0
- package/dist-server/harness/auth/index.js +2 -0
- package/dist-server/harness/auth/probe.d.ts +18 -0
- package/dist-server/harness/auth/probe.js +52 -0
- package/dist-server/harness/auth/types.d.ts +42 -0
- package/dist-server/harness/auth/types.js +9 -0
- package/dist-server/harness/bundle/loader.d.ts +32 -0
- package/dist-server/harness/bundle/loader.js +43 -0
- package/dist-server/harness/bundle/schema.d.ts +199 -0
- package/dist-server/harness/bundle/schema.js +127 -0
- package/dist-server/harness/bundle/version.d.ts +10 -0
- package/dist-server/harness/bundle/version.js +43 -0
- package/dist-server/harness/capability/gate.d.ts +6 -0
- package/dist-server/harness/capability/gate.js +29 -0
- package/dist-server/harness/capability/registry.d.ts +6 -0
- package/dist-server/harness/capability/registry.js +17 -0
- package/dist-server/harness/cli-args.d.ts +123 -0
- package/dist-server/harness/cli-args.js +247 -0
- package/dist-server/harness/cli.d.ts +2 -0
- package/dist-server/harness/cli.js +151 -0
- package/dist-server/harness/compile/cache.d.ts +23 -0
- package/dist-server/harness/compile/cache.js +109 -0
- package/dist-server/harness/compile/compose-profile.d.ts +34 -0
- package/dist-server/harness/compile/compose-profile.js +95 -0
- package/dist-server/harness/compile/errors.d.ts +22 -0
- package/dist-server/harness/compile/errors.js +41 -0
- package/dist-server/harness/compile/fingerprint.d.ts +22 -0
- package/dist-server/harness/compile/fingerprint.js +84 -0
- package/dist-server/harness/compile/index.d.ts +8 -0
- package/dist-server/harness/compile/index.js +7 -0
- package/dist-server/harness/compile/pipeline.d.ts +66 -0
- package/dist-server/harness/compile/pipeline.js +176 -0
- package/dist-server/harness/compile/resolve-binary.d.ts +55 -0
- package/dist-server/harness/compile/resolve-binary.js +133 -0
- package/dist-server/harness/compile/types.d.ts +107 -0
- package/dist-server/harness/compile/types.js +1 -0
- package/dist-server/harness/compile/warble-identity.d.ts +12 -0
- package/dist-server/harness/compile/warble-identity.js +33 -0
- package/dist-server/harness/compliance/gate.d.ts +35 -0
- package/dist-server/harness/compliance/gate.js +48 -0
- package/dist-server/harness/compliance/index.d.ts +2 -0
- package/dist-server/harness/compliance/index.js +1 -0
- package/dist-server/harness/compliance/types.d.ts +16 -0
- package/dist-server/harness/compliance/types.js +1 -0
- package/dist-server/harness/events/emitter.d.ts +34 -0
- package/dist-server/harness/events/emitter.js +25 -0
- package/dist-server/harness/events/index.d.ts +4 -0
- package/dist-server/harness/events/index.js +2 -0
- package/dist-server/harness/events/sse.d.ts +20 -0
- package/dist-server/harness/events/sse.js +48 -0
- package/dist-server/harness/events/types.d.ts +131 -0
- package/dist-server/harness/events/types.js +1 -0
- package/dist-server/harness/exec/errors.d.ts +16 -0
- package/dist-server/harness/exec/errors.js +29 -0
- package/dist-server/harness/exec/index.d.ts +5 -0
- package/dist-server/harness/exec/index.js +2 -0
- package/dist-server/harness/exec/local.d.ts +32 -0
- package/dist-server/harness/exec/local.js +134 -0
- package/dist-server/harness/exec/policy.d.ts +12 -0
- package/dist-server/harness/exec/policy.js +1 -0
- package/dist-server/harness/exec/types.d.ts +63 -0
- package/dist-server/harness/exec/types.js +1 -0
- package/dist-server/harness/guardrails/index.d.ts +2 -0
- package/dist-server/harness/guardrails/index.js +1 -0
- package/dist-server/harness/guardrails/policy.d.ts +45 -0
- package/dist-server/harness/guardrails/policy.js +57 -0
- package/dist-server/harness/index.d.ts +37 -0
- package/dist-server/harness/index.js +19 -0
- package/dist-server/harness/loop/errors.d.ts +53 -0
- package/dist-server/harness/loop/errors.js +72 -0
- package/dist-server/harness/loop/executor.d.ts +123 -0
- package/dist-server/harness/loop/executor.js +380 -0
- package/dist-server/harness/loop/guard.d.ts +16 -0
- package/dist-server/harness/loop/guard.js +1 -0
- package/dist-server/harness/loop/index.d.ts +5 -0
- package/dist-server/harness/loop/index.js +3 -0
- package/dist-server/harness/native-producer/index.d.ts +109 -0
- package/dist-server/harness/native-producer/index.js +302 -0
- package/dist-server/harness/npm-package-resolve.d.ts +28 -0
- package/dist-server/harness/npm-package-resolve.js +47 -0
- package/dist-server/harness/providers/adapters/anthropic.d.ts +7 -0
- package/dist-server/harness/providers/adapters/anthropic.js +6 -0
- package/dist-server/harness/providers/adapters/mock.d.ts +4 -0
- package/dist-server/harness/providers/adapters/mock.js +5 -0
- package/dist-server/harness/providers/adapters/openai-compatible.d.ts +10 -0
- package/dist-server/harness/providers/adapters/openai-compatible.js +10 -0
- package/dist-server/harness/providers/binding.d.ts +23 -0
- package/dist-server/harness/providers/binding.js +13 -0
- package/dist-server/harness/providers/errors.d.ts +6 -0
- package/dist-server/harness/providers/errors.js +12 -0
- package/dist-server/harness/providers/index.d.ts +18 -0
- package/dist-server/harness/providers/index.js +22 -0
- package/dist-server/harness/providers/registry.d.ts +16 -0
- package/dist-server/harness/providers/registry.js +24 -0
- package/dist-server/harness/render/envelope.d.ts +145 -0
- package/dist-server/harness/render/envelope.js +428 -0
- package/dist-server/harness/render/errors.d.ts +33 -0
- package/dist-server/harness/render/errors.js +46 -0
- package/dist-server/harness/render/index.d.ts +5 -0
- package/dist-server/harness/render/index.js +3 -0
- package/dist-server/harness/render/validate.d.ts +13 -0
- package/dist-server/harness/render/validate.js +88 -0
- package/dist-server/harness/route/adapter-spec.d.ts +40 -0
- package/dist-server/harness/route/adapter-spec.js +61 -0
- package/dist-server/harness/route/agent-sdk-cli.d.ts +30 -0
- package/dist-server/harness/route/agent-sdk-cli.js +86 -0
- package/dist-server/harness/route/agent-sdk-manifest.d.ts +31 -0
- package/dist-server/harness/route/agent-sdk-manifest.js +56 -0
- package/dist-server/harness/route/artifact-content.d.ts +53 -0
- package/dist-server/harness/route/artifact-content.js +83 -0
- package/dist-server/harness/route/chat-event-mapper.d.ts +95 -0
- package/dist-server/harness/route/chat-event-mapper.js +164 -0
- package/dist-server/harness/route/codex-ask-events.d.ts +25 -0
- package/dist-server/harness/route/codex-ask-events.js +395 -0
- package/dist-server/harness/route/codex-ask.d.ts +15 -0
- package/dist-server/harness/route/codex-ask.js +242 -0
- package/dist-server/harness/route/codex-local-cli.d.ts +20 -0
- package/dist-server/harness/route/codex-local-cli.js +78 -0
- package/dist-server/harness/route/codex-local-manifest.d.ts +22 -0
- package/dist-server/harness/route/codex-local-manifest.js +180 -0
- package/dist-server/harness/route/describe.d.ts +54 -0
- package/dist-server/harness/route/describe.js +84 -0
- package/dist-server/harness/route/dispatched.d.ts +138 -0
- package/dist-server/harness/route/dispatched.js +339 -0
- package/dist-server/harness/route/in-process.d.ts +43 -0
- package/dist-server/harness/route/in-process.js +106 -0
- package/dist-server/harness/route/index.d.ts +19 -0
- package/dist-server/harness/route/index.js +12 -0
- package/dist-server/harness/route/profile-source.d.ts +37 -0
- package/dist-server/harness/route/profile-source.js +76 -0
- package/dist-server/harness/route/route.d.ts +33 -0
- package/dist-server/harness/route/route.js +114 -0
- package/dist-server/harness/route/tier-binding.d.ts +36 -0
- package/dist-server/harness/route/tier-binding.js +63 -0
- package/dist-server/harness/route/types.d.ts +286 -0
- package/dist-server/harness/route/types.js +1 -0
- package/dist-server/harness/session/errors.d.ts +4 -0
- package/dist-server/harness/session/errors.js +7 -0
- package/dist-server/harness/session/gate.d.ts +11 -0
- package/dist-server/harness/session/gate.js +13 -0
- package/dist-server/harness/session/index.d.ts +5 -0
- package/dist-server/harness/session/index.js +3 -0
- package/dist-server/harness/session/run.d.ts +60 -0
- package/dist-server/harness/session/run.js +333 -0
- package/dist-server/harness/session/types.d.ts +29 -0
- package/dist-server/harness/session/types.js +1 -0
- package/dist-server/harness/setup/codex-events.d.ts +12 -0
- package/dist-server/harness/setup/codex-events.js +108 -0
- package/dist-server/harness/setup/runner.d.ts +497 -0
- package/dist-server/harness/setup/runner.js +1314 -0
- package/dist-server/harness/tools/errors.d.ts +107 -0
- package/dist-server/harness/tools/errors.js +141 -0
- package/dist-server/harness/tools/index.d.ts +13 -0
- package/dist-server/harness/tools/index.js +8 -0
- package/dist-server/harness/tools/mcp.d.ts +26 -0
- package/dist-server/harness/tools/mcp.js +15 -0
- package/dist-server/harness/tools/native.d.ts +179 -0
- package/dist-server/harness/tools/native.js +322 -0
- package/dist-server/harness/tools/parse.d.ts +14 -0
- package/dist-server/harness/tools/parse.js +18 -0
- package/dist-server/harness/tools/resolve-wren-binary.d.ts +12 -0
- package/dist-server/harness/tools/resolve-wren-binary.js +21 -0
- package/dist-server/harness/tools/resolve.d.ts +51 -0
- package/dist-server/harness/tools/resolve.js +79 -0
- package/dist-server/harness/tools/setup-native.d.ts +84 -0
- package/dist-server/harness/tools/setup-native.js +353 -0
- package/dist-server/harness/tools/wiring.d.ts +10 -0
- package/dist-server/harness/tools/wiring.js +16 -0
- package/dist-server/providers/setup.provider.yaml +31 -0
- package/dist-server/providers/wren.provider.yaml +33 -0
- package/dist-server/server/adopt.d.ts +87 -0
- package/dist-server/server/adopt.js +263 -0
- package/dist-server/server/app.d.ts +6 -0
- package/dist-server/server/app.js +2521 -0
- package/dist-server/server/auth-choice.d.ts +16 -0
- package/dist-server/server/auth-choice.js +36 -0
- package/dist-server/server/bin.d.ts +2 -0
- package/dist-server/server/bin.js +601 -0
- package/dist-server/server/bootstrap-project-binding.d.ts +31 -0
- package/dist-server/server/bootstrap-project-binding.js +71 -0
- package/dist-server/server/clarify.d.ts +10 -0
- package/dist-server/server/clarify.js +17 -0
- package/dist-server/server/codex-setup-mcp.d.ts +2 -0
- package/dist-server/server/codex-setup-mcp.js +147 -0
- package/dist-server/server/compose.d.ts +89 -0
- package/dist-server/server/compose.js +271 -0
- package/dist-server/server/conn-config.d.ts +30 -0
- package/dist-server/server/conn-config.js +253 -0
- package/dist-server/server/context-files.d.ts +12 -0
- package/dist-server/server/context-files.js +117 -0
- package/dist-server/server/context-map.d.ts +30 -0
- package/dist-server/server/context-map.js +95 -0
- package/dist-server/server/context-source.d.ts +68 -0
- package/dist-server/server/context-source.js +85 -0
- package/dist-server/server/db.d.ts +862 -0
- package/dist-server/server/db.js +1839 -0
- package/dist-server/server/enrichment-runner.d.ts +184 -0
- package/dist-server/server/enrichment-runner.js +213 -0
- package/dist-server/server/enrichment-verify.d.ts +73 -0
- package/dist-server/server/enrichment-verify.js +290 -0
- package/dist-server/server/enrichment.d.ts +232 -0
- package/dist-server/server/enrichment.js +199 -0
- package/dist-server/server/env-detect.d.ts +8 -0
- package/dist-server/server/env-detect.js +17 -0
- package/dist-server/server/env-field-hints.d.ts +46 -0
- package/dist-server/server/env-field-hints.js +48 -0
- package/dist-server/server/fold.d.ts +133 -0
- package/dist-server/server/fold.js +407 -0
- package/dist-server/server/harness-profile-sources.d.ts +3 -0
- package/dist-server/server/harness-profile-sources.js +24 -0
- package/dist-server/server/harness.d.ts +19 -0
- package/dist-server/server/harness.js +439 -0
- package/dist-server/server/impact.d.ts +18 -0
- package/dist-server/server/impact.js +85 -0
- package/dist-server/server/interactive-terminal.d.ts +175 -0
- package/dist-server/server/interactive-terminal.js +336 -0
- package/dist-server/server/native-artifacts.d.ts +1004 -0
- package/dist-server/server/native-artifacts.js +564 -0
- package/dist-server/server/native-dispatch-registry.d.ts +42 -0
- package/dist-server/server/native-dispatch-registry.js +45 -0
- package/dist-server/server/native-producer-fence.d.ts +14 -0
- package/dist-server/server/native-producer-fence.js +48 -0
- package/dist-server/server/native-session-resume.d.ts +6 -0
- package/dist-server/server/native-session-resume.js +103 -0
- package/dist-server/server/native-session-workspace.d.ts +40 -0
- package/dist-server/server/native-session-workspace.js +175 -0
- package/dist-server/server/native-sessions.d.ts +374 -0
- package/dist-server/server/native-sessions.js +1517 -0
- package/dist-server/server/native-wren-runtime.d.ts +20 -0
- package/dist-server/server/native-wren-runtime.js +259 -0
- package/dist-server/server/node-pty-host.d.ts +31 -0
- package/dist-server/server/node-pty-host.js +100 -0
- package/dist-server/server/route-intent.d.ts +40 -0
- package/dist-server/server/route-intent.js +23 -0
- package/dist-server/server/runtime-binding.d.ts +52 -0
- package/dist-server/server/runtime-binding.js +258 -0
- package/dist-server/server/source-catalog.d.ts +84 -0
- package/dist-server/server/source-catalog.js +221 -0
- package/dist-server/server/source-driver.d.ts +35 -0
- package/dist-server/server/source-driver.js +124 -0
- package/dist-server/server/spa.d.ts +2 -0
- package/dist-server/server/spa.js +51 -0
- package/dist-server/server/subscription-model-catalog.d.ts +27 -0
- package/dist-server/server/subscription-model-catalog.js +203 -0
- package/dist-server/server/turn.d.ts +249 -0
- package/dist-server/server/turn.js +1074 -0
- package/dist-server/server/wire-types.d.ts +799 -0
- package/dist-server/server/wire-types.js +1 -0
- package/dist-server/server/wren-home.d.ts +19 -0
- package/dist-server/server/wren-home.js +33 -0
- package/dist-server/server/wren-profiles.d.ts +43 -0
- package/dist-server/server/wren-profiles.js +123 -0
- package/package.json +93 -0
- package/profiles/genbi-default/context/binding.yml +9 -0
- package/profiles/genbi-default/ir.golden.json +506 -0
- package/profiles/genbi-default/profile.yml +16 -0
- package/profiles/genbi-enrich-context/components/apply_enrichment/component.yml +42 -0
- package/profiles/genbi-enrich-context/components/draft_enrichment/component.yml +30 -0
- package/profiles/genbi-enrich-context/components/draft_enrichment/steps/draft.md +34 -0
- package/profiles/genbi-enrich-context/components/inspect_context/component.yml +32 -0
- package/profiles/genbi-enrich-context/components/inspect_context/steps/inspect.md +13 -0
- package/profiles/genbi-enrich-context/context/binding.yml +4 -0
- package/profiles/genbi-enrich-context/ir.golden.json +302 -0
- package/profiles/genbi-enrich-context/profile.yml +15 -0
- package/profiles/genbi-monitor/context/binding.yml +7 -0
- package/profiles/genbi-monitor/ir.golden.json +188 -0
- package/profiles/genbi-monitor/profile.yml +27 -0
- package/profiles/genbi-setup/components/build_context/component.yml +44 -0
- package/profiles/genbi-setup/components/build_context/steps/build.md +14 -0
- package/profiles/genbi-setup/components/connect_source/component.yml +51 -0
- package/profiles/genbi-setup/components/connect_source/steps/connect.md +23 -0
- package/profiles/genbi-setup/context/binding.yml +8 -0
- package/profiles/genbi-setup/ir.golden.json +140 -0
- package/profiles/genbi-setup/profile.yml +18 -0
- package/profiles/genbi-setup/raw/schema.json +5 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real (non-mock) `EnrichmentRunner` implementation for the draft path.
|
|
3
|
+
*
|
|
4
|
+
* Dispatches warble's `genbi-enrich-context` profile — `inspect_context`
|
|
5
|
+
* then `draft_enrichment` — via dispatched (the Claude Agent SDK dispatcher),
|
|
6
|
+
* one subprocess per component. `warble-agent-sdk chat` is a single
|
|
7
|
+
* line-per-turn stdin protocol (see `harness/route/dispatched.ts`'s
|
|
8
|
+
* `spawnChat`/`buildAgentSdkChatArgs`), so a two-component flow is two
|
|
9
|
+
* separate dispatches: this module folds turn 1's finalText into turn 2's
|
|
10
|
+
* composed question itself — there is no SDK-level session chaining that
|
|
11
|
+
* could do this for us within one `draft()` call.
|
|
12
|
+
*
|
|
13
|
+
* Translation, not policy. `server/enrichment.ts`'s `canonicalizeProposal`
|
|
14
|
+
* is the only place a draft becomes a trusted `EnrichmentProposal`: it
|
|
15
|
+
* ignores any `id`/`hash`/`projectRevision`/`risk` the model supplies and
|
|
16
|
+
* independently recomputes them. This module's `translateDraftTerminal`
|
|
17
|
+
* adds a second, independent layer of the same discipline by construction:
|
|
18
|
+
* it copies over only five named fields (`sink`, `changeKind`, `summary`,
|
|
19
|
+
* `draft`, `confidence`) from the model's parsed JSON, so a forged
|
|
20
|
+
* `hash`/`id`/`risk`/`projectRevision` the model includes never even
|
|
21
|
+
* reaches `canonicalizeProposal` in the first place.
|
|
22
|
+
*
|
|
23
|
+
* Vocabulary seam: warble's `draft_enrichment` component (steps/draft.md)
|
|
24
|
+
* only ever describes the operation envelope in prose — `relative_sink`,
|
|
25
|
+
* `recommended_yaml`, confidence/evidence — and is silent on a literal
|
|
26
|
+
* `changeKind`/`summary` field, because those are GenBI-host vocabulary
|
|
27
|
+
* (`EnrichmentChangeKind`), not something warble's own contract shares with
|
|
28
|
+
* the model. `composeDraftPrompt` below is where that gap is closed: it
|
|
29
|
+
* layers an additional host-owned instruction on top of the dispatched
|
|
30
|
+
* component's own step prompt, exactly the way `server/compose.ts`'s
|
|
31
|
+
* `composeSetupPrompt` layers its own `SETUP_STATUS: ok|needs_input|error`
|
|
32
|
+
* terminal convention on top of `connect_source`, "since warble's
|
|
33
|
+
* `connect_source` component carries no terminal-status convention of its
|
|
34
|
+
* own." Neither wrapper prompt edits or contradicts the dispatched
|
|
35
|
+
* component's own instructions.
|
|
36
|
+
*/
|
|
37
|
+
import type { AgentEvent, AuthChoice } from "../harness/index.js";
|
|
38
|
+
import { type EnrichmentMode, type EnrichmentRunner } from "./enrichment.js";
|
|
39
|
+
export declare const INSPECT_CONTEXT_AGENT_ID = "inspect_context";
|
|
40
|
+
export declare const DRAFT_ENRICHMENT_AGENT_ID = "draft_enrichment";
|
|
41
|
+
/** One dispatched turn: an `agentId` (warble component) + composed `question`, against a bound project. */
|
|
42
|
+
export interface EnrichmentDispatchInput {
|
|
43
|
+
readonly agentId: string;
|
|
44
|
+
readonly question: string;
|
|
45
|
+
readonly userProject: string;
|
|
46
|
+
}
|
|
47
|
+
export interface EnrichmentDispatchResult {
|
|
48
|
+
readonly finalText: string;
|
|
49
|
+
}
|
|
50
|
+
/** Test-only seam: replaces the two real dispatched subprocess dispatches. Never set in production. */
|
|
51
|
+
export type EnrichmentDispatch = (input: EnrichmentDispatchInput) => Promise<EnrichmentDispatchResult>;
|
|
52
|
+
export interface DispatchedEnrichmentDraftRunnerOptions {
|
|
53
|
+
/**
|
|
54
|
+
* Live auth-choice read, not a value frozen at construction. `EnrichmentRunner.draft()`
|
|
55
|
+
* (`server/enrichment.ts`) takes no `authChoice` parameter of its own — unlike
|
|
56
|
+
* `SetupStepRunner.run()`, which does — so this is this module's own seam for staying current
|
|
57
|
+
* with a later `PUT /api/config/runtime` rebind (`server/turn.ts`'s `TurnDeps.getAuthChoice`)
|
|
58
|
+
* instead of dispatching every future draft call against whatever auth choice happened to be
|
|
59
|
+
* active when `server/bin.ts` constructed this runner at boot.
|
|
60
|
+
*/
|
|
61
|
+
readonly getAuthChoice: () => AuthChoice;
|
|
62
|
+
/** Defaults to `resolveDefaultEnrichIrPath()` (the committed `profiles/genbi-enrich-context/ir.golden.json`). */
|
|
63
|
+
readonly irPath?: string;
|
|
64
|
+
readonly warbleBin?: string;
|
|
65
|
+
readonly agentSdkBin?: string;
|
|
66
|
+
readonly outDir?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Mirrors `DispatchedSetupRunnerOptions.getModelsConfig` — a live read, not a value frozen at
|
|
69
|
+
* construction, so a later `PUT /api/config/runtime` rebind is picked up by the next draft
|
|
70
|
+
* call instead of requiring a process restart.
|
|
71
|
+
*/
|
|
72
|
+
/**
|
|
73
|
+
* Directory of the genbi-enrich-context profile. When set, the draft is
|
|
74
|
+
* Dispatched from an IR compiled against the bound project — which is the
|
|
75
|
+
* only way the agent's injected context describes the project it is about to
|
|
76
|
+
* propose changes to.
|
|
77
|
+
*
|
|
78
|
+
* Without it the runner falls back to `irPath`, a prebuilt IR. That is how
|
|
79
|
+
* this ran until now, and the prebuilt IR available to it was the profile's
|
|
80
|
+
* eval golden: the profile compiled against warble's own example project,
|
|
81
|
+
* with jaffle-shop's models baked into `context_binding.resolved`. A live
|
|
82
|
+
* draft duly analysed gaps in someone else's schema.
|
|
83
|
+
*/
|
|
84
|
+
readonly profileSource?: string;
|
|
85
|
+
readonly getModelsConfig?: () => string | undefined;
|
|
86
|
+
readonly chatTimeoutMs?: number;
|
|
87
|
+
readonly maxTurns?: number;
|
|
88
|
+
readonly onEvent?: (event: AgentEvent) => void;
|
|
89
|
+
/** Test-only seam. See `EnrichmentDispatch`. Never set in production wiring (`server/bin.ts`). */
|
|
90
|
+
readonly dispatch?: EnrichmentDispatch;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Which profile input `runDispatchedDefault` is given, and whether it is allowed to
|
|
94
|
+
* skip compilation.
|
|
95
|
+
*
|
|
96
|
+
* Passing `irPath` short-circuits `compileProfile`, which is how a prebuilt
|
|
97
|
+
* golden — the profile compiled against warble's own example project — used to
|
|
98
|
+
* reach the agent. With a profile source we want the opposite: compile, so the
|
|
99
|
+
* Dispatched IR's context is the bound project's.
|
|
100
|
+
*
|
|
101
|
+
* Exported because that branch is the whole point of the fix and is otherwise
|
|
102
|
+
* only reachable through a real dispatch.
|
|
103
|
+
*/
|
|
104
|
+
export declare function draftProfileInput(profileSource: string | undefined, irPath: string): {
|
|
105
|
+
profileSource: string;
|
|
106
|
+
irPath?: string;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* `inspect_context` has no formal params and no dynamic per-run content to
|
|
110
|
+
* restate (unlike Setup's `connect`/`context` steps, which restate a
|
|
111
|
+
* project name / source type the warble component has no other way to
|
|
112
|
+
* learn). The only thing this run-specific wrapper needs to convey is the
|
|
113
|
+
* mode, because `steps/inspect.md` itself makes probe permission mode
|
|
114
|
+
* dependent ("In grill mode, live database probes are allowed only after
|
|
115
|
+
* the host records the user's one-time consent; in autopilot they are
|
|
116
|
+
* forbidden"). This host does not yet implement a consent-recording
|
|
117
|
+
* mechanism, so it must say so honestly rather than silently imply consent
|
|
118
|
+
* was granted — asserting an unrecorded consent is exactly the kind of
|
|
119
|
+
* disprovable claim this codebase has been burned by before.
|
|
120
|
+
*/
|
|
121
|
+
export declare function composeInspectPrompt(mode: EnrichmentMode): string;
|
|
122
|
+
/**
|
|
123
|
+
* Layers two host-owned requirements on top of `draft_enrichment`'s own
|
|
124
|
+
* `steps/draft.md` instructions, which never contradict: (1) the pinned
|
|
125
|
+
* project revision this run is locked to, restated so the model treats it
|
|
126
|
+
* as input rather than inferring one of its own (draft.md already demands
|
|
127
|
+
* this, this just supplies the concrete value); (2) a `changeKind` and a
|
|
128
|
+
* `summary` field on every operation — vocabulary the host's own
|
|
129
|
+
* `EnrichmentChangeKind` type needs to classify and route the sink, that
|
|
130
|
+
* warble's component prose never names. Everything else (field names for
|
|
131
|
+
* the sink/body themselves, the single-operation-plus-decision shape for
|
|
132
|
+
* grill, the cube schema, the append-only/no-overwrite rules) is exactly
|
|
133
|
+
* what draft.md already tells the model — restating it here would be
|
|
134
|
+
* redundant, not additive.
|
|
135
|
+
*/
|
|
136
|
+
export declare function composeDraftPrompt(mode: EnrichmentMode, projectRevision: string, gapInventory: string): string;
|
|
137
|
+
/**
|
|
138
|
+
* Parses the model's bare-JSON final message. draft.md's instruction is
|
|
139
|
+
* unambiguous ("Your FINAL message must be one JSON object only. Do not
|
|
140
|
+
* include prose or Markdown fences"), and the compiled golden the runtime
|
|
141
|
+
* actually dispatches matches it byte for byte -- so a fenced terminal is
|
|
142
|
+
* model variance, not prompt drift, and the durable fix is host-side
|
|
143
|
+
* tolerance, not a prompt rewrite (see
|
|
144
|
+
* `test/draft-enrichment-fenced-terminal.integration.test.ts`, pinned
|
|
145
|
+
* against a real recorded run whose terminal was prose followed by a
|
|
146
|
+
* ```json fenced block).
|
|
147
|
+
*
|
|
148
|
+
* The fence match is intentionally NOT anchored to the whole trimmed
|
|
149
|
+
* string, so a fence preceded (or followed) by prose is tolerated the same
|
|
150
|
+
* as a bare fence or no fence at all. This duplicates the fence-matching
|
|
151
|
+
* approach `harness/render/envelope.ts`'s `extractJsonObjectText` already
|
|
152
|
+
* uses for the unrelated answer-rendering path, rather than importing that
|
|
153
|
+
* function directly: it is private to that module, and its extra
|
|
154
|
+
* brace-scanning fallback (for free-form, unfenced prose) is machinery this
|
|
155
|
+
* caller doesn't need -- a bare JSON terminal here already round-trips
|
|
156
|
+
* through `JSON.parse` below with no fence at all.
|
|
157
|
+
*/
|
|
158
|
+
export declare function parseDraftTerminalJson(finalText: string): unknown;
|
|
159
|
+
/**
|
|
160
|
+
* Normalizes warble's model-facing terminal shape (`{ enrichment_proposal:
|
|
161
|
+
* {...} }`, a single operation directly under `enrichment_proposal` for
|
|
162
|
+
* grill per draft.md's spec, or an `operations` array for a multi-operation
|
|
163
|
+
* flow) into the shape `canonicalizeProposal` (server/enrichment.ts)
|
|
164
|
+
* accepts: `{ operations: [{ sink, changeKind, summary, draft, confidence
|
|
165
|
+
* }] }`. Copies over ONLY those five fields, by name, from whichever of the
|
|
166
|
+
* model's own field names (`relative_sink`/`recommended_yaml`, this
|
|
167
|
+
* module's added `changeKind`/`summary`) or the host's own names
|
|
168
|
+
* (`sink`/`draft`) the model actually used — so a forged `hash`, `id`,
|
|
169
|
+
* `projectRevision`, or `risk` the model includes anywhere in its JSON is
|
|
170
|
+
* silently dropped here and never reaches `canonicalizeProposal` at all.
|
|
171
|
+
*/
|
|
172
|
+
export declare function translateDraftTerminal(finalText: string): unknown;
|
|
173
|
+
/**
|
|
174
|
+
* Builds the real, production `EnrichmentRunner.draft()`: two dispatched
|
|
175
|
+
* dispatches (`inspect_context` then `draft_enrichment`) against the bound
|
|
176
|
+
* project, folding turn 1's output into turn 2's composed question, then
|
|
177
|
+
* translating the terminal into the shape the host's own
|
|
178
|
+
* `canonicalizeProposal` independently validates and hashes. Returns
|
|
179
|
+
* `unknown`, exactly like the interface requires — this function never
|
|
180
|
+
* calls `canonicalizeProposal` itself; that stays the caller's (the `/api/
|
|
181
|
+
* context/enrichment/*` route's) job, same as every mock runner in
|
|
182
|
+
* `test/bff-enrichment.test.ts`.
|
|
183
|
+
*/
|
|
184
|
+
export declare function createDispatchedEnrichmentDraftRunner(options: DispatchedEnrichmentDraftRunnerOptions): EnrichmentRunner;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { resolveDefaultEnrichIrPath, runDispatchedDefault } from "../harness/index.js";
|
|
2
|
+
import { EnrichmentContractError } from "./enrichment.js";
|
|
3
|
+
/**
|
|
4
|
+
* The one live refusal condition `readiness()` and `defaultDispatch` share --
|
|
5
|
+
* this dispatch path only ever talks to Claude via dispatched, so anything else
|
|
6
|
+
* is a refusal, not a routing choice. Kept as a single function so the two
|
|
7
|
+
* call sites (the readiness check below, and `defaultDispatch`'s own guard)
|
|
8
|
+
* can never drift apart from each other; the reason code is also exactly
|
|
9
|
+
* what `readiness()` hands to the host route, which forwards it verbatim.
|
|
10
|
+
*/
|
|
11
|
+
const REQUIRES_CLAUDE_SUBSCRIPTION = "requires_claude_subscription";
|
|
12
|
+
/**
|
|
13
|
+
* A type guard (not just a boolean) so `defaultDispatch`'s own guard clause
|
|
14
|
+
* keeps narrowing `authChoice` to what `runDispatchedDefault` requires -- the
|
|
15
|
+
* single source of truth `draftAuthReadiness` and `defaultDispatch` both
|
|
16
|
+
* call, so the two can never drift apart.
|
|
17
|
+
*/
|
|
18
|
+
function isClaudeSubscriptionAuth(authChoice) {
|
|
19
|
+
return authChoice.mode === "subscription" && authChoice.provider === "claude";
|
|
20
|
+
}
|
|
21
|
+
function draftAuthReadiness(authChoice) {
|
|
22
|
+
return isClaudeSubscriptionAuth(authChoice) ? { available: true } : { available: false, reason: REQUIRES_CLAUDE_SUBSCRIPTION };
|
|
23
|
+
}
|
|
24
|
+
export const INSPECT_CONTEXT_AGENT_ID = "inspect_context";
|
|
25
|
+
export const DRAFT_ENRICHMENT_AGENT_ID = "draft_enrichment";
|
|
26
|
+
/**
|
|
27
|
+
* Which profile input `runDispatchedDefault` is given, and whether it is allowed to
|
|
28
|
+
* skip compilation.
|
|
29
|
+
*
|
|
30
|
+
* Passing `irPath` short-circuits `compileProfile`, which is how a prebuilt
|
|
31
|
+
* golden — the profile compiled against warble's own example project — used to
|
|
32
|
+
* reach the agent. With a profile source we want the opposite: compile, so the
|
|
33
|
+
* Dispatched IR's context is the bound project's.
|
|
34
|
+
*
|
|
35
|
+
* Exported because that branch is the whole point of the fix and is otherwise
|
|
36
|
+
* only reachable through a real dispatch.
|
|
37
|
+
*/
|
|
38
|
+
export function draftProfileInput(profileSource, irPath) {
|
|
39
|
+
return profileSource === undefined ? { profileSource: irPath, irPath } : { profileSource };
|
|
40
|
+
}
|
|
41
|
+
function defaultDispatch(options) {
|
|
42
|
+
return async ({ agentId, question, userProject }) => {
|
|
43
|
+
const irPath = options.irPath ?? resolveDefaultEnrichIrPath();
|
|
44
|
+
if (irPath === undefined) {
|
|
45
|
+
throw new EnrichmentContractError("no genbi-enrich-context IR found (searched ancestors for a sibling warble checkout); " +
|
|
46
|
+
"pass an explicit irPath or check out warble as a sibling repo");
|
|
47
|
+
}
|
|
48
|
+
const authChoice = options.getAuthChoice();
|
|
49
|
+
if (!isClaudeSubscriptionAuth(authChoice)) {
|
|
50
|
+
throw new EnrichmentContractError(`enrichment draft dispatch requires Claude subscription auth, got mode "${authChoice.mode}"` +
|
|
51
|
+
(authChoice.mode === "subscription" ? ` provider "${authChoice.provider}"` : ""));
|
|
52
|
+
}
|
|
53
|
+
const modelsConfig = options.getModelsConfig?.();
|
|
54
|
+
const result = await runDispatchedDefault({
|
|
55
|
+
authChoice,
|
|
56
|
+
...draftProfileInput(options.profileSource, irPath),
|
|
57
|
+
userProject,
|
|
58
|
+
question,
|
|
59
|
+
agentId,
|
|
60
|
+
...(options.warbleBin !== undefined ? { warbleBin: options.warbleBin } : {}),
|
|
61
|
+
...(options.agentSdkBin !== undefined ? { agentSdkBin: options.agentSdkBin } : {}),
|
|
62
|
+
...(options.outDir !== undefined ? { outDir: options.outDir } : {}),
|
|
63
|
+
...(modelsConfig !== undefined ? { modelsConfig } : {}),
|
|
64
|
+
...(options.chatTimeoutMs !== undefined ? { chatTimeoutMs: options.chatTimeoutMs } : {}),
|
|
65
|
+
...(options.maxTurns !== undefined ? { maxTurns: options.maxTurns } : {}),
|
|
66
|
+
...(options.onEvent !== undefined ? { onEvent: options.onEvent } : {}),
|
|
67
|
+
});
|
|
68
|
+
return { finalText: result.finalText };
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* `inspect_context` has no formal params and no dynamic per-run content to
|
|
73
|
+
* restate (unlike Setup's `connect`/`context` steps, which restate a
|
|
74
|
+
* project name / source type the warble component has no other way to
|
|
75
|
+
* learn). The only thing this run-specific wrapper needs to convey is the
|
|
76
|
+
* mode, because `steps/inspect.md` itself makes probe permission mode
|
|
77
|
+
* dependent ("In grill mode, live database probes are allowed only after
|
|
78
|
+
* the host records the user's one-time consent; in autopilot they are
|
|
79
|
+
* forbidden"). This host does not yet implement a consent-recording
|
|
80
|
+
* mechanism, so it must say so honestly rather than silently imply consent
|
|
81
|
+
* was granted — asserting an unrecorded consent is exactly the kind of
|
|
82
|
+
* disprovable claim this codebase has been burned by before.
|
|
83
|
+
*/
|
|
84
|
+
export function composeInspectPrompt(mode) {
|
|
85
|
+
const probeRule = mode === "grill"
|
|
86
|
+
? "No one-time database-probe consent has been recorded for this run, so do not perform any live database probe — rely only on already-materialized MDL, cube, knowledge, and NL-to-SQL content."
|
|
87
|
+
: "Autopilot mode: live database probes are forbidden — rely only on already-materialized MDL, cube, knowledge, and NL-to-SQL content.";
|
|
88
|
+
return `Begin the enrichment inventory now. Run mode is "${mode}". ${probeRule} Produce the enrichment_gaps inventory exactly as instructed.`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Layers two host-owned requirements on top of `draft_enrichment`'s own
|
|
92
|
+
* `steps/draft.md` instructions, which never contradict: (1) the pinned
|
|
93
|
+
* project revision this run is locked to, restated so the model treats it
|
|
94
|
+
* as input rather than inferring one of its own (draft.md already demands
|
|
95
|
+
* this, this just supplies the concrete value); (2) a `changeKind` and a
|
|
96
|
+
* `summary` field on every operation — vocabulary the host's own
|
|
97
|
+
* `EnrichmentChangeKind` type needs to classify and route the sink, that
|
|
98
|
+
* warble's component prose never names. Everything else (field names for
|
|
99
|
+
* the sink/body themselves, the single-operation-plus-decision shape for
|
|
100
|
+
* grill, the cube schema, the append-only/no-overwrite rules) is exactly
|
|
101
|
+
* what draft.md already tells the model — restating it here would be
|
|
102
|
+
* redundant, not additive.
|
|
103
|
+
*/
|
|
104
|
+
export function composeDraftPrompt(mode, projectRevision, gapInventory) {
|
|
105
|
+
const changeKinds = "knowledge_append, new_cube, new_view, new_relationship, mdl_metric, calculated_column, conflict, ambiguous";
|
|
106
|
+
return (`Draft the enrichment proposal now for project revision "${projectRevision}", run mode "${mode}". ` +
|
|
107
|
+
`In addition to the fields your own instructions already describe, every operation object must also carry ` +
|
|
108
|
+
`a "changeKind" field set to exactly one of: ${changeKinds}; and a "summary" field: a short, one-line, ` +
|
|
109
|
+
`human-readable description of the change with no raw excerpts or credentials. Do not invent or claim a ` +
|
|
110
|
+
`hash, digest, id, or risk label for any operation — the host computes and independently verifies all of ` +
|
|
111
|
+
`those and will discard any you include. Gap inventory from the inspection step:\n${gapInventory}`);
|
|
112
|
+
}
|
|
113
|
+
function record(value) {
|
|
114
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Parses the model's bare-JSON final message. draft.md's instruction is
|
|
118
|
+
* unambiguous ("Your FINAL message must be one JSON object only. Do not
|
|
119
|
+
* include prose or Markdown fences"), and the compiled golden the runtime
|
|
120
|
+
* actually dispatches matches it byte for byte -- so a fenced terminal is
|
|
121
|
+
* model variance, not prompt drift, and the durable fix is host-side
|
|
122
|
+
* tolerance, not a prompt rewrite (see
|
|
123
|
+
* `test/draft-enrichment-fenced-terminal.integration.test.ts`, pinned
|
|
124
|
+
* against a real recorded run whose terminal was prose followed by a
|
|
125
|
+
* ```json fenced block).
|
|
126
|
+
*
|
|
127
|
+
* The fence match is intentionally NOT anchored to the whole trimmed
|
|
128
|
+
* string, so a fence preceded (or followed) by prose is tolerated the same
|
|
129
|
+
* as a bare fence or no fence at all. This duplicates the fence-matching
|
|
130
|
+
* approach `harness/render/envelope.ts`'s `extractJsonObjectText` already
|
|
131
|
+
* uses for the unrelated answer-rendering path, rather than importing that
|
|
132
|
+
* function directly: it is private to that module, and its extra
|
|
133
|
+
* brace-scanning fallback (for free-form, unfenced prose) is machinery this
|
|
134
|
+
* caller doesn't need -- a bare JSON terminal here already round-trips
|
|
135
|
+
* through `JSON.parse` below with no fence at all.
|
|
136
|
+
*/
|
|
137
|
+
export function parseDraftTerminalJson(finalText) {
|
|
138
|
+
let text = finalText.trim();
|
|
139
|
+
const fenced = /```(?:json)?\s*([\s\S]*?)\s*```/.exec(text);
|
|
140
|
+
if (fenced?.[1] !== undefined)
|
|
141
|
+
text = fenced[1].trim();
|
|
142
|
+
try {
|
|
143
|
+
return JSON.parse(text);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
throw new EnrichmentContractError("draft turn did not return a parseable JSON terminal");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Normalizes warble's model-facing terminal shape (`{ enrichment_proposal:
|
|
151
|
+
* {...} }`, a single operation directly under `enrichment_proposal` for
|
|
152
|
+
* grill per draft.md's spec, or an `operations` array for a multi-operation
|
|
153
|
+
* flow) into the shape `canonicalizeProposal` (server/enrichment.ts)
|
|
154
|
+
* accepts: `{ operations: [{ sink, changeKind, summary, draft, confidence
|
|
155
|
+
* }] }`. Copies over ONLY those five fields, by name, from whichever of the
|
|
156
|
+
* model's own field names (`relative_sink`/`recommended_yaml`, this
|
|
157
|
+
* module's added `changeKind`/`summary`) or the host's own names
|
|
158
|
+
* (`sink`/`draft`) the model actually used — so a forged `hash`, `id`,
|
|
159
|
+
* `projectRevision`, or `risk` the model includes anywhere in its JSON is
|
|
160
|
+
* silently dropped here and never reaches `canonicalizeProposal` at all.
|
|
161
|
+
*/
|
|
162
|
+
export function translateDraftTerminal(finalText) {
|
|
163
|
+
const parsed = parseDraftTerminalJson(finalText);
|
|
164
|
+
const root = record(parsed);
|
|
165
|
+
const proposal = root ? record(root["enrichment_proposal"]) : undefined;
|
|
166
|
+
if (!proposal)
|
|
167
|
+
throw new EnrichmentContractError("draft turn's terminal did not contain an enrichment_proposal object");
|
|
168
|
+
const rawOperations = Array.isArray(proposal["operations"]) ? proposal["operations"] : [proposal];
|
|
169
|
+
const operations = rawOperations.map((rawOperation) => {
|
|
170
|
+
const op = record(rawOperation) ?? {};
|
|
171
|
+
return {
|
|
172
|
+
sink: op["sink"] ?? op["relative_sink"],
|
|
173
|
+
changeKind: op["changeKind"] ?? op["change_kind"],
|
|
174
|
+
summary: op["summary"],
|
|
175
|
+
draft: op["draft"] ?? op["recommended_yaml"],
|
|
176
|
+
confidence: op["confidence"],
|
|
177
|
+
};
|
|
178
|
+
});
|
|
179
|
+
return { operations };
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Builds the real, production `EnrichmentRunner.draft()`: two dispatched
|
|
183
|
+
* dispatches (`inspect_context` then `draft_enrichment`) against the bound
|
|
184
|
+
* project, folding turn 1's output into turn 2's composed question, then
|
|
185
|
+
* translating the terminal into the shape the host's own
|
|
186
|
+
* `canonicalizeProposal` independently validates and hashes. Returns
|
|
187
|
+
* `unknown`, exactly like the interface requires — this function never
|
|
188
|
+
* calls `canonicalizeProposal` itself; that stays the caller's (the `/api/
|
|
189
|
+
* context/enrichment/*` route's) job, same as every mock runner in
|
|
190
|
+
* `test/bff-enrichment.test.ts`.
|
|
191
|
+
*/
|
|
192
|
+
export function createDispatchedEnrichmentDraftRunner(options) {
|
|
193
|
+
const dispatch = options.dispatch ?? defaultDispatch(options);
|
|
194
|
+
return {
|
|
195
|
+
async draft(input) {
|
|
196
|
+
const inspectResult = await dispatch({
|
|
197
|
+
agentId: INSPECT_CONTEXT_AGENT_ID,
|
|
198
|
+
question: composeInspectPrompt(input.mode),
|
|
199
|
+
userProject: input.projectPath,
|
|
200
|
+
});
|
|
201
|
+
const draftResult = await dispatch({
|
|
202
|
+
agentId: DRAFT_ENRICHMENT_AGENT_ID,
|
|
203
|
+
question: composeDraftPrompt(input.mode, input.projectRevision, inspectResult.finalText),
|
|
204
|
+
userProject: input.projectPath,
|
|
205
|
+
});
|
|
206
|
+
return translateDraftTerminal(draftResult.finalText);
|
|
207
|
+
},
|
|
208
|
+
// Pure read of the live auth choice -- no dispatch, no cost, no side effect.
|
|
209
|
+
readiness() {
|
|
210
|
+
return draftAuthReadiness(options.getAuthChoice());
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { EnrichmentBinding, EnrichmentProposal } from "./enrichment.js";
|
|
2
|
+
/**
|
|
3
|
+
* The ladder, cheapest first. Every step before `dry_run` is local: no
|
|
4
|
+
* database, no credentials, no round trip. Ordering is the point — a proposal
|
|
5
|
+
* refuted by grammar must never reach the warehouse.
|
|
6
|
+
*
|
|
7
|
+
* `dry_run` is not optional the way that phrasing might suggest. A `new_cube`
|
|
8
|
+
* always reaches it, because nothing local resolves a cube's expressions; every
|
|
9
|
+
* other change kind is refuted or verified before it.
|
|
10
|
+
*/
|
|
11
|
+
export type VerificationStep = "sink" | "grammar" | "validate" | "build" | "dry_plan" | "dry_run";
|
|
12
|
+
export declare const VERIFICATION_LADDER: readonly VerificationStep[];
|
|
13
|
+
export interface VerificationRefutation {
|
|
14
|
+
readonly operationId: string;
|
|
15
|
+
readonly step: VerificationStep;
|
|
16
|
+
/** Readable by a person and consumable by a later repair step. Never raw source material. */
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
}
|
|
19
|
+
export type VerificationVerdict = {
|
|
20
|
+
readonly status: "verified";
|
|
21
|
+
readonly proposalHash: string;
|
|
22
|
+
readonly projectRevision: string;
|
|
23
|
+
readonly stepsRun: readonly VerificationStep[];
|
|
24
|
+
} | {
|
|
25
|
+
readonly status: "refuted";
|
|
26
|
+
readonly proposalHash: string;
|
|
27
|
+
readonly projectRevision: string;
|
|
28
|
+
readonly stepsRun: readonly VerificationStep[];
|
|
29
|
+
readonly refutation: VerificationRefutation;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The ladder could not be run at all. Deliberately distinct from `verified`:
|
|
33
|
+
* "we could not check" and "we checked and it holds" must never collapse into
|
|
34
|
+
* the same value, or an unrunnable checker silently becomes an approval.
|
|
35
|
+
*/
|
|
36
|
+
| {
|
|
37
|
+
readonly status: "unavailable";
|
|
38
|
+
readonly proposalHash: string;
|
|
39
|
+
readonly projectRevision: string;
|
|
40
|
+
readonly reason: string;
|
|
41
|
+
};
|
|
42
|
+
export interface VerifyProposalOptions {
|
|
43
|
+
/** Test seam. Defaults to running the real `wren` in the shadow directory. */
|
|
44
|
+
readonly run?: (args: readonly string[], cwd: string) => Promise<{
|
|
45
|
+
stdout: string;
|
|
46
|
+
stderr: string;
|
|
47
|
+
error: NodeJS.ErrnoException | null;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* There is deliberately no opt-out for the data-source step.
|
|
52
|
+
*
|
|
53
|
+
* An earlier version carried an `includeWarehouseDryRun` flag documented as
|
|
54
|
+
* "off by default". Once cubes had to be checked through `dry-run` — nothing
|
|
55
|
+
* local resolves their expressions — the flag stopped being read while its
|
|
56
|
+
* documentation went on promising a round trip could be avoided. An advertised
|
|
57
|
+
* safety lever that does nothing is worse than none, so it is gone.
|
|
58
|
+
*
|
|
59
|
+
* What is true, in one place: verifying a `new_cube` always reaches the data
|
|
60
|
+
* source, via `dry-run`, which parses and validates without returning rows.
|
|
61
|
+
* Every other change kind is verified entirely locally. A caller that cannot
|
|
62
|
+
* reach its source cannot verify a cube, and the honest report for that is a
|
|
63
|
+
* refutation or `unavailable` from the attempt itself — not a flag that skips
|
|
64
|
+
* the check and calls the result verified.
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Runs the ladder against a shadow copy of the bound project. Stops at the
|
|
68
|
+
* first refutation, so a proposal refuted locally never reaches the warehouse.
|
|
69
|
+
*
|
|
70
|
+
* The verdict carries the proposal hash and project revision it was earned
|
|
71
|
+
* against: a verdict must not survive onto edited content or a moved project.
|
|
72
|
+
*/
|
|
73
|
+
export declare function verifyProposal(proposal: EnrichmentProposal, binding: EnrichmentBinding, options?: VerifyProposalOptions): Promise<VerificationVerdict>;
|