@xemahq/kernel-contracts 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/decision-gate/index.d.ts +3 -0
- package/dist/decision-gate/index.d.ts.map +1 -0
- package/dist/decision-gate/index.js +19 -0
- package/dist/decision-gate/index.js.map +1 -0
- package/dist/decision-gate/lib/decision-gate.d.ts +55 -0
- package/dist/decision-gate/lib/decision-gate.d.ts.map +1 -0
- package/dist/decision-gate/lib/decision-gate.js +56 -0
- package/dist/decision-gate/lib/decision-gate.js.map +1 -0
- package/dist/decision-gate/lib/pinned-subject-artifact.d.ts +9 -0
- package/dist/decision-gate/lib/pinned-subject-artifact.d.ts.map +1 -0
- package/dist/decision-gate/lib/pinned-subject-artifact.js +11 -0
- package/dist/decision-gate/lib/pinned-subject-artifact.js.map +1 -0
- package/dist/document-patch/index.d.ts +4 -0
- package/dist/document-patch/index.d.ts.map +1 -0
- package/dist/document-patch/index.js +20 -0
- package/dist/document-patch/index.js.map +1 -0
- package/dist/document-patch/lib/patch-anchor.d.ts +7 -0
- package/dist/document-patch/lib/patch-anchor.d.ts.map +1 -0
- package/dist/document-patch/lib/patch-anchor.js +14 -0
- package/dist/document-patch/lib/patch-anchor.js.map +1 -0
- package/dist/document-patch/lib/patch-enums.d.ts +11 -0
- package/dist/document-patch/lib/patch-enums.d.ts.map +1 -0
- package/dist/document-patch/lib/patch-enums.js +16 -0
- package/dist/document-patch/lib/patch-enums.js.map +1 -0
- package/dist/document-patch/lib/pending-patch.d.ts +22 -0
- package/dist/document-patch/lib/pending-patch.d.ts.map +1 -0
- package/dist/document-patch/lib/pending-patch.js +3 -0
- package/dist/document-patch/lib/pending-patch.js.map +1 -0
- package/dist/output/index.d.ts +7 -0
- package/dist/output/index.d.ts.map +1 -0
- package/dist/output/index.js +23 -0
- package/dist/output/index.js.map +1 -0
- package/dist/output/lib/output-deliverable-expectation.d.ts +9 -0
- package/dist/output/lib/output-deliverable-expectation.d.ts.map +1 -0
- package/dist/output/lib/output-deliverable-expectation.js +3 -0
- package/dist/output/lib/output-deliverable-expectation.js.map +1 -0
- package/dist/output/lib/output-item-dto.d.ts +25 -0
- package/dist/output/lib/output-item-dto.d.ts.map +1 -0
- package/dist/output/lib/output-item-dto.js +3 -0
- package/dist/output/lib/output-item-dto.js.map +1 -0
- package/dist/output/lib/output-kind.d.ts +14 -0
- package/dist/output/lib/output-kind.d.ts.map +1 -0
- package/dist/output/lib/output-kind.js +18 -0
- package/dist/output/lib/output-kind.js.map +1 -0
- package/dist/output/lib/output-render-hint.d.ts +11 -0
- package/dist/output/lib/output-render-hint.d.ts.map +1 -0
- package/dist/output/lib/output-render-hint.js +10 -0
- package/dist/output/lib/output-render-hint.js.map +1 -0
- package/dist/output/lib/output-version-dto.d.ts +10 -0
- package/dist/output/lib/output-version-dto.d.ts.map +1 -0
- package/dist/output/lib/output-version-dto.js +3 -0
- package/dist/output/lib/output-version-dto.js.map +1 -0
- package/dist/output/lib/payload-schemas/code-diff.d.ts +7 -0
- package/dist/output/lib/payload-schemas/code-diff.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/code-diff.js +11 -0
- package/dist/output/lib/payload-schemas/code-diff.js.map +1 -0
- package/dist/output/lib/payload-schemas/decision-record.d.ts +19 -0
- package/dist/output/lib/payload-schemas/decision-record.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/decision-record.js +39 -0
- package/dist/output/lib/payload-schemas/decision-record.js.map +1 -0
- package/dist/output/lib/payload-schemas/diagram.d.ts +12 -0
- package/dist/output/lib/payload-schemas/diagram.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/diagram.js +34 -0
- package/dist/output/lib/payload-schemas/diagram.js.map +1 -0
- package/dist/output/lib/payload-schemas/external-blob.d.ts +9 -0
- package/dist/output/lib/payload-schemas/external-blob.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/external-blob.js +15 -0
- package/dist/output/lib/payload-schemas/external-blob.js.map +1 -0
- package/dist/output/lib/payload-schemas/index.d.ts +17 -0
- package/dist/output/lib/payload-schemas/index.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/index.js +94 -0
- package/dist/output/lib/payload-schemas/index.js.map +1 -0
- package/dist/output/lib/payload-schemas/json-payload.d.ts +4 -0
- package/dist/output/lib/payload-schemas/json-payload.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/json-payload.js +9 -0
- package/dist/output/lib/payload-schemas/json-payload.js.map +1 -0
- package/dist/output/lib/payload-schemas/manifest.d.ts +37 -0
- package/dist/output/lib/payload-schemas/manifest.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/manifest.js +43 -0
- package/dist/output/lib/payload-schemas/manifest.js.map +1 -0
- package/dist/output/lib/payload-schemas/markdown-doc.d.ts +8 -0
- package/dist/output/lib/payload-schemas/markdown-doc.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/markdown-doc.js +12 -0
- package/dist/output/lib/payload-schemas/markdown-doc.js.map +1 -0
- package/dist/output/lib/payload-schemas/review-findings.d.ts +30 -0
- package/dist/output/lib/payload-schemas/review-findings.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/review-findings.js +39 -0
- package/dist/output/lib/payload-schemas/review-findings.js.map +1 -0
- package/dist/output/lib/payload-schemas/schema.d.ts +4 -0
- package/dist/output/lib/payload-schemas/schema.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/schema.js +10 -0
- package/dist/output/lib/payload-schemas/schema.js.map +1 -0
- package/dist/output/lib/payload-schemas/test-report.d.ts +33 -0
- package/dist/output/lib/payload-schemas/test-report.d.ts.map +1 -0
- package/dist/output/lib/payload-schemas/test-report.js +46 -0
- package/dist/output/lib/payload-schemas/test-report.js.map +1 -0
- package/dist/question/index.d.ts +5 -0
- package/dist/question/index.d.ts.map +1 -0
- package/dist/question/index.js +21 -0
- package/dist/question/index.js.map +1 -0
- package/dist/question/lib/question-action-context.d.ts +7 -0
- package/dist/question/lib/question-action-context.d.ts.map +1 -0
- package/dist/question/lib/question-action-context.js +3 -0
- package/dist/question/lib/question-action-context.js.map +1 -0
- package/dist/question/lib/question-dto.d.ts +54 -0
- package/dist/question/lib/question-dto.d.ts.map +1 -0
- package/dist/question/lib/question-dto.js +3 -0
- package/dist/question/lib/question-dto.js.map +1 -0
- package/dist/question/lib/question-enums.d.ts +20 -0
- package/dist/question/lib/question-enums.d.ts.map +1 -0
- package/dist/question/lib/question-enums.js +32 -0
- package/dist/question/lib/question-enums.js.map +1 -0
- package/dist/question/lib/question-escalation.d.ts +8 -0
- package/dist/question/lib/question-escalation.d.ts.map +1 -0
- package/dist/question/lib/question-escalation.js +3 -0
- package/dist/question/lib/question-escalation.js.map +1 -0
- package/dist/review-inquiry/index.d.ts +3 -0
- package/dist/review-inquiry/index.d.ts.map +1 -0
- package/dist/review-inquiry/index.js +19 -0
- package/dist/review-inquiry/index.js.map +1 -0
- package/dist/review-inquiry/lib/review-inquiry.d.ts +138 -0
- package/dist/review-inquiry/lib/review-inquiry.d.ts.map +1 -0
- package/dist/review-inquiry/lib/review-inquiry.js +20 -0
- package/dist/review-inquiry/lib/review-inquiry.js.map +1 -0
- package/dist/review-inquiry/lib/web-annotation.d.ts +195 -0
- package/dist/review-inquiry/lib/web-annotation.d.ts.map +1 -0
- package/dist/review-inquiry/lib/web-annotation.js +59 -0
- package/dist/review-inquiry/lib/web-annotation.js.map +1 -0
- package/dist/run-detail/index.d.ts +7 -0
- package/dist/run-detail/index.d.ts.map +1 -0
- package/dist/run-detail/index.js +23 -0
- package/dist/run-detail/index.js.map +1 -0
- package/dist/run-detail/lib/run-detail-dto.d.ts +34 -0
- package/dist/run-detail/lib/run-detail-dto.d.ts.map +1 -0
- package/dist/run-detail/lib/run-detail-dto.js +3 -0
- package/dist/run-detail/lib/run-detail-dto.js.map +1 -0
- package/dist/run-detail/lib/run-mode.d.ts +14 -0
- package/dist/run-detail/lib/run-mode.d.ts.map +1 -0
- package/dist/run-detail/lib/run-mode.js +25 -0
- package/dist/run-detail/lib/run-mode.js.map +1 -0
- package/dist/run-detail/lib/run-outcome.d.ts +28 -0
- package/dist/run-detail/lib/run-outcome.d.ts.map +1 -0
- package/dist/run-detail/lib/run-outcome.js +27 -0
- package/dist/run-detail/lib/run-outcome.js.map +1 -0
- package/dist/run-detail/lib/run-phase-rail.d.ts +21 -0
- package/dist/run-detail/lib/run-phase-rail.d.ts.map +1 -0
- package/dist/run-detail/lib/run-phase-rail.js +14 -0
- package/dist/run-detail/lib/run-phase-rail.js.map +1 -0
- package/dist/run-detail/lib/run-revision-state.d.ts +47 -0
- package/dist/run-detail/lib/run-revision-state.d.ts.map +1 -0
- package/dist/run-detail/lib/run-revision-state.js +11 -0
- package/dist/run-detail/lib/run-revision-state.js.map +1 -0
- package/dist/run-detail/lib/wait-windows.d.ts +15 -0
- package/dist/run-detail/lib/wait-windows.d.ts.map +1 -0
- package/dist/run-detail/lib/wait-windows.js +39 -0
- package/dist/run-detail/lib/wait-windows.js.map +1 -0
- package/dist/workspace-image/index.d.ts +5 -0
- package/dist/workspace-image/index.d.ts.map +1 -0
- package/dist/workspace-image/index.js +21 -0
- package/dist/workspace-image/index.js.map +1 -0
- package/dist/workspace-image/lib/enums.d.ts +17 -0
- package/dist/workspace-image/lib/enums.d.ts.map +1 -0
- package/dist/workspace-image/lib/enums.js +22 -0
- package/dist/workspace-image/lib/enums.js.map +1 -0
- package/dist/workspace-image/lib/hash.d.ts +3 -0
- package/dist/workspace-image/lib/hash.d.ts.map +1 -0
- package/dist/workspace-image/lib/hash.js +50 -0
- package/dist/workspace-image/lib/hash.js.map +1 -0
- package/dist/workspace-image/lib/schemas.d.ts +103 -0
- package/dist/workspace-image/lib/schemas.d.ts.map +1 -0
- package/dist/workspace-image/lib/schemas.js +53 -0
- package/dist/workspace-image/lib/schemas.js.map +1 -0
- package/dist/workspace-image/lib/types.d.ts +50 -0
- package/dist/workspace-image/lib/types.d.ts.map +1 -0
- package/dist/workspace-image/lib/types.js +3 -0
- package/dist/workspace-image/lib/types.js.map +1 -0
- package/package.json +1 -1
- package/src/decision-gate/index.ts +13 -0
- package/src/decision-gate/lib/decision-gate.ts +113 -0
- package/src/decision-gate/lib/pinned-subject-artifact.ts +29 -0
- package/src/document-patch/index.ts +25 -0
- package/src/document-patch/lib/patch-anchor.ts +22 -0
- package/src/document-patch/lib/patch-enums.ts +36 -0
- package/src/document-patch/lib/pending-patch.ts +31 -0
- package/src/output/index.ts +20 -0
- package/src/output/lib/output-deliverable-expectation.ts +25 -0
- package/src/output/lib/output-item-dto.ts +54 -0
- package/src/output/lib/output-kind.ts +44 -0
- package/src/output/lib/output-render-hint.ts +28 -0
- package/src/output/lib/output-version-dto.ts +21 -0
- package/src/output/lib/payload-schemas/code-diff.ts +20 -0
- package/src/output/lib/payload-schemas/decision-record.ts +71 -0
- package/src/output/lib/payload-schemas/diagram.ts +54 -0
- package/src/output/lib/payload-schemas/external-blob.ts +36 -0
- package/src/output/lib/payload-schemas/index.ts +133 -0
- package/src/output/lib/payload-schemas/json-payload.ts +19 -0
- package/src/output/lib/payload-schemas/manifest.ts +81 -0
- package/src/output/lib/payload-schemas/markdown-doc.ts +33 -0
- package/src/output/lib/payload-schemas/review-findings.ts +75 -0
- package/src/output/lib/payload-schemas/schema.ts +22 -0
- package/src/output/lib/payload-schemas/test-report.ts +69 -0
- package/src/question/index.ts +24 -0
- package/src/question/lib/question-action-context.ts +26 -0
- package/src/question/lib/question-dto.ts +143 -0
- package/src/question/lib/question-enums.ts +67 -0
- package/src/question/lib/question-escalation.ts +22 -0
- package/src/review-inquiry/index.ts +19 -0
- package/src/review-inquiry/lib/review-inquiry.ts +76 -0
- package/src/review-inquiry/lib/web-annotation.ts +136 -0
- package/src/run-detail/index.ts +22 -0
- package/src/run-detail/lib/run-detail-dto.ts +84 -0
- package/src/run-detail/lib/run-mode.ts +65 -0
- package/src/run-detail/lib/run-outcome.ts +66 -0
- package/src/run-detail/lib/run-phase-rail.ts +43 -0
- package/src/run-detail/lib/run-revision-state.ts +83 -0
- package/src/run-detail/lib/wait-windows.ts +70 -0
- package/src/workspace-image/index.ts +13 -0
- package/src/workspace-image/lib/enums.ts +38 -0
- package/src/workspace-image/lib/hash.ts +95 -0
- package/src/workspace-image/lib/schemas.ts +63 -0
- package/src/workspace-image/lib/types.ts +79 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLOSED set of output renderer kinds. Adding a new kind:
|
|
3
|
+
*
|
|
4
|
+
* 1. Extend this enum.
|
|
5
|
+
* 2. Register a renderer component in the FE renderer-registry.
|
|
6
|
+
* 3. CI fails until both are done (xema-fe/output-renderer-coverage
|
|
7
|
+
* lints the registry against this enum).
|
|
8
|
+
*
|
|
9
|
+
* No "unknown" fallback that silently dumps JSON — `UNKNOWN` is rendered
|
|
10
|
+
* by an explicit "we don't have a renderer for this yet" component
|
|
11
|
+
* with a "Show raw" toggle. Producers must NEVER emit `UNKNOWN` for a
|
|
12
|
+
* kind that has a real renderer; the engine refuses to materialize an
|
|
13
|
+
* output with `UNKNOWN` if the producer can derive a real kind from
|
|
14
|
+
* the deliverable spec.
|
|
15
|
+
*/
|
|
16
|
+
export enum OutputKind {
|
|
17
|
+
/** Markdown document — renders with TOC, code blocks, diagrams. */
|
|
18
|
+
MARKDOWN_DOC = 'markdown_doc',
|
|
19
|
+
/** Code diff — renders with side-by-side or unified view. */
|
|
20
|
+
CODE_DIFF = 'code_diff',
|
|
21
|
+
/** Architectural Decision Record — renders with status + decision context. */
|
|
22
|
+
DECISION_RECORD = 'decision_record',
|
|
23
|
+
/** Findings list from a reviewer agent — renders as severity-grouped table. */
|
|
24
|
+
REVIEW_FINDINGS = 'review_findings',
|
|
25
|
+
/** JSON Schema — renders as type tree with examples. */
|
|
26
|
+
SCHEMA = 'schema',
|
|
27
|
+
/** Manifest (workflow YAML, biome manifest, etc.) — renders as structured form. */
|
|
28
|
+
MANIFEST = 'manifest',
|
|
29
|
+
/** Test report — renders pass/fail summary + failing-case detail. */
|
|
30
|
+
TEST_REPORT = 'test_report',
|
|
31
|
+
/** Diagram (mermaid, drawio, etc.) — renders as SVG. */
|
|
32
|
+
DIAGRAM = 'diagram',
|
|
33
|
+
/**
|
|
34
|
+
* Generic structured JSON payload — used when the value IS the JSON
|
|
35
|
+
* envelope itself (e.g. `xema/http` / `xema/endpoint-fetch` results,
|
|
36
|
+
* or any producer emitting a free-form structured object that
|
|
37
|
+
* doesn't map onto a more specific kind). Rendered as a JSON tree.
|
|
38
|
+
*/
|
|
39
|
+
JSON_PAYLOAD = 'json_payload',
|
|
40
|
+
/** External blob (image, binary, etc.) — renders as preview + download. */
|
|
41
|
+
EXTERNAL_BLOB = 'external_blob',
|
|
42
|
+
/** Fallback for outputs without a typed renderer. Renders "no renderer" notice. */
|
|
43
|
+
UNKNOWN = 'unknown',
|
|
44
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-kind rendering hint the engine attaches to an output. Optional —
|
|
3
|
+
* the renderer has sensible defaults — but lets producers steer
|
|
4
|
+
* presentation without freeform CSS.
|
|
5
|
+
*
|
|
6
|
+
* Closed enum so the renderer registry knows the full hint surface.
|
|
7
|
+
*/
|
|
8
|
+
export enum OutputRenderDensity {
|
|
9
|
+
COMPACT = 'compact',
|
|
10
|
+
COMFORTABLE = 'comfortable',
|
|
11
|
+
FULL = 'full',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface OutputRenderHint {
|
|
15
|
+
readonly density: OutputRenderDensity;
|
|
16
|
+
/**
|
|
17
|
+
* When true, the renderer expands inline by default (no click).
|
|
18
|
+
* When false, the renderer shows a one-line summary card and
|
|
19
|
+
* expands on click.
|
|
20
|
+
*/
|
|
21
|
+
readonly expandByDefault: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Optional preferred starting tab when the renderer has multiple
|
|
24
|
+
* tabs (e.g. code-diff: "unified" vs "split"). The renderer
|
|
25
|
+
* validates this against its known tab set.
|
|
26
|
+
*/
|
|
27
|
+
readonly preferredTab: string | null;
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One row in the version history of an output. The Outputs panel
|
|
3
|
+
* renders a dropdown when `versions.length > 1`; clicking a non-current
|
|
4
|
+
* version navigates to the inline VersionCompare view (NOT a drawer).
|
|
5
|
+
*
|
|
6
|
+
*: per-version metadata lives
|
|
7
|
+
* on `ArtifactVersion`. The engine populates this DTO from there.
|
|
8
|
+
* Consumers MUST NOT trust `OutputItemDto.title` for historical
|
|
9
|
+
* versions — read this row's `title` field instead.
|
|
10
|
+
*/
|
|
11
|
+
export interface OutputVersionDto {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly version: number;
|
|
14
|
+
readonly title: string;
|
|
15
|
+
readonly hash: string;
|
|
16
|
+
readonly createdAt: string;
|
|
17
|
+
/** Slug of the agent that produced this version. `null` for non-agent producers. */
|
|
18
|
+
readonly producerAgentSlug: string | null;
|
|
19
|
+
/** True when this row is the latest version. Exactly one row has this set. */
|
|
20
|
+
readonly isCurrent: boolean;
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Payload shape for `OutputKind.CODE_DIFF` artifacts — unified-diff
|
|
5
|
+
* text produced by SCM-integration adapters and code-reviewing agents.
|
|
6
|
+
*
|
|
7
|
+
* The convention is a single `body` string carrying the diff in standard
|
|
8
|
+
* unified-diff format. The FE renders it through Monaco's diff-aware
|
|
9
|
+
* tokenizer (`language: 'diff'`) so additions/removals get syntax
|
|
10
|
+
* highlighting.
|
|
11
|
+
*/
|
|
12
|
+
export const CodeDiffPayloadSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
body: z.string().min(1, 'code_diff.body must be non-empty'),
|
|
15
|
+
/** Optional: human-readable label for the change (e.g. "Refactor auth flow"). */
|
|
16
|
+
title: z.string().optional(),
|
|
17
|
+
})
|
|
18
|
+
.passthrough();
|
|
19
|
+
|
|
20
|
+
export type CodeDiffPayload = z.infer<typeof CodeDiffPayloadSchema>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Architectural Decision Record (ADR) status — RFC-style lifecycle.
|
|
5
|
+
*
|
|
6
|
+
* Closed enum so the FE can render distinctive pills per state
|
|
7
|
+
* (`accepted` green, `superseded` strikethrough, etc.). Producers
|
|
8
|
+
* MUST pick one; freeform strings are rejected so we don't grow a
|
|
9
|
+
* long tail of bespoke statuses.
|
|
10
|
+
*/
|
|
11
|
+
export enum DecisionRecordStatus {
|
|
12
|
+
PROPOSED = 'proposed',
|
|
13
|
+
ACCEPTED = 'accepted',
|
|
14
|
+
REJECTED = 'rejected',
|
|
15
|
+
DEPRECATED = 'deprecated',
|
|
16
|
+
SUPERSEDED = 'superseded',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const DecisionRecordStatusSchema = z.nativeEnum(DecisionRecordStatus);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Payload shape for `OutputKind.DECISION_RECORD` artifacts.
|
|
23
|
+
*
|
|
24
|
+
* Follows the Michael Nygard ADR template — title, status, context,
|
|
25
|
+
* decision, consequences. Each field is markdown so the FE renderer
|
|
26
|
+
* can present them as separate sections with appropriate framing
|
|
27
|
+
* (status pill, headings, etc.).
|
|
28
|
+
*
|
|
29
|
+
* Backward-compat: producers that pre-date this schema emit a single
|
|
30
|
+
* `body` markdown string (legacy convention shared across all
|
|
31
|
+
* markdown-bearing kinds via `textViewOfPayload`). The schema
|
|
32
|
+
* tolerates that by making every structured field optional and
|
|
33
|
+
* requiring at-least-one-of via `superRefine`. New producers should
|
|
34
|
+
* emit the structured fields so the renderer's rich form lights up.
|
|
35
|
+
*/
|
|
36
|
+
export const DecisionRecordPayloadSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
title: z.string().optional(),
|
|
39
|
+
status: DecisionRecordStatusSchema.optional(),
|
|
40
|
+
context: z.string().optional(),
|
|
41
|
+
decision: z.string().optional(),
|
|
42
|
+
consequences: z.string().optional(),
|
|
43
|
+
/**
|
|
44
|
+
* Legacy / fallback: a single markdown document holding the whole
|
|
45
|
+
* ADR. New producers SHOULD prefer the structured fields; this
|
|
46
|
+
* stays for backward-compatibility and for cases where the ADR
|
|
47
|
+
* doesn't map cleanly onto the four-section template.
|
|
48
|
+
*/
|
|
49
|
+
body: z.string().optional(),
|
|
50
|
+
})
|
|
51
|
+
.passthrough()
|
|
52
|
+
.superRefine((value, ctx) => {
|
|
53
|
+
const structuredFields = [
|
|
54
|
+
value.context,
|
|
55
|
+
value.decision,
|
|
56
|
+
value.consequences,
|
|
57
|
+
];
|
|
58
|
+
const hasStructured = structuredFields.some(
|
|
59
|
+
(v) => typeof v === 'string' && v.trim().length > 0,
|
|
60
|
+
);
|
|
61
|
+
const hasBody = typeof value.body === 'string' && value.body.trim().length > 0;
|
|
62
|
+
if (!hasStructured && !hasBody) {
|
|
63
|
+
ctx.addIssue({
|
|
64
|
+
code: 'custom',
|
|
65
|
+
message:
|
|
66
|
+
'decision_record payload must include at least one of `body` or the structured fields (`context`, `decision`, `consequences`).',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export type DecisionRecordPayload = z.infer<typeof DecisionRecordPayloadSchema>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Diagram-dialect enum. Closed today on `mermaid` only — the FE
|
|
5
|
+
* renderer pipeline can ingest mermaid via the existing
|
|
6
|
+
* `MarkdownView` mermaid block. Add new values here when a new
|
|
7
|
+
* dialect (drawio, plantuml, …) has a renderer wired.
|
|
8
|
+
*/
|
|
9
|
+
export enum DiagramDialect {
|
|
10
|
+
MERMAID = 'mermaid',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const DiagramDialectSchema = z.nativeEnum(DiagramDialect);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Payload shape for `OutputKind.DIAGRAM` artifacts — standalone
|
|
17
|
+
* diagrams emitted by architecture / requirements agents.
|
|
18
|
+
*
|
|
19
|
+
* Two valid shapes (mirroring how `xema/emit-artifact` producers
|
|
20
|
+
* actually emit today):
|
|
21
|
+
*
|
|
22
|
+
* 1. Inline source: `{ type: 'mermaid', source: '<mermaid src>' }`.
|
|
23
|
+
* 2. Markdown fallback: `{ body: '...mermaid block...' }` — when
|
|
24
|
+
* the producer wrapped a mermaid fence in a markdown narrative.
|
|
25
|
+
*
|
|
26
|
+
* The FE `DiagramRenderer` reads `source` when present, else falls
|
|
27
|
+
* through to markdown rendering which itself supports mermaid.
|
|
28
|
+
*/
|
|
29
|
+
export const DiagramPayloadSchema = z
|
|
30
|
+
.object({
|
|
31
|
+
type: DiagramDialectSchema.optional(),
|
|
32
|
+
source: z.string().optional(),
|
|
33
|
+
body: z.string().optional(),
|
|
34
|
+
})
|
|
35
|
+
.passthrough()
|
|
36
|
+
.superRefine((value, ctx) => {
|
|
37
|
+
const hasSource = typeof value.source === 'string' && value.source.trim().length > 0;
|
|
38
|
+
const hasBody = typeof value.body === 'string' && value.body.trim().length > 0;
|
|
39
|
+
if (!hasSource && !hasBody) {
|
|
40
|
+
ctx.addIssue({
|
|
41
|
+
code: 'custom',
|
|
42
|
+
message: 'diagram payload must include either `source` or `body`.',
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (hasSource && value.type === undefined) {
|
|
46
|
+
ctx.addIssue({
|
|
47
|
+
code: 'custom',
|
|
48
|
+
path: ['type'],
|
|
49
|
+
message: 'diagram payload with `source` must declare `type` (e.g. `mermaid`).',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export type DiagramPayload = z.infer<typeof DiagramPayloadSchema>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Payload shape for `OutputKind.EXTERNAL_BLOB` artifacts — images,
|
|
5
|
+
* PDFs, archives, and other binary content stored out-of-band in
|
|
6
|
+
* MinIO / S3.
|
|
7
|
+
*
|
|
8
|
+
* The `payload` itself is metadata about the external bytes. The
|
|
9
|
+
* actual bytes live behind `ArtifactVersion.pointer` (durable
|
|
10
|
+
* storage URI) and are streamed via the artifact-store's
|
|
11
|
+
* version-content endpoint, NOT carried inline.
|
|
12
|
+
*
|
|
13
|
+
* `contentType` (IANA media type) is required so the FE renderer
|
|
14
|
+
* can branch on preview mode (image / pdf / video / download).
|
|
15
|
+
* `size` is informational. `originalFilename` flows into the
|
|
16
|
+
* download affordance when present.
|
|
17
|
+
*/
|
|
18
|
+
export const ExternalBlobPayloadSchema = z
|
|
19
|
+
.object({
|
|
20
|
+
contentType: z
|
|
21
|
+
.string()
|
|
22
|
+
.min(1, 'external_blob.contentType must be a non-empty IANA media type'),
|
|
23
|
+
/** Byte count, when known. Producers without it may omit. */
|
|
24
|
+
size: z.number().nonnegative().int().optional(),
|
|
25
|
+
/** Original filename, used as the download attachment name. */
|
|
26
|
+
originalFilename: z.string().optional(),
|
|
27
|
+
/**
|
|
28
|
+
* Producer-supplied alt text for image-kind blobs (a11y) and
|
|
29
|
+
* for any future LLM-briefing path that needs a non-visual
|
|
30
|
+
* description.
|
|
31
|
+
*/
|
|
32
|
+
altText: z.string().optional(),
|
|
33
|
+
})
|
|
34
|
+
.passthrough();
|
|
35
|
+
|
|
36
|
+
export type ExternalBlobPayload = z.infer<typeof ExternalBlobPayloadSchema>;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { ZodTypeAny } from 'zod';
|
|
2
|
+
|
|
3
|
+
import { CodeDiffPayloadSchema } from './code-diff';
|
|
4
|
+
import { DecisionRecordPayloadSchema } from './decision-record';
|
|
5
|
+
import { DiagramPayloadSchema } from './diagram';
|
|
6
|
+
import { ExternalBlobPayloadSchema } from './external-blob';
|
|
7
|
+
import { JsonPayloadPayloadSchema } from './json-payload';
|
|
8
|
+
import { ManifestPayloadSchema } from './manifest';
|
|
9
|
+
import { MarkdownDocPayloadSchema } from './markdown-doc';
|
|
10
|
+
import { ReviewFindingsPayloadSchema } from './review-findings';
|
|
11
|
+
import { JsonSchemaPayloadSchema } from './schema';
|
|
12
|
+
import { TestReportPayloadSchema } from './test-report';
|
|
13
|
+
|
|
14
|
+
import { OutputKind } from '../output-kind';
|
|
15
|
+
|
|
16
|
+
export * from './code-diff';
|
|
17
|
+
export * from './decision-record';
|
|
18
|
+
export * from './diagram';
|
|
19
|
+
export * from './external-blob';
|
|
20
|
+
export * from './json-payload';
|
|
21
|
+
export * from './manifest';
|
|
22
|
+
export * from './markdown-doc';
|
|
23
|
+
export * from './review-findings';
|
|
24
|
+
export * from './schema';
|
|
25
|
+
export * from './test-report';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Registry mapping closed `OutputKind` → Zod schema for the matching
|
|
29
|
+
* artifact payload. Every kind that has a renderer also has a schema;
|
|
30
|
+
* `OutputKind.UNKNOWN` is intentionally absent — biome-supplied
|
|
31
|
+
* payloads we can't classify are NOT validated (they pass through to
|
|
32
|
+
* the `unknown` renderer's "Show raw" surface).
|
|
33
|
+
*
|
|
34
|
+
* Keeping the registry keyed on `OutputKind` rather than free-form
|
|
35
|
+
* `type` strings means: the `(type → OutputKind)` mapping is the single
|
|
36
|
+
* place biomes add new aliases; once a producer's `type` resolves to
|
|
37
|
+
* a known kind, validation kicks in automatically.
|
|
38
|
+
*/
|
|
39
|
+
export const OUTPUT_KIND_PAYLOAD_SCHEMAS: Readonly<
|
|
40
|
+
Partial<Record<OutputKind, ZodTypeAny>>
|
|
41
|
+
> = {
|
|
42
|
+
[OutputKind.MARKDOWN_DOC]: MarkdownDocPayloadSchema,
|
|
43
|
+
[OutputKind.CODE_DIFF]: CodeDiffPayloadSchema,
|
|
44
|
+
[OutputKind.DECISION_RECORD]: DecisionRecordPayloadSchema,
|
|
45
|
+
[OutputKind.REVIEW_FINDINGS]: ReviewFindingsPayloadSchema,
|
|
46
|
+
[OutputKind.SCHEMA]: JsonSchemaPayloadSchema,
|
|
47
|
+
[OutputKind.MANIFEST]: ManifestPayloadSchema,
|
|
48
|
+
[OutputKind.TEST_REPORT]: TestReportPayloadSchema,
|
|
49
|
+
[OutputKind.DIAGRAM]: DiagramPayloadSchema,
|
|
50
|
+
[OutputKind.JSON_PAYLOAD]: JsonPayloadPayloadSchema,
|
|
51
|
+
[OutputKind.EXTERNAL_BLOB]: ExternalBlobPayloadSchema,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Closed mapping from producer-supplied `type` string (the
|
|
56
|
+
* `EmitArtifactDto.type` value) → `OutputKind` enum. This is the
|
|
57
|
+
* platform's authoritative `type → kind` table; the FE and BE both
|
|
58
|
+
* read from here. Biomes that ship new aliases for an existing kind
|
|
59
|
+
* extend this map via a biome-host extension point (future) or
|
|
60
|
+
* register a new OutputKind (kernel-level).
|
|
61
|
+
*
|
|
62
|
+
* Order is irrelevant — duplicate keys would be a build-time error
|
|
63
|
+
* in TS, and the map is frozen at module load.
|
|
64
|
+
*/
|
|
65
|
+
export const ARTIFACT_TYPE_TO_OUTPUT_KIND: Readonly<Record<string, OutputKind>> = {
|
|
66
|
+
// markdown_doc
|
|
67
|
+
document_page: OutputKind.MARKDOWN_DOC,
|
|
68
|
+
'markdown.doc': OutputKind.MARKDOWN_DOC,
|
|
69
|
+
'doc.markdown': OutputKind.MARKDOWN_DOC,
|
|
70
|
+
'requirements.doc': OutputKind.MARKDOWN_DOC,
|
|
71
|
+
'design.doc': OutputKind.MARKDOWN_DOC,
|
|
72
|
+
'spec.doc': OutputKind.MARKDOWN_DOC,
|
|
73
|
+
// code_diff
|
|
74
|
+
'code.diff': OutputKind.CODE_DIFF,
|
|
75
|
+
'src.diff': OutputKind.CODE_DIFF,
|
|
76
|
+
'patch.diff': OutputKind.CODE_DIFF,
|
|
77
|
+
// decision_record
|
|
78
|
+
'decision.record': OutputKind.DECISION_RECORD,
|
|
79
|
+
adr: OutputKind.DECISION_RECORD,
|
|
80
|
+
// review_findings
|
|
81
|
+
'review.findings': OutputKind.REVIEW_FINDINGS,
|
|
82
|
+
'review.report': OutputKind.REVIEW_FINDINGS,
|
|
83
|
+
'review.verdict': OutputKind.REVIEW_FINDINGS,
|
|
84
|
+
// schema
|
|
85
|
+
schema: OutputKind.SCHEMA,
|
|
86
|
+
'json.schema': OutputKind.SCHEMA,
|
|
87
|
+
// manifest
|
|
88
|
+
manifest: OutputKind.MANIFEST,
|
|
89
|
+
'workflow.manifest': OutputKind.MANIFEST,
|
|
90
|
+
'biome.manifest': OutputKind.MANIFEST,
|
|
91
|
+
// test_report
|
|
92
|
+
'test.report': OutputKind.TEST_REPORT,
|
|
93
|
+
'qa.report': OutputKind.TEST_REPORT,
|
|
94
|
+
// diagram
|
|
95
|
+
diagram: OutputKind.DIAGRAM,
|
|
96
|
+
mermaid: OutputKind.DIAGRAM,
|
|
97
|
+
// json_payload
|
|
98
|
+
endpoint_fetch_response: OutputKind.JSON_PAYLOAD,
|
|
99
|
+
structured_json: OutputKind.JSON_PAYLOAD,
|
|
100
|
+
'json.payload': OutputKind.JSON_PAYLOAD,
|
|
101
|
+
// external_blob
|
|
102
|
+
'image.png': OutputKind.EXTERNAL_BLOB,
|
|
103
|
+
'image.jpeg': OutputKind.EXTERNAL_BLOB,
|
|
104
|
+
'binary.blob': OutputKind.EXTERNAL_BLOB,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Resolve a producer-supplied `type` to the matching `OutputKind`.
|
|
109
|
+
* Returns `undefined` when no mapping exists — callers treat that as
|
|
110
|
+
* "biome-defined custom type" and skip schema validation, falling
|
|
111
|
+
* through to the `unknown` renderer downstream.
|
|
112
|
+
*/
|
|
113
|
+
export function outputKindForType(type: string): OutputKind | undefined {
|
|
114
|
+
return ARTIFACT_TYPE_TO_OUTPUT_KIND[type];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Resolve the Zod payload schema for a given `type` string, going
|
|
119
|
+
* through the `type → OutputKind → schema` chain. Returns
|
|
120
|
+
* `undefined` when the `type` is unknown OR when the kind has no
|
|
121
|
+
* registered schema (today only `OutputKind.UNKNOWN`).
|
|
122
|
+
*
|
|
123
|
+
* Callers (artifact-store-api's `EmitArtifactValidator`,
|
|
124
|
+
* future FE preview helpers) treat `undefined` as "pass through —
|
|
125
|
+
* no schema-level validation for this type". Biome extensibility is
|
|
126
|
+
* preserved: a custom `my-org.special-output` type that's not in the
|
|
127
|
+
* table simply isn't validated, exactly as today.
|
|
128
|
+
*/
|
|
129
|
+
export function payloadSchemaForType(type: string): ZodTypeAny | undefined {
|
|
130
|
+
const kind = outputKindForType(type);
|
|
131
|
+
if (kind === undefined) {return undefined;}
|
|
132
|
+
return OUTPUT_KIND_PAYLOAD_SCHEMAS[kind];
|
|
133
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Payload shape for `OutputKind.JSON_PAYLOAD` artifacts — the
|
|
5
|
+
* deliberate "structured JSON without a more specific kind" bucket.
|
|
6
|
+
* Used today by `xema/http`, `xema/endpoint-fetch`, and any producer
|
|
7
|
+
* emitting an opaque JSON envelope.
|
|
8
|
+
*
|
|
9
|
+
* Permissive by design — the WHOLE payload IS the deliverable, no
|
|
10
|
+
* particular field is required. Validation just ensures it's an
|
|
11
|
+
* object (not a bare primitive); arrays masquerading as the root are
|
|
12
|
+
* also accepted via the union below.
|
|
13
|
+
*/
|
|
14
|
+
export const JsonPayloadPayloadSchema = z.union([
|
|
15
|
+
z.record(z.string(), z.unknown()),
|
|
16
|
+
z.array(z.unknown()),
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export type JsonPayloadPayload = z.infer<typeof JsonPayloadPayloadSchema>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One reference inside a manifest's `refs[]` — a pointer to a KB page,
|
|
5
|
+
* a backlog item, an emitted file, or any other tracked artifact the
|
|
6
|
+
* manifest summarises.
|
|
7
|
+
*/
|
|
8
|
+
export const ManifestRefSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
/** Closed-ish set of ref kinds; producers may extend via .passthrough(). */
|
|
11
|
+
type: z.string().min(1),
|
|
12
|
+
id: z.string().min(1),
|
|
13
|
+
title: z.string().optional(),
|
|
14
|
+
/** Producer-defined verb describing what happened to the ref (created / modified / referenced / …). */
|
|
15
|
+
action: z.string().optional(),
|
|
16
|
+
/** File-system path for `file`-kind refs. */
|
|
17
|
+
path: z.string().optional(),
|
|
18
|
+
})
|
|
19
|
+
.passthrough();
|
|
20
|
+
|
|
21
|
+
export type ManifestRef = z.infer<typeof ManifestRefSchema>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* An inline diagram embedded in the manifest. Today only `mermaid`
|
|
25
|
+
* is supported; the FE renders via the existing mermaid pipeline in
|
|
26
|
+
* `MarkdownView`.
|
|
27
|
+
*/
|
|
28
|
+
export const ManifestDiagramSchema = z
|
|
29
|
+
.object({
|
|
30
|
+
key: z.string().min(1),
|
|
31
|
+
title: z.string().min(1),
|
|
32
|
+
type: z.literal('mermaid'),
|
|
33
|
+
source: z.string().min(1),
|
|
34
|
+
})
|
|
35
|
+
.passthrough();
|
|
36
|
+
|
|
37
|
+
export type ManifestDiagram = z.infer<typeof ManifestDiagramSchema>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Payload shape for `OutputKind.MANIFEST` artifacts — phase summaries,
|
|
41
|
+
* workflow manifests, biome manifests, and any structured "summary
|
|
42
|
+
* with cross-references" document.
|
|
43
|
+
*
|
|
44
|
+
* Two render shapes the FE recognises:
|
|
45
|
+
*
|
|
46
|
+
* 1. Rich manifest: `{ schemaVersion, summary, refs[]?, diagrams[]? }`.
|
|
47
|
+
* The FE renderer (`ManifestRenderer`, plus the legacy
|
|
48
|
+
* `ArtifactContentViewer`) renders the summary as markdown with
|
|
49
|
+
* phase + ref + diagram sidebars.
|
|
50
|
+
* 2. Plain YAML/JSON: `{ body: string }`. The renderer falls back
|
|
51
|
+
* to monospaced text preserving indentation.
|
|
52
|
+
*
|
|
53
|
+
* `passthrough()` so the `schemaVersion` field — which is a producer-
|
|
54
|
+
* declared manifest version, distinct from the artifact-store's
|
|
55
|
+
* `EmitArtifactDto.schemaVersion` — flows through.
|
|
56
|
+
*/
|
|
57
|
+
export const ManifestPayloadSchema = z
|
|
58
|
+
.object({
|
|
59
|
+
schemaVersion: z.string().optional(),
|
|
60
|
+
summary: z.string().optional(),
|
|
61
|
+
refs: z.array(ManifestRefSchema).optional(),
|
|
62
|
+
diagrams: z.array(ManifestDiagramSchema).optional(),
|
|
63
|
+
body: z.string().optional(),
|
|
64
|
+
stageKey: z.string().optional(),
|
|
65
|
+
})
|
|
66
|
+
.passthrough()
|
|
67
|
+
.superRefine((value, ctx) => {
|
|
68
|
+
const hasSummary =
|
|
69
|
+
typeof value.summary === 'string' && value.summary.trim().length > 0;
|
|
70
|
+
const hasBody = typeof value.body === 'string' && value.body.trim().length > 0;
|
|
71
|
+
const hasRefs = Array.isArray(value.refs) && value.refs.length > 0;
|
|
72
|
+
if (!hasSummary && !hasBody && !hasRefs) {
|
|
73
|
+
ctx.addIssue({
|
|
74
|
+
code: 'custom',
|
|
75
|
+
message:
|
|
76
|
+
'manifest payload must include at least one of `summary`, `body`, or non-empty `refs[]`.',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export type ManifestPayload = z.infer<typeof ManifestPayloadSchema>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Payload shape for `OutputKind.MARKDOWN_DOC` artifacts.
|
|
5
|
+
*
|
|
6
|
+
* The canonical document-page shape across the platform. Used by the
|
|
7
|
+
* deliverable harvester (one artifact per page), `xema/emit-artifact`
|
|
8
|
+
* with markdown content, requirements/design/spec agents, and KB-bound
|
|
9
|
+
* publications.
|
|
10
|
+
*
|
|
11
|
+
* `body` is the rendered narrative — markdown source. The FE renderer
|
|
12
|
+
* (`MarkdownDocRenderer`) reads `body` directly via
|
|
13
|
+
* `useArtifactContent.textViewOfPayload` and renders it through
|
|
14
|
+
* `MarkdownView` (react-markdown + remark-gfm + mermaid).
|
|
15
|
+
*
|
|
16
|
+
* `slug` and `parentSlug` are KB-publish hints; the publish-kb activity
|
|
17
|
+
* reads them when present, otherwise it derives slugs from the
|
|
18
|
+
* artifact's title + phase. They are NOT required at emit-time — a
|
|
19
|
+
* deliverable that's reviewed but never published has no slug.
|
|
20
|
+
*
|
|
21
|
+
* `.passthrough()` is intentional: producers may attach arbitrary
|
|
22
|
+
* extras (e.g. front-matter metadata, agent commentary) without the
|
|
23
|
+
* schema rejecting the emit.
|
|
24
|
+
*/
|
|
25
|
+
export const MarkdownDocPayloadSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
body: z.string().min(1, 'markdown_doc.body must be non-empty'),
|
|
28
|
+
slug: z.string().optional(),
|
|
29
|
+
parentSlug: z.string().optional(),
|
|
30
|
+
})
|
|
31
|
+
.passthrough();
|
|
32
|
+
|
|
33
|
+
export type MarkdownDocPayload = z.infer<typeof MarkdownDocPayloadSchema>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Closed severity enum for `ReviewFinding.severity`. Drives FE
|
|
5
|
+
* grouping + colouring in `ReviewFindingsRenderer`. `info` is
|
|
6
|
+
* commentary that doesn't gate a verdict; `minor` / `major` /
|
|
7
|
+
* `blocking` escalate.
|
|
8
|
+
*/
|
|
9
|
+
export enum ReviewFindingSeverity {
|
|
10
|
+
INFO = 'info',
|
|
11
|
+
MINOR = 'minor',
|
|
12
|
+
MAJOR = 'major',
|
|
13
|
+
BLOCKING = 'blocking',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const ReviewFindingSeveritySchema = z.nativeEnum(ReviewFindingSeverity);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A single finding inside a review-findings payload.
|
|
20
|
+
*
|
|
21
|
+
* `anchor` is a free-form string today (pre-W3C-anchor migration on
|
|
22
|
+
* REVIEW inquiries). Producers conventionally use shapes like
|
|
23
|
+
* `file:path:line` or `heading:slug`. A future tightening could
|
|
24
|
+
* promote this to a `WebAnnotationTarget` once the producer fleet
|
|
25
|
+
* is migrated, matching the inquiry-side anchor work.
|
|
26
|
+
*/
|
|
27
|
+
export const ReviewFindingSchema = z
|
|
28
|
+
.object({
|
|
29
|
+
severity: ReviewFindingSeveritySchema,
|
|
30
|
+
message: z.string().min(1, 'review_findings.findings[].message must be non-empty'),
|
|
31
|
+
anchor: z.string().optional(),
|
|
32
|
+
})
|
|
33
|
+
.passthrough();
|
|
34
|
+
|
|
35
|
+
export type ReviewFinding = z.infer<typeof ReviewFindingSchema>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Payload shape for `OutputKind.REVIEW_FINDINGS` artifacts — emitted
|
|
39
|
+
* by reviewer agents inside `xema/review` iterations.
|
|
40
|
+
*
|
|
41
|
+
* Two valid shapes (the FE renderer detects both):
|
|
42
|
+
*
|
|
43
|
+
* 1. Structured: `findings: ReviewFinding[]` — preferred. Renders
|
|
44
|
+
* as a severity-grouped table with anchors.
|
|
45
|
+
* 2. Legacy: `body: string` — markdown narrative of the review.
|
|
46
|
+
* The renderer falls back to markdown rendering when `findings`
|
|
47
|
+
* is absent.
|
|
48
|
+
*
|
|
49
|
+
* `verdict` + `summary` are optional rollups — the reviewer's
|
|
50
|
+
* top-line answer and a short paragraph framing the detailed
|
|
51
|
+
* findings.
|
|
52
|
+
*/
|
|
53
|
+
export const ReviewFindingsPayloadSchema = z
|
|
54
|
+
.object({
|
|
55
|
+
findings: z.array(ReviewFindingSchema).optional(),
|
|
56
|
+
verdict: z.enum(['approve', 'reject', 'abstain']).optional(),
|
|
57
|
+
summary: z.string().optional(),
|
|
58
|
+
body: z.string().optional(),
|
|
59
|
+
})
|
|
60
|
+
.passthrough()
|
|
61
|
+
.superRefine((value, ctx) => {
|
|
62
|
+
const hasFindings = Array.isArray(value.findings) && value.findings.length > 0;
|
|
63
|
+
const hasBody = typeof value.body === 'string' && value.body.trim().length > 0;
|
|
64
|
+
const hasSummary =
|
|
65
|
+
typeof value.summary === 'string' && value.summary.trim().length > 0;
|
|
66
|
+
if (!hasFindings && !hasBody && !hasSummary) {
|
|
67
|
+
ctx.addIssue({
|
|
68
|
+
code: 'custom',
|
|
69
|
+
message:
|
|
70
|
+
'review_findings payload must include at least one of `findings[]`, `summary`, or `body`.',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export type ReviewFindingsPayload = z.infer<typeof ReviewFindingsPayloadSchema>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Payload shape for `OutputKind.SCHEMA` artifacts — JSON Schema
|
|
5
|
+
* documents declared by agents.
|
|
6
|
+
*
|
|
7
|
+
* The payload IS the JSON Schema document. We don't dictate which
|
|
8
|
+
* dialect (Draft 07, 2020-12, OpenAPI) — the validator we use
|
|
9
|
+
* downstream picks based on the document's own `$schema` field.
|
|
10
|
+
* Minimum check: it must be a non-empty object.
|
|
11
|
+
*
|
|
12
|
+
* The FE `SchemaRenderer` reads the payload directly via
|
|
13
|
+
* `useArtifactContent.payload` (NOT `content`) and renders the
|
|
14
|
+
* schema as a typed tree.
|
|
15
|
+
*/
|
|
16
|
+
export const JsonSchemaPayloadSchema = z
|
|
17
|
+
.record(z.string(), z.unknown())
|
|
18
|
+
.refine((v) => Object.keys(v).length > 0, {
|
|
19
|
+
message: 'schema payload must be a non-empty JSON Schema document.',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export type JsonSchemaPayload = z.infer<typeof JsonSchemaPayloadSchema>;
|