voratiq 0.1.0-beta.20 → 0.1.0-beta.21

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.
Files changed (85) hide show
  1. package/dist/agents/runtime/policy.d.ts +1 -1
  2. package/dist/bin.js +50 -19
  3. package/dist/cli/contract.d.ts +35 -5
  4. package/dist/cli/contract.js +42 -5
  5. package/dist/cli/list.js +4 -1
  6. package/dist/cli/message.d.ts +28 -0
  7. package/dist/cli/message.js +147 -0
  8. package/dist/cli/operator-envelope.d.ts +22 -1
  9. package/dist/cli/operator-envelope.js +48 -3
  10. package/dist/cli/reduce.js +5 -2
  11. package/dist/cli/verify.js +6 -2
  12. package/dist/commands/list/command.d.ts +1 -0
  13. package/dist/commands/list/command.js +117 -7
  14. package/dist/commands/message/command.d.ts +23 -0
  15. package/dist/commands/message/command.js +215 -0
  16. package/dist/commands/message/errors.d.ts +9 -0
  17. package/dist/commands/message/errors.js +20 -0
  18. package/dist/commands/message/lifecycle.d.ts +14 -0
  19. package/dist/commands/message/lifecycle.js +128 -0
  20. package/dist/commands/reduce/command.d.ts +1 -0
  21. package/dist/commands/reduce/command.js +3 -1
  22. package/dist/commands/reduce/targets.d.ts +1 -0
  23. package/dist/commands/reduce/targets.js +48 -2
  24. package/dist/commands/shared/resolve-stage-competitors.js +4 -1
  25. package/dist/commands/verify/command.d.ts +1 -0
  26. package/dist/commands/verify/command.js +2 -1
  27. package/dist/commands/verify/max-parallel.d.ts +1 -1
  28. package/dist/commands/verify/max-parallel.js +3 -1
  29. package/dist/commands/verify/targets.d.ts +2 -1
  30. package/dist/commands/verify/targets.js +154 -22
  31. package/dist/configs/agents/defaults.js +25 -25
  32. package/dist/configs/orchestration/bootstrap.d.ts +6 -1
  33. package/dist/configs/orchestration/bootstrap.js +27 -6
  34. package/dist/configs/orchestration/types.d.ts +25 -10
  35. package/dist/configs/orchestration/types.js +10 -6
  36. package/dist/configs/verification/types.d.ts +5 -0
  37. package/dist/configs/verification/types.js +3 -0
  38. package/dist/contracts/list.d.ts +38 -4
  39. package/dist/contracts/list.js +30 -1
  40. package/dist/domain/message/competition/adapter.d.ts +36 -0
  41. package/dist/domain/message/competition/adapter.js +197 -0
  42. package/dist/domain/message/competition/prompt.d.ts +8 -0
  43. package/dist/domain/message/competition/prompt.js +29 -0
  44. package/dist/domain/message/model/mutators.d.ts +17 -0
  45. package/dist/domain/message/model/mutators.js +107 -0
  46. package/dist/domain/message/model/types.d.ts +100 -0
  47. package/dist/domain/message/model/types.js +87 -0
  48. package/dist/domain/message/persistence/adapter.d.ts +43 -0
  49. package/dist/domain/message/persistence/adapter.js +124 -0
  50. package/dist/domain/reduce/competition/adapter.d.ts +1 -0
  51. package/dist/domain/reduce/competition/adapter.js +57 -4
  52. package/dist/domain/reduce/competition/prompt.d.ts +1 -1
  53. package/dist/domain/reduce/model/types.d.ts +3 -0
  54. package/dist/domain/reduce/model/types.js +2 -1
  55. package/dist/domain/verify/competition/adapter.js +8 -5
  56. package/dist/domain/verify/competition/programmatic.js +3 -0
  57. package/dist/domain/verify/competition/prompt.js +6 -0
  58. package/dist/domain/verify/competition/rubric.js +7 -1
  59. package/dist/domain/verify/competition/shared-layout.d.ts +42 -2
  60. package/dist/domain/verify/competition/shared-layout.js +92 -21
  61. package/dist/domain/verify/competition/target.d.ts +17 -0
  62. package/dist/domain/verify/model/types.d.ts +20 -2
  63. package/dist/domain/verify/model/types.js +15 -2
  64. package/dist/mcp/server.d.ts +2 -2
  65. package/dist/mcp/server.js +30 -13
  66. package/dist/policy/verification.js +2 -0
  67. package/dist/preflight/index.d.ts +2 -0
  68. package/dist/preflight/index.js +3 -1
  69. package/dist/render/transcripts/list.d.ts +2 -0
  70. package/dist/render/transcripts/list.js +24 -0
  71. package/dist/render/transcripts/message.d.ts +72 -0
  72. package/dist/render/transcripts/message.js +362 -0
  73. package/dist/render/transcripts/stage-progress.d.ts +1 -1
  74. package/dist/render/transcripts/verify.d.ts +4 -0
  75. package/dist/render/transcripts/verify.js +7 -1
  76. package/dist/render/utils/transcript-shell.d.ts +1 -1
  77. package/dist/render/utils/transcript-shell.js +6 -0
  78. package/dist/status/index.d.ts +21 -0
  79. package/dist/status/index.js +30 -0
  80. package/dist/workspace/setup.js +13 -7
  81. package/dist/workspace/structure.d.ts +14 -6
  82. package/dist/workspace/structure.js +25 -9
  83. package/dist/workspace/verification-defaults.d.ts +1 -1
  84. package/dist/workspace/verification-defaults.js +255 -0
  85. package/package.json +15 -16
@@ -0,0 +1,100 @@
1
+ import { z } from "zod";
2
+ import { type MessageRecipientStatus, messageRecipientStatusSchema, type MessageStatus, messageStatusSchema, TERMINAL_MESSAGE_RECIPIENT_STATUSES, TERMINAL_MESSAGE_STATUSES } from "../../../status/index.js";
3
+ export type { MessageRecipientStatus, MessageStatus };
4
+ export { messageRecipientStatusSchema, messageStatusSchema, TERMINAL_MESSAGE_RECIPIENT_STATUSES, TERMINAL_MESSAGE_STATUSES, };
5
+ export declare const messageRecipientEntrySchema: z.ZodObject<{
6
+ agentId: z.ZodString;
7
+ status: z.ZodEnum<{
8
+ queued: "queued";
9
+ running: "running";
10
+ succeeded: "succeeded";
11
+ failed: "failed";
12
+ aborted: "aborted";
13
+ }>;
14
+ startedAt: z.ZodOptional<z.ZodString>;
15
+ completedAt: z.ZodOptional<z.ZodString>;
16
+ outputPath: z.ZodOptional<z.ZodString>;
17
+ stdoutPath: z.ZodOptional<z.ZodString>;
18
+ stderrPath: z.ZodOptional<z.ZodString>;
19
+ tokenUsage: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
20
+ input_tokens: z.ZodOptional<z.ZodNumber>;
21
+ output_tokens: z.ZodOptional<z.ZodNumber>;
22
+ cache_read_input_tokens: z.ZodOptional<z.ZodNumber>;
23
+ cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>;
24
+ }, z.core.$strict>, z.ZodObject<{
25
+ input_tokens: z.ZodOptional<z.ZodNumber>;
26
+ cached_input_tokens: z.ZodOptional<z.ZodNumber>;
27
+ output_tokens: z.ZodOptional<z.ZodNumber>;
28
+ reasoning_output_tokens: z.ZodOptional<z.ZodNumber>;
29
+ total_tokens: z.ZodOptional<z.ZodNumber>;
30
+ }, z.core.$strict>, z.ZodObject<{
31
+ input: z.ZodOptional<z.ZodNumber>;
32
+ output: z.ZodOptional<z.ZodNumber>;
33
+ cached: z.ZodOptional<z.ZodNumber>;
34
+ thoughts: z.ZodOptional<z.ZodNumber>;
35
+ tool: z.ZodOptional<z.ZodNumber>;
36
+ total: z.ZodOptional<z.ZodNumber>;
37
+ }, z.core.$strict>]>>;
38
+ error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
39
+ }, z.core.$strip>;
40
+ export type MessageRecipientEntry = z.infer<typeof messageRecipientEntrySchema>;
41
+ export declare const messageRecordSchema: z.ZodObject<{
42
+ sessionId: z.ZodString;
43
+ createdAt: z.ZodString;
44
+ startedAt: z.ZodString;
45
+ completedAt: z.ZodOptional<z.ZodString>;
46
+ status: z.ZodEnum<{
47
+ queued: "queued";
48
+ running: "running";
49
+ succeeded: "succeeded";
50
+ failed: "failed";
51
+ aborted: "aborted";
52
+ }>;
53
+ baseRevisionSha: z.ZodOptional<z.ZodString>;
54
+ prompt: z.ZodString;
55
+ sourceInteractiveSessionId: z.ZodOptional<z.ZodString>;
56
+ extraContext: z.ZodOptional<z.ZodArray<z.ZodString>>;
57
+ extraContextMetadata: z.ZodOptional<z.ZodArray<z.ZodObject<{
58
+ stagedPath: z.ZodString;
59
+ sourcePath: z.ZodString;
60
+ }, z.core.$strip>>>;
61
+ recipients: z.ZodArray<z.ZodObject<{
62
+ agentId: z.ZodString;
63
+ status: z.ZodEnum<{
64
+ queued: "queued";
65
+ running: "running";
66
+ succeeded: "succeeded";
67
+ failed: "failed";
68
+ aborted: "aborted";
69
+ }>;
70
+ startedAt: z.ZodOptional<z.ZodString>;
71
+ completedAt: z.ZodOptional<z.ZodString>;
72
+ outputPath: z.ZodOptional<z.ZodString>;
73
+ stdoutPath: z.ZodOptional<z.ZodString>;
74
+ stderrPath: z.ZodOptional<z.ZodString>;
75
+ tokenUsage: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
76
+ input_tokens: z.ZodOptional<z.ZodNumber>;
77
+ output_tokens: z.ZodOptional<z.ZodNumber>;
78
+ cache_read_input_tokens: z.ZodOptional<z.ZodNumber>;
79
+ cache_creation_input_tokens: z.ZodOptional<z.ZodNumber>;
80
+ }, z.core.$strict>, z.ZodObject<{
81
+ input_tokens: z.ZodOptional<z.ZodNumber>;
82
+ cached_input_tokens: z.ZodOptional<z.ZodNumber>;
83
+ output_tokens: z.ZodOptional<z.ZodNumber>;
84
+ reasoning_output_tokens: z.ZodOptional<z.ZodNumber>;
85
+ total_tokens: z.ZodOptional<z.ZodNumber>;
86
+ }, z.core.$strict>, z.ZodObject<{
87
+ input: z.ZodOptional<z.ZodNumber>;
88
+ output: z.ZodOptional<z.ZodNumber>;
89
+ cached: z.ZodOptional<z.ZodNumber>;
90
+ thoughts: z.ZodOptional<z.ZodNumber>;
91
+ tool: z.ZodOptional<z.ZodNumber>;
92
+ total: z.ZodOptional<z.ZodNumber>;
93
+ }, z.core.$strict>]>>;
94
+ error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
95
+ }, z.core.$strip>>;
96
+ error: z.ZodOptional<z.ZodNullable<z.ZodString>>;
97
+ }, z.core.$strip>;
98
+ export type MessageRecord = z.infer<typeof messageRecordSchema>;
99
+ export type MessageIndexEntry = Pick<MessageRecord, "sessionId" | "createdAt" | "status">;
100
+ export declare function deriveMessageStatusFromRecipients(recipientStatuses: readonly MessageRecipientStatus[]): MessageStatus;
@@ -0,0 +1,87 @@
1
+ import { z } from "zod";
2
+ import { agentIdSchema } from "../../../configs/agents/types.js";
3
+ import { extractedTokenUsageSchema } from "../../../domain/run/model/types.js";
4
+ import { extraContextMetadataEntrySchema, persistedExtraContextPathSchema, } from "../../../persistence/extra-context.js";
5
+ import { repoRelativeRecordPathSchema } from "../../../persistence/record-path-schema.js";
6
+ import { messageRecipientStatusSchema, messageStatusSchema, TERMINAL_MESSAGE_RECIPIENT_STATUSES, TERMINAL_MESSAGE_STATUSES, } from "../../../status/index.js";
7
+ import { validateOperationLifecycleTimestamps, validateRecordLifecycleTimestamps, } from "../../shared/lifecycle.js";
8
+ export { messageRecipientStatusSchema, messageStatusSchema, TERMINAL_MESSAGE_RECIPIENT_STATUSES, TERMINAL_MESSAGE_STATUSES, };
9
+ const RUNNING_MESSAGE_RECORD_STATUSES = [
10
+ "running",
11
+ ];
12
+ export const messageRecipientEntrySchema = z
13
+ .object({
14
+ agentId: agentIdSchema,
15
+ status: messageRecipientStatusSchema,
16
+ startedAt: z.string().optional(),
17
+ completedAt: z.string().optional(),
18
+ outputPath: repoRelativeRecordPathSchema.optional(),
19
+ stdoutPath: repoRelativeRecordPathSchema.optional(),
20
+ stderrPath: repoRelativeRecordPathSchema.optional(),
21
+ tokenUsage: extractedTokenUsageSchema.optional(),
22
+ error: z.string().nullable().optional(),
23
+ })
24
+ .superRefine((recipient, ctx) => {
25
+ if (recipient.status === "succeeded" && !recipient.outputPath) {
26
+ ctx.addIssue({
27
+ code: z.ZodIssueCode.custom,
28
+ path: ["outputPath"],
29
+ message: "succeeded message recipients must persist `outputPath`",
30
+ });
31
+ }
32
+ validateOperationLifecycleTimestamps({
33
+ status: recipient.status,
34
+ startedAt: recipient.startedAt,
35
+ completedAt: recipient.completedAt,
36
+ }, ctx, {
37
+ queued: ["queued"],
38
+ running: ["running"],
39
+ terminal: TERMINAL_MESSAGE_RECIPIENT_STATUSES,
40
+ });
41
+ });
42
+ export const messageRecordSchema = z
43
+ .object({
44
+ sessionId: z.string(),
45
+ createdAt: z.string(),
46
+ startedAt: z.string(),
47
+ completedAt: z.string().optional(),
48
+ status: messageStatusSchema,
49
+ baseRevisionSha: z.string().optional(),
50
+ prompt: z.string(),
51
+ sourceInteractiveSessionId: z.string().optional(),
52
+ extraContext: z.array(persistedExtraContextPathSchema).optional(),
53
+ extraContextMetadata: z.array(extraContextMetadataEntrySchema).optional(),
54
+ recipients: z
55
+ .array(messageRecipientEntrySchema)
56
+ .min(1)
57
+ .superRefine((recipients, ctx) => {
58
+ const seen = new Set();
59
+ for (const recipient of recipients) {
60
+ if (seen.has(recipient.agentId)) {
61
+ ctx.addIssue({
62
+ code: z.ZodIssueCode.custom,
63
+ message: `Duplicate message recipient agent id: ${recipient.agentId}`,
64
+ });
65
+ return;
66
+ }
67
+ seen.add(recipient.agentId);
68
+ }
69
+ }),
70
+ error: z.string().nullable().optional(),
71
+ })
72
+ .superRefine((record, ctx) => {
73
+ validateRecordLifecycleTimestamps({
74
+ status: record.status,
75
+ createdAt: record.createdAt,
76
+ startedAt: record.startedAt,
77
+ completedAt: record.completedAt,
78
+ }, ctx, {
79
+ queued: [],
80
+ running: RUNNING_MESSAGE_RECORD_STATUSES,
81
+ terminal: TERMINAL_MESSAGE_STATUSES,
82
+ });
83
+ });
84
+ export function deriveMessageStatusFromRecipients(recipientStatuses) {
85
+ const hasSuccess = recipientStatuses.some((status) => status === "succeeded");
86
+ return hasSuccess ? "succeeded" : "failed";
87
+ }
@@ -0,0 +1,43 @@
1
+ import type { MessageRecord } from "../model/types.js";
2
+ export type MessageRecordPredicate = (record: MessageRecord) => boolean;
3
+ export interface MessageRecordWarningMissing {
4
+ kind: "missing-record";
5
+ sessionId: string;
6
+ recordPath: string;
7
+ displayPath: string;
8
+ }
9
+ export interface MessageRecordWarningParse {
10
+ kind: "parse-error";
11
+ sessionId: string;
12
+ recordPath: string;
13
+ displayPath: string;
14
+ details: string;
15
+ }
16
+ export type MessageRecordWarning = MessageRecordWarningMissing | MessageRecordWarningParse;
17
+ export interface ReadMessageRecordsOptions {
18
+ root: string;
19
+ messagesFilePath: string;
20
+ limit?: number;
21
+ predicate?: MessageRecordPredicate;
22
+ onWarning?: (warning: MessageRecordWarning) => void;
23
+ }
24
+ export interface RewriteMessageRecordOptions {
25
+ root: string;
26
+ messagesFilePath: string;
27
+ sessionId: string;
28
+ mutate: (record: MessageRecord) => MessageRecord;
29
+ forceFlush?: boolean;
30
+ }
31
+ export interface AppendMessageRecordOptions {
32
+ root: string;
33
+ messagesFilePath: string;
34
+ record: MessageRecord;
35
+ }
36
+ export declare function readMessageRecords(options: ReadMessageRecordsOptions): Promise<MessageRecord[]>;
37
+ export declare function appendMessageRecord(options: AppendMessageRecordOptions): Promise<void>;
38
+ export declare function rewriteMessageRecord(options: RewriteMessageRecordOptions): Promise<MessageRecord>;
39
+ export declare function flushMessageRecordBuffer(options: {
40
+ messagesFilePath: string;
41
+ sessionId: string;
42
+ }): Promise<void>;
43
+ export declare function flushAllMessageRecordBuffers(): Promise<void>;
@@ -0,0 +1,124 @@
1
+ import { dirname, join } from "node:path";
2
+ import { mapSessionStoreError, sessionStoreErrorMapper, } from "../../../persistence/error-mapping.js";
3
+ import { SessionRecordParseError } from "../../../persistence/errors.js";
4
+ import { acquireHistoryLock } from "../../../persistence/history-lock.js";
5
+ import { createSessionStore, } from "../../../persistence/session-store.js";
6
+ import { messageRecordSchema, TERMINAL_MESSAGE_STATUSES, } from "../model/types.js";
7
+ const MESSAGE_INDEX_VERSION = 1;
8
+ const MESSAGE_RECORD_FILENAME = "record.json";
9
+ const MESSAGE_HISTORY_LOCK_FILENAME = "history.lock";
10
+ const messagePersistence = createSessionStore({
11
+ recordFilename: MESSAGE_RECORD_FILENAME,
12
+ indexVersion: MESSAGE_INDEX_VERSION,
13
+ acquireLock: acquireHistoryLock,
14
+ parseRecord: ({ path, raw }) => {
15
+ const parsed = JSON.parse(raw);
16
+ const result = messageRecordSchema.safeParse(parsed);
17
+ if (!result.success) {
18
+ const issues = result.error.issues
19
+ .map((issue) => issue.message)
20
+ .join(", ");
21
+ throw new SessionRecordParseError(path, issues);
22
+ }
23
+ return result.data;
24
+ },
25
+ buildIndexEntry: (record) => ({
26
+ sessionId: record.sessionId,
27
+ createdAt: record.createdAt,
28
+ status: record.status,
29
+ }),
30
+ getIndexEntryId: (entry) => entry.sessionId,
31
+ shouldForceFlush: (record) => TERMINAL_MESSAGE_STATUSES.includes(record.status),
32
+ getRecordId: (record) => record.sessionId,
33
+ getRecordStatus: (record) => record.status,
34
+ readIndexEntries: (parsed) => {
35
+ const payload = parsed;
36
+ return Array.isArray(payload.sessions) ? payload.sessions : [];
37
+ },
38
+ });
39
+ export async function readMessageRecords(options) {
40
+ const { root, messagesFilePath, limit, predicate, onWarning } = options;
41
+ const paths = buildMessagePaths(root, messagesFilePath);
42
+ try {
43
+ return await messagePersistence.readRecords({
44
+ paths,
45
+ limit,
46
+ predicate,
47
+ onWarning: onWarning
48
+ ? (warning) => onWarning(mapWarning(warning))
49
+ : undefined,
50
+ });
51
+ }
52
+ catch (error) {
53
+ throw mapSessionStoreError(error, sessionStoreErrorMapper);
54
+ }
55
+ }
56
+ export async function appendMessageRecord(options) {
57
+ const { root, messagesFilePath, record } = options;
58
+ const paths = buildMessagePaths(root, messagesFilePath);
59
+ try {
60
+ await messagePersistence.appendRecord({ paths, record });
61
+ }
62
+ catch (error) {
63
+ throw mapSessionStoreError(error, sessionStoreErrorMapper);
64
+ }
65
+ }
66
+ export async function rewriteMessageRecord(options) {
67
+ const { root, messagesFilePath, sessionId, mutate, forceFlush = false, } = options;
68
+ const paths = buildMessagePaths(root, messagesFilePath);
69
+ try {
70
+ return await messagePersistence.rewriteRecord({
71
+ paths,
72
+ sessionId,
73
+ mutate,
74
+ forceFlush,
75
+ });
76
+ }
77
+ catch (error) {
78
+ throw mapSessionStoreError(error, sessionStoreErrorMapper);
79
+ }
80
+ }
81
+ export async function flushMessageRecordBuffer(options) {
82
+ const { messagesFilePath, sessionId } = options;
83
+ const paths = buildMessagePaths("", messagesFilePath);
84
+ try {
85
+ await messagePersistence.flushRecordBuffer({ paths, sessionId });
86
+ }
87
+ catch (error) {
88
+ throw mapSessionStoreError(error, sessionStoreErrorMapper);
89
+ }
90
+ }
91
+ export async function flushAllMessageRecordBuffers() {
92
+ try {
93
+ await messagePersistence.flushAllRecordBuffers();
94
+ }
95
+ catch (error) {
96
+ throw mapSessionStoreError(error, sessionStoreErrorMapper);
97
+ }
98
+ }
99
+ function buildMessagePaths(root, messagesFilePath) {
100
+ const messagesRoot = dirname(messagesFilePath);
101
+ return {
102
+ root,
103
+ indexPath: messagesFilePath,
104
+ sessionsDir: join(messagesRoot, "sessions"),
105
+ lockPath: join(messagesRoot, MESSAGE_HISTORY_LOCK_FILENAME),
106
+ };
107
+ }
108
+ function mapWarning(warning) {
109
+ if (warning.kind === "parse-error") {
110
+ return {
111
+ kind: "parse-error",
112
+ sessionId: warning.sessionId,
113
+ recordPath: warning.recordPath,
114
+ displayPath: warning.displayPath,
115
+ details: warning.details,
116
+ };
117
+ }
118
+ return {
119
+ kind: "missing-record",
120
+ sessionId: warning.sessionId,
121
+ recordPath: warning.recordPath,
122
+ displayPath: warning.displayPath,
123
+ };
124
+ }
@@ -31,6 +31,7 @@ export interface CreateReduceCompetitionAdapterInput {
31
31
  readonly reductionsFilePath: string;
32
32
  readonly specsFilePath: string;
33
33
  readonly runsFilePath: string;
34
+ readonly messagesFilePath: string;
34
35
  readonly verificationsFilePath: string;
35
36
  readonly target: ReductionTarget;
36
37
  readonly environment: EnvironmentConfig;
@@ -7,6 +7,7 @@ import { RunNotFoundCliError } from "../../../cli/errors.js";
7
7
  import { stageExtraContextFiles, } from "../../../competition/shared/extra-context.js";
8
8
  import { composeStageSandboxPolicy } from "../../../competition/shared/sandbox-policy.js";
9
9
  import { createTeardownController, runTeardown, } from "../../../competition/shared/teardown.js";
10
+ import { readMessageRecords } from "../../../domain/message/persistence/adapter.js";
10
11
  import { validateReductionOutputContract } from "../../../domain/reduce/competition/output-validation.js";
11
12
  import { buildReducePrompt } from "../../../domain/reduce/competition/prompt.js";
12
13
  import { parseReductionArtifact } from "../../../domain/reduce/competition/reduction.js";
@@ -25,9 +26,9 @@ import { normalizePathForDisplay, relativeToRoot, resolvePath, } from "../../../
25
26
  import { extractProviderNativeTokenUsageForSession } from "../../../workspace/chat/native-usage.js";
26
27
  import { scaffoldAgentSessionWorkspace, } from "../../../workspace/layout.js";
27
28
  import { promoteWorkspaceFile } from "../../../workspace/promotion.js";
28
- import { REDUCTION_ARTIFACT_INFO_FILENAME, REDUCTION_DATA_FILENAME, REDUCTION_FILENAME, VORATIQ_REDUCTION_DIR, } from "../../../workspace/structure.js";
29
+ import { MESSAGE_RESPONSE_FILENAME, REDUCTION_ARTIFACT_INFO_FILENAME, REDUCTION_DATA_FILENAME, REDUCTION_FILENAME, VORATIQ_REDUCTION_DIR, } from "../../../workspace/structure.js";
29
30
  export function createReduceCompetitionAdapter(input) {
30
- const { root, reductionId, createdAt, reductionsFilePath, specsFilePath, runsFilePath, verificationsFilePath, target, environment, extraContextFiles = [], renderer, } = input;
31
+ const { root, reductionId, createdAt, reductionsFilePath, specsFilePath, runsFilePath, messagesFilePath, verificationsFilePath, target, environment, extraContextFiles = [], renderer, } = input;
31
32
  let failure;
32
33
  const teardown = createTeardownController(`reduce \`${reductionId}\``);
33
34
  teardown.addAction({
@@ -55,6 +56,7 @@ export function createReduceCompetitionAdapter(input) {
55
56
  root,
56
57
  specsFilePath,
57
58
  runsFilePath,
59
+ messagesFilePath,
58
60
  verificationsFilePath,
59
61
  reductionsFilePath,
60
62
  target,
@@ -443,10 +445,12 @@ async function prepareReductionTargetContext(options) {
443
445
  return await prepareSpecTargetContext(options);
444
446
  case "run":
445
447
  return await prepareRunTargetContext(options);
446
- case "verify":
447
- return await prepareVerificationTargetContext(options);
448
448
  case "reduce":
449
449
  return await prepareReductionTargetContextInternal(options);
450
+ case "verify":
451
+ return await prepareVerificationTargetContext(options);
452
+ case "message":
453
+ return await prepareMessageTargetContext(options);
450
454
  }
451
455
  }
452
456
  async function prepareSpecTargetContext(options) {
@@ -682,6 +686,55 @@ async function prepareReductionTargetContextInternal(options) {
682
686
  },
683
687
  };
684
688
  }
689
+ async function prepareMessageTargetContext(options) {
690
+ const { root, messagesFilePath, target } = options;
691
+ const [record] = await readMessageRecords({
692
+ root,
693
+ messagesFilePath,
694
+ limit: 1,
695
+ predicate: (entry) => entry.sessionId === target.id,
696
+ });
697
+ if (!record) {
698
+ throw new Error(`Message session \`${target.id}\` not found.`);
699
+ }
700
+ const succeededRecipients = record.recipients.filter((recipient) => recipient.status === "succeeded" &&
701
+ typeof recipient.outputPath === "string");
702
+ if (succeededRecipients.length === 0) {
703
+ throw new Error(`Message session \`${target.id}\` has no generated artifacts.`);
704
+ }
705
+ const stagedFiles = [];
706
+ const artifacts = [];
707
+ for (const recipient of succeededRecipients) {
708
+ const outputRelative = `inputs/recipients/${recipient.agentId}/${MESSAGE_RESPONSE_FILENAME}`;
709
+ stagedFiles.push({
710
+ sourceAbsolutePath: resolvePath(root, recipient.outputPath),
711
+ stagedRelativePath: outputRelative,
712
+ });
713
+ artifacts.push({
714
+ artifactId: `message:${recipient.agentId}`,
715
+ kind: "message-output",
716
+ agentId: recipient.agentId,
717
+ status: recipient.status,
718
+ outputPath: outputRelative,
719
+ ...(recipient.tokenUsage ? { tokenUsage: recipient.tokenUsage } : {}),
720
+ });
721
+ }
722
+ return {
723
+ target,
724
+ displayPath: `.voratiq/message/sessions/${record.sessionId}`,
725
+ stagedFiles,
726
+ manifest: {
727
+ target: {
728
+ operator: "message",
729
+ id: record.sessionId,
730
+ path: `.voratiq/message/sessions/${record.sessionId}`,
731
+ status: record.status,
732
+ prompt: record.prompt,
733
+ },
734
+ artifacts,
735
+ },
736
+ };
737
+ }
685
738
  async function stageReductionTargetContext(options) {
686
739
  const { workspacePath, targetContext } = options;
687
740
  for (const stagedFile of targetContext.stagedFiles) {
@@ -1,6 +1,6 @@
1
1
  import { type ResolvedExtraContextFile } from "../../../competition/shared/extra-context.js";
2
2
  export interface BuildReducePromptOptions {
3
- targetOperator: "spec" | "run" | "verify" | "reduce";
3
+ targetOperator: "spec" | "run" | "reduce" | "verify" | "message";
4
4
  targetId: string;
5
5
  artifactInfoPath: string;
6
6
  repoRootPath: string;
@@ -3,6 +3,7 @@ import { type ReductionStatus, reductionStatusSchema, TERMINAL_REDUCTION_STATUSE
3
3
  export type { ReductionStatus };
4
4
  export { reductionStatusSchema, TERMINAL_REDUCTION_STATUSES };
5
5
  export declare const reductionTargetTypeSchema: z.ZodEnum<{
6
+ message: "message";
6
7
  reduce: "reduce";
7
8
  spec: "spec";
8
9
  run: "run";
@@ -11,6 +12,7 @@ export declare const reductionTargetTypeSchema: z.ZodEnum<{
11
12
  export type ReductionTargetType = z.infer<typeof reductionTargetTypeSchema>;
12
13
  export declare const reductionTargetSchema: z.ZodObject<{
13
14
  type: z.ZodEnum<{
15
+ message: "message";
14
16
  reduce: "reduce";
15
17
  spec: "spec";
16
18
  run: "run";
@@ -57,6 +59,7 @@ export declare const reductionRecordSchema: z.ZodObject<{
57
59
  sessionId: z.ZodString;
58
60
  target: z.ZodObject<{
59
61
  type: z.ZodEnum<{
62
+ message: "message";
60
63
  reduce: "reduce";
61
64
  spec: "spec";
62
65
  run: "run";
@@ -9,8 +9,9 @@ export { reductionStatusSchema, TERMINAL_REDUCTION_STATUSES };
9
9
  export const reductionTargetTypeSchema = z.enum([
10
10
  "spec",
11
11
  "run",
12
- "verify",
13
12
  "reduce",
13
+ "verify",
14
+ "message",
14
15
  ]);
15
16
  export const reductionTargetSchema = z
16
17
  .object({
@@ -17,7 +17,7 @@ import { verificationResultArtifactSchema, } from "../model/types.js";
17
17
  import { writeVerificationArtifact } from "./artifacts.js";
18
18
  import { assertNoVerificationIdentityLeak, assertRubricResultSelectorsMatchAliasMap, buildForbiddenVerificationIdentityTokens, parseRubricResultPayload, } from "./blinding.js";
19
19
  import { buildRubricPrompt } from "./prompt.js";
20
- import { attachVerifierWorkspaceMounts, buildStagedVerificationInputs, } from "./shared-layout.js";
20
+ import { attachVerifierWorkspaceMounts, buildStagedVerificationInputs, sharedInputsUseReferenceRepo, } from "./shared-layout.js";
21
21
  export function createVerifyCompetitionAdapter(input) {
22
22
  const { root, verificationId, resolvedTarget, aliasMap, environment, extraContextFiles, sharedInputs, teardown, mutators, renderer, } = input;
23
23
  const startedAtByExecutionKey = new Map();
@@ -94,8 +94,7 @@ export function createVerifyCompetitionAdapter(input) {
94
94
  await attachVerifierWorkspaceMounts({
95
95
  workspacePath: workspacePaths.workspacePath,
96
96
  contextPath: workspacePaths.contextPath,
97
- sharedInputsAbsolute: sharedInputs.sharedInputsAbsolute,
98
- referenceRepoAbsolute: sharedInputs.referenceRepoAbsolute,
97
+ sharedInputs,
99
98
  });
100
99
  await ensureWorkspaceDependencies({
101
100
  root,
@@ -131,9 +130,13 @@ export function createVerifyCompetitionAdapter(input) {
131
130
  workspacePaths.contextPath,
132
131
  join(workspacePaths.workspacePath, "context"),
133
132
  join(workspacePaths.workspacePath, "inputs"),
134
- join(workspacePaths.workspacePath, "reference_repo"),
135
133
  sharedInputs.sharedInputsAbsolute,
136
- sharedInputs.referenceRepoAbsolute,
134
+ ...(sharedInputsUseReferenceRepo(sharedInputs)
135
+ ? [
136
+ join(workspacePaths.workspacePath, "reference_repo"),
137
+ sharedInputs.referenceRepoAbsolute,
138
+ ]
139
+ : []),
137
140
  ],
138
141
  });
139
142
  const result = await runSandboxedAgent({
@@ -277,6 +277,9 @@ function resolveProgrammaticMethodPlan(options) {
277
277
  checks,
278
278
  };
279
279
  }
280
+ if (resolvedTarget.target.kind === "message") {
281
+ return { kind: "none" };
282
+ }
280
283
  const configuredChecks = extractUnsupportedProgrammaticChecks(resolvedTarget.target.kind === "spec"
281
284
  ? verificationConfig.spec
282
285
  : verificationConfig.reduce);
@@ -38,6 +38,12 @@ export function buildRubricPrompt(options) {
38
38
  return ` - ${candidate.alias}${suffix}`;
39
39
  }));
40
40
  }
41
+ else if (staged.kind === "message") {
42
+ lines.push(`- Original message prompt: \`${staged.promptPath}\``, "- Candidate responses:", ...staged.candidates.map((candidate) => ` - ${candidate.alias}: \`${candidate.responsePath}\``));
43
+ }
44
+ else if (staged.kind === "reduce-no-reference") {
45
+ lines.push(`- No repository snapshot is available for this reduction target because its lineage reaches message session \`${staged.referenceRepoUnavailable.messageSessionId}\` without a durable base revision.`, "- Reduction candidates:", ...staged.candidates.map((candidate) => ` - ${candidate.alias}: \`${candidate.reductionPath}\``));
46
+ }
41
47
  else {
42
48
  lines.push(`- Base repository snapshot (read-only): \`${staged.referenceRepoPath}/\``, "- Reduction candidates:", ...staged.candidates.map((candidate) => ` - ${candidate.alias}: \`${candidate.reductionPath}\``));
43
49
  }
@@ -8,7 +8,13 @@ export async function executeAndPersistRubricMethods(options) {
8
8
  ? verificationConfig.spec.rubric
9
9
  : resolvedTarget.target.kind === "run"
10
10
  ? verificationConfig.run.rubric
11
- : verificationConfig.reduce.rubric;
11
+ : resolvedTarget.target.kind === "reduce"
12
+ ? verificationConfig.reduce.rubric
13
+ : verificationConfig.message.rubric;
14
+ if (resolvedTarget.target.kind === "message" &&
15
+ rubricTemplates.length === 0) {
16
+ throw new Error("Message verification requires at least one configured rubric template under `message.rubric` in `.voratiq/verification.yaml`.");
17
+ }
12
18
  if (rubricTemplates.length === 0 || verifierAgents.length === 0) {
13
19
  return [];
14
20
  }
@@ -31,6 +31,27 @@ export type SharedVerificationInputs = {
31
31
  candidates: readonly {
32
32
  alias: string;
33
33
  }[];
34
+ } | {
35
+ kind: "reduce-no-reference";
36
+ sharedRootAbsolute: string;
37
+ sharedInputsAbsolute: string;
38
+ worktreesToRemove: readonly string[];
39
+ referenceRepoUnavailable: {
40
+ reason: "message-lineage";
41
+ messageSessionId: string;
42
+ };
43
+ candidates: readonly {
44
+ alias: string;
45
+ }[];
46
+ } | {
47
+ kind: "message";
48
+ sharedRootAbsolute: string;
49
+ sharedInputsAbsolute: string;
50
+ worktreesToRemove: readonly string[];
51
+ promptAbsolute: string;
52
+ candidates: readonly {
53
+ alias: string;
54
+ }[];
34
55
  };
35
56
  export type StagedVerificationInputs = {
36
57
  kind: "spec";
@@ -57,6 +78,23 @@ export type StagedVerificationInputs = {
57
78
  alias: string;
58
79
  reductionPath: string;
59
80
  }[];
81
+ } | {
82
+ kind: "reduce-no-reference";
83
+ referenceRepoUnavailable: {
84
+ reason: "message-lineage";
85
+ messageSessionId: string;
86
+ };
87
+ candidates: readonly {
88
+ alias: string;
89
+ reductionPath: string;
90
+ }[];
91
+ } | {
92
+ kind: "message";
93
+ promptPath: string;
94
+ candidates: readonly {
95
+ alias: string;
96
+ responsePath: string;
97
+ }[];
60
98
  };
61
99
  export declare function prepareSharedVerificationInputs(options: {
62
100
  root: string;
@@ -73,9 +111,11 @@ export declare function buildStagedVerificationInputs(options: {
73
111
  workspacePaths: AgentWorkspacePaths;
74
112
  sharedInputs: SharedVerificationInputs;
75
113
  }): StagedVerificationInputs;
114
+ export declare function sharedInputsUseReferenceRepo(sharedInputs: SharedVerificationInputs): sharedInputs is Extract<SharedVerificationInputs, {
115
+ kind: "spec" | "run" | "reduce";
116
+ }>;
76
117
  export declare function attachVerifierWorkspaceMounts(options: {
77
118
  workspacePath: string;
78
119
  contextPath: string;
79
- sharedInputsAbsolute: string;
80
- referenceRepoAbsolute: string;
120
+ sharedInputs: SharedVerificationInputs;
81
121
  }): Promise<void>;