@xfey/tutti 0.1.17 → 0.1.18

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 (46) hide show
  1. package/dist/collaboration-state/run-recording.js +3 -0
  2. package/dist/collaboration-state/run-results.js +3 -0
  3. package/dist/collaboration-state/types.d.ts +1 -0
  4. package/dist/control-plane/index.js +3 -0
  5. package/dist/control-plane/types.d.ts +1 -0
  6. package/dist/control-plane/worklist-terminal-feedback.d.ts +1 -0
  7. package/dist/control-plane/worklist-terminal-feedback.js +109 -0
  8. package/dist/run-pipeline/openai.js +6 -0
  9. package/dist/run-pipeline/promotion-reconcile.d.ts +2 -2
  10. package/dist/run-pipeline/promotion-reconcile.js +3 -0
  11. package/dist/run-pipeline/result-projections.d.ts +1 -0
  12. package/dist/run-pipeline/result-projections.js +3 -0
  13. package/dist/run-pipeline/task-run-output.d.ts +9 -3
  14. package/dist/run-pipeline/task-run-output.js +24 -4
  15. package/dist/server-shell/http/routes/project-api/openapi-execution-routes.d.ts +1 -0
  16. package/dist/server-shell/http/routes/project-api/openapi-viewer-routes.d.ts +2 -0
  17. package/dist/server-shell/http/routes/project-api/openapi.d.ts +1 -0
  18. package/dist/server-shell/http/routes/project-api/reference-files.js +9 -3
  19. package/dist/workspace-ops/constants.d.ts +1 -0
  20. package/dist/workspace-ops/constants.js +1 -0
  21. package/dist/workspace-ops/index.d.ts +2 -2
  22. package/dist/workspace-ops/index.js +2 -2
  23. package/dist/workspace-ops/reference-metadata.d.ts +2 -0
  24. package/dist/workspace-ops/reference-metadata.js +26 -1
  25. package/node_modules/@tutti/shared/dist/schemas/api/clarifications.d.ts +9 -0
  26. package/node_modules/@tutti/shared/dist/schemas/api/index.d.ts +1 -1
  27. package/node_modules/@tutti/shared/dist/schemas/api/index.js +1 -1
  28. package/node_modules/@tutti/shared/dist/schemas/api/messages.d.ts +52 -0
  29. package/node_modules/@tutti/shared/dist/schemas/api/messages.js +10 -0
  30. package/node_modules/@tutti/shared/dist/schemas/api/runtime-events.d.ts +1 -0
  31. package/node_modules/@tutti/shared/dist/schemas/api/types.d.ts +2 -1
  32. package/node_modules/@tutti/shared/dist/schemas/api/viewer-reference.d.ts +14 -0
  33. package/node_modules/@tutti/shared/dist/schemas/api/viewer-reference.js +2 -0
  34. package/node_modules/@tutti/shared/dist/schemas/api/work-items.d.ts +3 -0
  35. package/node_modules/@tutti/shared/dist/schemas/api/work-items.js +2 -0
  36. package/package.json +1 -1
  37. package/prompts/prompt-flow-map.md +2 -2
  38. package/prompts/runs/README.md +2 -1
  39. package/prompts/runs/task-continuation.md +8 -2
  40. package/prompts/runs/task-retry.md +8 -2
  41. package/prompts/runs/task-run.md +8 -2
  42. package/web/assets/index-4JInvPEN.js +29 -0
  43. package/web/assets/index-P5uZBm0s.css +1 -0
  44. package/web/index.html +2 -2
  45. package/web/assets/index-BhNJQ717.js +0 -29
  46. package/web/assets/index-mXkNKFjm.css +0 -1
@@ -5,7 +5,7 @@ export { ProviderUsageBreakdownProjectionSchema, ProviderUsageCategorySchema, Pr
5
5
  export { ProjectTimelineItemKindSchema, ProjectTimelineItemSchema, ProjectTimelineItemStatusSchema, ProjectTimelineResponseSchema, } from "./project-timeline.js";
6
6
  export { MAX_REFERENCE_STAGED_UPLOAD_BYTES, MAX_SKILL_ZIP_STAGED_UPLOAD_BYTES, MAX_STAGED_UPLOAD_BYTES, PresignedUploadPutSchema, ReferenceFileStartRelayUploadPayloadSchema, ReferenceStagedUploadReferenceProperties, RelayUploadProjectionSchema, RelayUploadPurposeSchema, Sha256DigestSchema, SkillZipStartRelayUploadPayloadSchema, SkillZipStagedUploadReferenceProperties, StagedUploadReferenceProperties, StagedUploadReferenceSchema, StartRelayUploadBodySchema, StartRelayUploadDispositionSchema, StartRelayUploadPayloadSchema, StartRelayUploadResponseSchema, StartRelayUploadResultSchema, maxStagedUploadBytesForPurpose, } from "./uploads.js";
7
7
  export { MarkReadBodySchema, MarkReadDispositionSchema, MarkReadPayloadSchema, MarkReadResponseSchema, MarkReadResultSchema, ReadStateScopeProjectionSchema, ReadStateScopeSchema, ReadStateSummaryProjectionSchema, } from "./read-state.js";
8
- export { GetMessagesRequestSchema, MessageAuthorSchema, MessageCreatedEventPayloadSchema, MessageKindSchema, MessageProjectionSchema, MessageReferenceFileRefSchema, MessageRefsSchema, MessageScopeSchema, MessageWindowSchema, ReferenceFileCategorySchema, SendMainChatMessageBodySchema, SendMainChatMessageCreatedDispositionSchema, SendMainChatMessageDispositionSchema, SendMainChatMessagePayloadSchema, SendMainChatMessageResponseSchema, SendMainChatMessageResultSchema, WorklistFeedbackItemSchema, WorklistFeedbackRefSchema, } from "./messages.js";
8
+ export { GetMessagesRequestSchema, MessageAuthorSchema, MessageCreatedEventPayloadSchema, MessageKindSchema, MessageProjectionSchema, MessageReferenceFileRefSchema, MessageRefsSchema, MessageScopeSchema, MessageWindowSchema, ReferenceFileCategorySchema, SendMainChatMessageBodySchema, SendMainChatMessageCreatedDispositionSchema, SendMainChatMessageDispositionSchema, SendMainChatMessagePayloadSchema, SendMainChatMessageResponseSchema, SendMainChatMessageResultSchema, WorklistFeedbackItemSchema, WorklistFeedbackGeneratedFileSchema, WorklistFeedbackRefSchema, } from "./messages.js";
9
9
  export { CheckSkipReasonCodeSchema, ExternalSideEffectSummaryProjectionSchema, GetRecoverySummariesRequestSchema, GetRecoverySummariesResponseSchema, GetRecoverySummaryResponseSchema, RecoverySummaryProjectionSchema, ResultAnchorSchema, RunLineageSchema, RunResultProjectionSchema, ScratchpadProjectionSchema, ScratchpadReceiptProjectionSchema, TaskContractProjectionSchema, TaskDetailProjectionSchema, TaskDetailResultProjectionSchema, TaskModuleProjectionSchema, TaskProjectionSchema, TaskRunResultsPageSchema, TaskStatusSchema, WorklistProjectionSchema, } from "./work-items.js";
10
10
  export { ActiveApprovalProjectionSchema, ApprovalCommandProjectionSchema, ApprovalDecisionKindSchema, ApprovalDecisionOptionProjectionSchema, ApprovalDecisionToneSchema, ApprovalFileChangeProjectionSchema, ApprovalPermissionsProjectionSchema, ApprovalRequestKindSchema, ApprovalRequestProjectionSchema, ApprovalResolutionOutcomeSchema, ApprovalResolutionProjectionSchema, DecideApprovalBodySchema, DecideApprovalDispositionSchema, DecideApprovalPayloadSchema, DecideApprovalResponseSchema, DecideApprovalResultSchema, } from "./approvals.js";
11
11
  export { ActiveClarificationProjectionSchema, ClarificationChangedEventPayloadSchema, ClarificationOwnerProjectionSchema, ClarificationRequestPayloadSchema, ClarificationRoundProjectionSchema, ClarificationRoundSummaryProjectionSchema, ClarificationSuccessorRefSchema, ClarificationThreadProjectionSchema, ContextRefSchema, GetClarificationRoundMessagesRequestSchema, GetClarificationRoundResponseSchema, GetClarificationThreadResponseSchema, HumanInteractionPayloadSchema, HumanRequestPayloadSchema, SendClarificationRoundMessageBodySchema, SendClarificationRoundMessageDispositionSchema, SendClarificationRoundMessagePayloadSchema, SendClarificationRoundMessageResponseSchema, SendClarificationRoundMessageResultSchema, SubmitClarificationRoundBodySchema, SubmitClarificationRoundDispositionSchema, SubmitClarificationRoundPayloadSchema, SubmitClarificationRoundResponseSchema, SubmitClarificationRoundResultSchema, } from "./clarifications.js";
@@ -35,6 +35,7 @@ export declare const ReferenceFileCategorySchema: import("@sinclair/typebox").TU
35
35
  export declare const MessageReferenceFileRefSchema: import("@sinclair/typebox").TObject<{
36
36
  path: import("@sinclair/typebox").TString;
37
37
  name: import("@sinclair/typebox").TString;
38
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
38
39
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
39
40
  blob_oid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
40
41
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -52,6 +53,13 @@ export declare const WorklistFeedbackItemSchema: import("@sinclair/typebox").TOb
52
53
  module_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
53
54
  latest_run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
54
55
  }>;
56
+ export declare const WorklistFeedbackGeneratedFileSchema: import("@sinclair/typebox").TObject<{
57
+ path: import("@sinclair/typebox").TString;
58
+ name: import("@sinclair/typebox").TString;
59
+ group: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
60
+ size_bytes: import("@sinclair/typebox").TInteger;
61
+ media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
62
+ }>;
55
63
  export declare const WorklistFeedbackRefSchema: import("@sinclair/typebox").TObject<{
56
64
  kind: import("@sinclair/typebox").TLiteral<"worklist_terminal">;
57
65
  status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"completed">, import("@sinclair/typebox").TLiteral<"failed">]>;
@@ -71,6 +79,14 @@ export declare const WorklistFeedbackRefSchema: import("@sinclair/typebox").TObj
71
79
  module_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
72
80
  latest_run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
73
81
  }>>;
82
+ final_note: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
83
+ generated_files: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
84
+ path: import("@sinclair/typebox").TString;
85
+ name: import("@sinclair/typebox").TString;
86
+ group: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
87
+ size_bytes: import("@sinclair/typebox").TInteger;
88
+ media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
89
+ }>>>;
74
90
  primary_task_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
75
91
  }>;
76
92
  export declare const MessageRefsSchema: import("@sinclair/typebox").TObject<{
@@ -83,6 +99,7 @@ export declare const MessageRefsSchema: import("@sinclair/typebox").TObject<{
83
99
  reference_file: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
84
100
  path: import("@sinclair/typebox").TString;
85
101
  name: import("@sinclair/typebox").TString;
102
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
86
103
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
87
104
  blob_oid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
88
105
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -111,6 +128,14 @@ export declare const MessageRefsSchema: import("@sinclair/typebox").TObject<{
111
128
  module_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
112
129
  latest_run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
113
130
  }>>;
131
+ final_note: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
132
+ generated_files: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
133
+ path: import("@sinclair/typebox").TString;
134
+ name: import("@sinclair/typebox").TString;
135
+ group: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
136
+ size_bytes: import("@sinclair/typebox").TInteger;
137
+ media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
138
+ }>>>;
114
139
  primary_task_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
115
140
  }>>;
116
141
  }>;
@@ -149,6 +174,7 @@ export declare const MessageProjectionSchema: import("@sinclair/typebox").TObjec
149
174
  reference_file: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
150
175
  path: import("@sinclair/typebox").TString;
151
176
  name: import("@sinclair/typebox").TString;
177
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
152
178
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
153
179
  blob_oid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
154
180
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -177,6 +203,14 @@ export declare const MessageProjectionSchema: import("@sinclair/typebox").TObjec
177
203
  module_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
178
204
  latest_run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
179
205
  }>>;
206
+ final_note: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
207
+ generated_files: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
208
+ path: import("@sinclair/typebox").TString;
209
+ name: import("@sinclair/typebox").TString;
210
+ group: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
211
+ size_bytes: import("@sinclair/typebox").TInteger;
212
+ media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
213
+ }>>>;
180
214
  primary_task_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
181
215
  }>>;
182
216
  }>>;
@@ -239,6 +273,7 @@ export declare const SendMainChatMessageResultSchema: import("@sinclair/typebox"
239
273
  reference_file: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
240
274
  path: import("@sinclair/typebox").TString;
241
275
  name: import("@sinclair/typebox").TString;
276
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
242
277
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
243
278
  blob_oid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
244
279
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -267,6 +302,14 @@ export declare const SendMainChatMessageResultSchema: import("@sinclair/typebox"
267
302
  module_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
268
303
  latest_run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
269
304
  }>>;
305
+ final_note: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
306
+ generated_files: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
307
+ path: import("@sinclair/typebox").TString;
308
+ name: import("@sinclair/typebox").TString;
309
+ group: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
310
+ size_bytes: import("@sinclair/typebox").TInteger;
311
+ media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
312
+ }>>>;
270
313
  primary_task_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
271
314
  }>>;
272
315
  }>>;
@@ -325,6 +368,7 @@ export declare const MessageCreatedEventPayloadSchema: import("@sinclair/typebox
325
368
  reference_file: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
326
369
  path: import("@sinclair/typebox").TString;
327
370
  name: import("@sinclair/typebox").TString;
371
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
328
372
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
329
373
  blob_oid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
330
374
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -353,6 +397,14 @@ export declare const MessageCreatedEventPayloadSchema: import("@sinclair/typebox
353
397
  module_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
354
398
  latest_run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
355
399
  }>>;
400
+ final_note: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
401
+ generated_files: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
402
+ path: import("@sinclair/typebox").TString;
403
+ name: import("@sinclair/typebox").TString;
404
+ group: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
405
+ size_bytes: import("@sinclair/typebox").TInteger;
406
+ media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
407
+ }>>>;
356
408
  primary_task_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
357
409
  }>>;
358
410
  }>>;
@@ -43,6 +43,7 @@ export const ReferenceFileCategorySchema = Type.Union([
43
43
  export const MessageReferenceFileRefSchema = Type.Object({
44
44
  path: Type.String({ minLength: 1 }),
45
45
  name: NonEmptyStringSchema,
46
+ source: Type.Union([Type.Literal("human_upload"), Type.Literal("tutti_output")]),
46
47
  category: ReferenceFileCategorySchema,
47
48
  blob_oid: Type.Optional(NonEmptyStringSchema),
48
49
  media_type: Type.Optional(NonEmptyStringSchema),
@@ -67,6 +68,13 @@ export const WorklistFeedbackItemSchema = Type.Object({
67
68
  module_name: Type.Optional(NonEmptyStringSchema),
68
69
  latest_run_result_id: Type.Optional(RunResultIdSchema),
69
70
  }, { additionalProperties: false });
71
+ export const WorklistFeedbackGeneratedFileSchema = Type.Object({
72
+ path: Type.String({ minLength: 1 }),
73
+ name: NonEmptyStringSchema,
74
+ group: Type.Optional(NonEmptyStringSchema),
75
+ size_bytes: Type.Integer({ minimum: 0 }),
76
+ media_type: Type.Optional(NonEmptyStringSchema),
77
+ }, { additionalProperties: false });
70
78
  export const WorklistFeedbackRefSchema = Type.Object({
71
79
  kind: Type.Literal("worklist_terminal"),
72
80
  status: Type.Union([Type.Literal("completed"), Type.Literal("failed")]),
@@ -79,6 +87,8 @@ export const WorklistFeedbackRefSchema = Type.Object({
79
87
  remaining: Type.Integer({ minimum: 0 }),
80
88
  }, { additionalProperties: false }),
81
89
  items: Type.Array(WorklistFeedbackItemSchema),
90
+ final_note: Type.Optional(Type.String()),
91
+ generated_files: Type.Optional(Type.Array(WorklistFeedbackGeneratedFileSchema)),
82
92
  primary_task_id: Type.Optional(TaskIdSchema),
83
93
  }, { additionalProperties: false });
84
94
  export const MessageRefsSchema = Type.Object({
@@ -475,6 +475,7 @@ export declare const TaskDetailUpdatedEventPayloadSchema: import("@sinclair/type
475
475
  finished_at: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
476
476
  }>>>;
477
477
  changed_paths: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
478
+ user_note_candidate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
478
479
  promotion: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
479
480
  status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"promoted">, import("@sinclair/typebox").TLiteral<"not_promoted">, import("@sinclair/typebox").TLiteral<"not_attempted">]>;
480
481
  summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -6,7 +6,7 @@ import type { ProviderUsageBreakdownProjectionSchema, ProviderUsageCategorySchem
6
6
  import type { ProjectTimelineItemKindSchema, ProjectTimelineItemSchema, ProjectTimelineItemStatusSchema, ProjectTimelineResponseSchema } from "./project-timeline.js";
7
7
  import type { PresignedUploadPutSchema, RelayUploadProjectionSchema, RelayUploadPurposeSchema, Sha256DigestSchema, StagedUploadReferenceSchema, StartRelayUploadDispositionSchema, StartRelayUploadPayloadSchema, StartRelayUploadResultSchema } from "./uploads.js";
8
8
  import type { MarkReadDispositionSchema, MarkReadPayloadSchema, MarkReadResultSchema, ReadStateScopeProjectionSchema, ReadStateScopeSchema, ReadStateSummaryProjectionSchema } from "./read-state.js";
9
- import type { GetMessagesRequestSchema, MessageCreatedEventPayloadSchema, MessageProjectionSchema, MessageReferenceFileRefSchema, ReferenceFileCategorySchema, SendMainChatMessageCreatedDispositionSchema, SendMainChatMessageDispositionSchema, SendMainChatMessagePayloadSchema, SendMainChatMessageResultSchema, WorklistFeedbackItemSchema, WorklistFeedbackRefSchema } from "./messages.js";
9
+ import type { GetMessagesRequestSchema, MessageCreatedEventPayloadSchema, MessageProjectionSchema, MessageReferenceFileRefSchema, ReferenceFileCategorySchema, SendMainChatMessageCreatedDispositionSchema, SendMainChatMessageDispositionSchema, SendMainChatMessagePayloadSchema, SendMainChatMessageResultSchema, WorklistFeedbackGeneratedFileSchema, WorklistFeedbackItemSchema, WorklistFeedbackRefSchema } from "./messages.js";
10
10
  import type { CheckSkipReasonCodeSchema, ExternalSideEffectSummaryProjectionSchema, GetRecoverySummariesRequestSchema, GetRecoverySummaryResponseSchema, RecoverySummaryProjectionSchema, RunResultProjectionSchema, ScratchpadProjectionSchema, ScratchpadReceiptProjectionSchema, TaskContractProjectionSchema, TaskDetailProjectionSchema, TaskDetailResultProjectionSchema, TaskModuleProjectionSchema, TaskProjectionSchema, TaskStatusSchema, WorklistProjectionSchema } from "./work-items.js";
11
11
  import type { ActiveApprovalProjectionSchema, ApprovalCommandProjectionSchema, ApprovalDecisionKindSchema, ApprovalDecisionOptionProjectionSchema, ApprovalFileChangeProjectionSchema, ApprovalPermissionsProjectionSchema, ApprovalRequestKindSchema, ApprovalRequestProjectionSchema, ApprovalResolutionOutcomeSchema, ApprovalResolutionProjectionSchema, DecideApprovalDispositionSchema, DecideApprovalPayloadSchema, DecideApprovalResultSchema } from "./approvals.js";
12
12
  import type { ActiveClarificationProjectionSchema, ClarificationChangedEventPayloadSchema, ClarificationOwnerProjectionSchema, ClarificationRequestPayloadSchema, ClarificationRoundProjectionSchema, ClarificationRoundSummaryProjectionSchema, ClarificationSuccessorRefSchema, ClarificationThreadProjectionSchema, ContextRefSchema, GetClarificationRoundMessagesRequestSchema, GetClarificationRoundResponseSchema, GetClarificationThreadResponseSchema, HumanInteractionPayloadSchema, HumanRequestPayloadSchema, SendClarificationRoundMessageDispositionSchema, SendClarificationRoundMessagePayloadSchema, SendClarificationRoundMessageResultSchema, SubmitClarificationRoundDispositionSchema, SubmitClarificationRoundPayloadSchema, SubmitClarificationRoundResultSchema } from "./clarifications.js";
@@ -98,6 +98,7 @@ export type MarkReadResponse = CommandResponse<MarkReadDisposition, MarkReadResu
98
98
  export type ReferenceFileCategory = Static<typeof ReferenceFileCategorySchema>;
99
99
  export type MessageReferenceFileRef = Static<typeof MessageReferenceFileRefSchema>;
100
100
  export type WorklistFeedbackItem = Static<typeof WorklistFeedbackItemSchema>;
101
+ export type WorklistFeedbackGeneratedFile = Static<typeof WorklistFeedbackGeneratedFileSchema>;
101
102
  export type WorklistFeedbackRef = Static<typeof WorklistFeedbackRefSchema>;
102
103
  export type MessageProjection = Static<typeof MessageProjectionSchema>;
103
104
  export type MessageWindow = TimelineWindow<MessageProjection>;
@@ -250,6 +250,7 @@ export declare const ReferenceDirectoryProjectionSchema: import("@sinclair/typeb
250
250
  index_path: import("@sinclair/typebox").TLiteral<"docs/reference/README.md">;
251
251
  files_path: import("@sinclair/typebox").TLiteral<"docs/reference/files">;
252
252
  images_path: import("@sinclair/typebox").TLiteral<"docs/reference/images">;
253
+ tutti_path: import("@sinclair/typebox").TLiteral<"docs/reference/tutti">;
253
254
  index_status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"available">, import("@sinclair/typebox").TLiteral<"missing">, import("@sinclair/typebox").TLiteral<"unreadable">]>;
254
255
  index_unreadable_reason: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"restricted_path">, import("@sinclair/typebox").TLiteral<"secret_like">, import("@sinclair/typebox").TLiteral<"binary">, import("@sinclair/typebox").TLiteral<"unsupported_encoding">, import("@sinclair/typebox").TLiteral<"too_large">]>>;
255
256
  }>;
@@ -265,6 +266,7 @@ export declare const ReferenceSummaryProjectionSchema: import("@sinclair/typebox
265
266
  export declare const ReferenceFileProjectionSchema: import("@sinclair/typebox").TObject<{
266
267
  path: import("@sinclair/typebox").TString;
267
268
  name: import("@sinclair/typebox").TString;
269
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
268
270
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
269
271
  size_bytes: import("@sinclair/typebox").TInteger;
270
272
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -306,12 +308,14 @@ export declare const GetReferenceFilesResponseSchema: import("@sinclair/typebox"
306
308
  index_path: import("@sinclair/typebox").TLiteral<"docs/reference/README.md">;
307
309
  files_path: import("@sinclair/typebox").TLiteral<"docs/reference/files">;
308
310
  images_path: import("@sinclair/typebox").TLiteral<"docs/reference/images">;
311
+ tutti_path: import("@sinclair/typebox").TLiteral<"docs/reference/tutti">;
309
312
  index_status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"available">, import("@sinclair/typebox").TLiteral<"missing">, import("@sinclair/typebox").TLiteral<"unreadable">]>;
310
313
  index_unreadable_reason: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"restricted_path">, import("@sinclair/typebox").TLiteral<"secret_like">, import("@sinclair/typebox").TLiteral<"binary">, import("@sinclair/typebox").TLiteral<"unsupported_encoding">, import("@sinclair/typebox").TLiteral<"too_large">]>>;
311
314
  }>;
312
315
  items: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
313
316
  path: import("@sinclair/typebox").TString;
314
317
  name: import("@sinclair/typebox").TString;
318
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
315
319
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
316
320
  size_bytes: import("@sinclair/typebox").TInteger;
317
321
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -355,6 +359,7 @@ export declare const UploadReferenceFileResultSchema: import("@sinclair/typebox"
355
359
  file: import("@sinclair/typebox").TObject<{
356
360
  path: import("@sinclair/typebox").TString;
357
361
  name: import("@sinclair/typebox").TString;
362
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
358
363
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
359
364
  size_bytes: import("@sinclair/typebox").TInteger;
360
365
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -409,6 +414,7 @@ export declare const UploadReferenceFileResultSchema: import("@sinclair/typebox"
409
414
  reference_file: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
410
415
  path: import("@sinclair/typebox").TString;
411
416
  name: import("@sinclair/typebox").TString;
417
+ source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human_upload">, import("@sinclair/typebox").TLiteral<"tutti_output">]>;
412
418
  category: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"file">, import("@sinclair/typebox").TLiteral<"image">]>;
413
419
  blob_oid: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
414
420
  media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -437,6 +443,14 @@ export declare const UploadReferenceFileResultSchema: import("@sinclair/typebox"
437
443
  module_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
438
444
  latest_run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
439
445
  }>>;
446
+ final_note: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
447
+ generated_files: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
448
+ path: import("@sinclair/typebox").TString;
449
+ name: import("@sinclair/typebox").TString;
450
+ group: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
451
+ size_bytes: import("@sinclair/typebox").TInteger;
452
+ media_type: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
453
+ }>>>;
440
454
  primary_task_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
441
455
  }>>;
442
456
  }>>;
@@ -164,6 +164,7 @@ export const ReferenceDirectoryProjectionSchema = Type.Object({
164
164
  index_path: Type.Literal("docs/reference/README.md"),
165
165
  files_path: Type.Literal("docs/reference/files"),
166
166
  images_path: Type.Literal("docs/reference/images"),
167
+ tutti_path: Type.Literal("docs/reference/tutti"),
167
168
  index_status: Type.Union([
168
169
  Type.Literal("available"),
169
170
  Type.Literal("missing"),
@@ -195,6 +196,7 @@ export const ReferenceSummaryProjectionSchema = Type.Object({
195
196
  export const ReferenceFileProjectionSchema = Type.Object({
196
197
  path: ViewerPathSchema,
197
198
  name: NonEmptyStringSchema,
199
+ source: Type.Union([Type.Literal("human_upload"), Type.Literal("tutti_output")]),
198
200
  category: ReferenceFileCategorySchema,
199
201
  size_bytes: Type.Integer({ minimum: 0 }),
200
202
  media_type: Type.Optional(NonEmptyStringSchema),
@@ -138,6 +138,7 @@ export declare const TaskDetailResultProjectionSchema: import("@sinclair/typebox
138
138
  finished_at: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
139
139
  }>>>;
140
140
  changed_paths: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
141
+ user_note_candidate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
141
142
  promotion: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
142
143
  status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"promoted">, import("@sinclair/typebox").TLiteral<"not_promoted">, import("@sinclair/typebox").TLiteral<"not_attempted">]>;
143
144
  summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -193,6 +194,7 @@ export declare const TaskDetailProjectionSchema: import("@sinclair/typebox").TOb
193
194
  finished_at: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
194
195
  }>>>;
195
196
  changed_paths: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
197
+ user_note_candidate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
196
198
  promotion: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
197
199
  status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"promoted">, import("@sinclair/typebox").TLiteral<"not_promoted">, import("@sinclair/typebox").TLiteral<"not_attempted">]>;
198
200
  summary: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
@@ -234,6 +236,7 @@ export declare const RunResultProjectionSchema: import("@sinclair/typebox").TUni
234
236
  result_kind: import("@sinclair/typebox").TLiteral<"finished">;
235
237
  outcome: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"completed">, import("@sinclair/typebox").TLiteral<"failed">]>;
236
238
  summary: import("@sinclair/typebox").TString;
239
+ user_note_candidate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
237
240
  checks: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"passed">, import("@sinclair/typebox").TLiteral<"failed">, import("@sinclair/typebox").TLiteral<"skipped">]>;
238
241
  docs: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"updated">, import("@sinclair/typebox").TLiteral<"checked_no_change">, import("@sinclair/typebox").TLiteral<"not_checked">, import("@sinclair/typebox").TLiteral<"sync_deferred">]>;
239
242
  skip_reason_code: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"no_validation_command_found">, import("@sinclair/typebox").TLiteral<"project_has_no_test_setup">, import("@sinclair/typebox").TLiteral<"validation_not_applicable">, import("@sinclair/typebox").TLiteral<"command_prerequisite_missing">, import("@sinclair/typebox").TLiteral<"command_requires_external_service">, import("@sinclair/typebox").TLiteral<"command_requires_secret">, import("@sinclair/typebox").TLiteral<"command_requires_interactive_input">, import("@sinclair/typebox").TLiteral<"command_too_expensive_for_mvp">, import("@sinclair/typebox").TLiteral<"unsafe_command_blocked">, import("@sinclair/typebox").TLiteral<"known_failing_baseline">]>>;
@@ -127,6 +127,7 @@ export const TaskDetailResultProjectionSchema = Type.Object({
127
127
  skip_reason_summary: Type.Optional(Type.String()),
128
128
  external_side_effects: Type.Optional(Type.Array(ExternalSideEffectSummaryProjectionSchema)),
129
129
  changed_paths: Type.Optional(Type.Array(Type.String())),
130
+ user_note_candidate: Type.Optional(Type.String()),
130
131
  promotion: Type.Optional(Type.Object({
131
132
  status: Type.Union([
132
133
  Type.Literal("promoted"),
@@ -170,6 +171,7 @@ export const RunResultProjectionSchema = Type.Union([
170
171
  result_kind: Type.Literal("finished"),
171
172
  outcome: Type.Union([Type.Literal("completed"), Type.Literal("failed")]),
172
173
  summary: Type.String(),
174
+ user_note_candidate: Type.Optional(Type.String()),
173
175
  checks: Type.Union([Type.Literal("passed"), Type.Literal("failed"), Type.Literal("skipped")]),
174
176
  docs: Type.Union([
175
177
  Type.Literal("updated"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfey/tutti",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -45,7 +45,7 @@ Provider validation 也使用 OpenAI Responses API,但它只是启动前 crede
45
45
  - 2026-06-28:`scratchpad_refresh` provider raw output 改为 `{ result: ... }` nested branch schema,`ready` 只输出 `scratchpad_snapshot`,`needs_human` 只输出 `request_payload`,adapter 解包后保持下游 workflow union 不变。
46
46
  - 2026-06-28:`task_compile` provider-facing input 改为压缩后的 Scratchpad / Worklist / optional clarification request + answer messages,不再注入 `context_entry_json`、workflow refs、审计字段、排序字段、时间戳或完整 message projection;provider raw output 改为 `{ result: ... }` 互斥分支,分支由 `proposal` 或 `clarification_request_payload` 字段存在性表达,不再输出 `decision`。proposal task 只输出 `module_ref / title / goal / scope`,runner adapter 再映射为 Control Plane 内部 proposal。
47
47
  - 2026-06-28:`context_sync` provider-facing input 去掉 `context_entry_json`、workflow/activity refs、触发原因和诊断型字段;输出去掉 `decision`、`doc_key`、`reason`、`evidence_paths`、`checked_paths`、`skipped_paths` 和 `open_questions`,只保留 `summary` 与 `updates[].path/content`,Control Plane 通过 `updates.length` 判断是否写入。
48
- - 2026-06-29:`task-run` / `task-continuation` / `task-retry` provider-facing input 统一只保留 `title / goal / scope` 加必要的 `continuation` 或 `correction` block,不再注入 `context_entry_json`、task id、task summary 或 Run lineage;`task-retry` correction block 只保留 summary、reason code、guidance 和可选 promotion failure 摘要;provider raw output 改为 `{ result: ... }` 互斥分支,只输出 `completed.summary`、`completed_no_repo_changes.summary`、`needs_human.{title,summary,request}` 或 `failed.summary`。
48
+ - 2026-06-29:`task-run` / `task-continuation` / `task-retry` provider-facing input 统一只保留 `title / goal / scope` 加必要的 `continuation` 或 `correction` block,不再注入 `context_entry_json`、task id、task summary 或 Run lineage;`task-retry` correction block 只保留 summary、reason code、guidance 和可选 promotion failure 摘要;provider raw output 改为 `{ result: ... }` 互斥分支,只输出 `completed.{summary,user_note_candidate}`、`completed_no_repo_changes.{summary,user_note_candidate}`、`needs_human.{title,summary,request}` 或 `failed.summary`。
49
49
  - 2026-06-29:`follow_up_check` provider-facing input 去掉 `context_entry_json`、task id/status、activity ref、result kind、Run lineage、message id、作者 identity 和时间戳,只保留 `title / goal / scope`、`previous_run.summary`、`previous_run.clarification_request_payload` 与 `answers[]`;provider raw output 改为 `{ result: ... }` 互斥分支,只输出 `resume.summary`、`needs_more_input.{title,summary,request}` 或 `requires_retasking.summary`。
50
50
  - 2026-06-29:`reference_summary_refresh` provider-facing input 清零;runner 复制目标 reference 文件到独立临时目录,并以该目录作为 app-server `cwd` 和唯一 readable path。prompt 不再接收 workflow/activity trace anchors、原始路径、file metadata、blob 或 media type;provider raw output 改为 `{ result: ... }` 互斥分支,只输出 `summarized.summary` 或自然语言 `unavailable.reason`。
51
51
  - 2026-07-02:新增 `project_brief_refresh`;在四个 canonical Project Docs 创建、同步、被成功 Run promotion 修改,或 provider 配置完成后需要 backfill 时尽力刷新 host-local Project Brief projection。provider-facing input 只包含四份 Project Docs 的 bounded source / status,输出 `product_summary / tech_summary / structure_summary / principles_summary`。
@@ -358,7 +358,7 @@ Provider raw 输出:根对象只包含 `result`;`result` 内二选一输出
358
358
  - Reference Files 不通过 built-in skill 暴露;若任务契约或 Project Docs 指向 `docs/reference/` 中资料,Codex 可直接读取相关 repo 文件正文。
359
359
  - 不直接读取主群聊或 Scratchpad;这些不作为 hidden scope。
360
360
 
361
- 输出:根对象只包含 `result`;`result` 内四选一输出 `completed.summary`、`completed_no_repo_changes.summary`、`needs_human.{title,summary,request}` 或 `failed.summary`。`completed_no_repo_changes` 只用于任务契约不要求 repository file changes 的情况。`needs_human` payload 必须能直接作为 task-bound clarification request 使用:解释为什么 frozen contract 下无法安全继续,并提出一个具体、可回答、非 secret 的问题。
361
+ 输出:根对象只包含 `result`;`result` 内四选一输出 `completed.{summary,user_note_candidate}`、`completed_no_repo_changes.{summary,user_note_candidate}`、`needs_human.{title,summary,request}` 或 `failed.summary`。`user_note_candidate` 是可选最终反馈候选,字段必填但可为 `null`;生成给用户直接查看的文件应写入 `docs/reference/tutti/`。`completed_no_repo_changes` 只用于任务契约不要求 repository file changes 的情况。`needs_human` payload 必须能直接作为 task-bound clarification request 使用:解释为什么 frozen contract 下无法安全继续,并提出一个具体、可回答、非 secret 的问题。
362
362
 
363
363
  下游:Run pipeline 收集真实 Git diff 作为 `changed_paths`;`needs_human` 时 Control Plane 记录 `Run.needs_human`、打开 task-bound clarification 并把 task 迁回 `pending`;有 repo candidate 的 `completed` 结果从 Git changed paths 派生 docs 状态,再执行 checks、result commit 和 mechanical promotion;空 diff 的 `completed_no_repo_changes` 结果跳过 checks / commit / promotion,记录 `promotion.status = not_attempted`。
364
364
 
@@ -9,7 +9,8 @@ Templates in this directory may describe task contracts, repo evidence, check ex
9
9
 
10
10
  `task-run.md` allows `needs_human` only for human requirement decisions, non-secret context, or risk confirmation. Unusable candidates, ordinary missing diffs, or repo/tooling errors that prevent implementation should be returned as `failed` so the Run does not open task-bound clarification incorrectly. If the task contract does not require repository file changes, the output can use `completed_no_repo_changes`; otherwise a completed implementation is expected to produce a candidate diff. If the candidate is complete but Codex self-validation commands are unavailable or blocked, the task-run output should still be `completed`; Tutti checks are the authoritative validation gate.
11
11
  Initial `task-run.md`, active `task-continuation.md`, and active pipeline `task-retry.md` receive only the compact task contract fields `title / goal / scope`; continuation adds the required `continuation` block, and pipeline self-correction retry adds the required `correction` block with only the previous failure summary, machine-generated reason code, correction guidance, and optional promotion failure summary. Provider-facing prompts do not receive task ids, task summaries, Run lineage, workflow anchors, changed paths, docs status, checks status, or the safety audit context entry.
12
- All three Run templates use a slim mutually exclusive structured output schema under `result`: exactly one of `completed.summary`, `completed_no_repo_changes.summary`, `needs_human.{title,summary,request}`, or `failed.summary`. The `summary` is a concise, human-readable result note for project members who may not inspect the code. It should describe what changed, what was found, or why the Run cannot continue; checks, docs, promotion, changed paths, and other Tutti status stay in structured fields derived by the Run pipeline. They do not ask Codex to self-report docs status or changed paths; both come from Run pipeline Git diff and derived projection.
12
+ All three Run templates use a slim mutually exclusive structured output schema under `result`: exactly one of `completed.{summary,user_note_candidate}`, `completed_no_repo_changes.{summary,user_note_candidate}`, `needs_human.{title,summary,request}`, or `failed.summary`. The `summary` is a concise, human-readable result note for project members who may not inspect the code. Completed branches also require `user_note_candidate`, which is either a short user-facing final-card sentence or `null`; it must not repeat `summary` or include file paths. Checks, docs, promotion, changed paths, and other Tutti status stay in structured fields derived by the Run pipeline. They do not ask Codex to self-report docs status or changed paths; both come from Run pipeline Git diff and derived projection.
13
+ Run templates describe `docs/reference/` as a user-visible file exchange area. Human uploads remain under `docs/reference/files/` and `docs/reference/images/`; Tutti-generated user-visible files must be written under `docs/reference/tutti/`, with `docs/reference/tutti/<meaningful-folder>/...` used when the folder name should be shown as a References UI group. Generated files under `docs/reference/tutti/` are discovered from promoted changed paths and rendered by References automatically.
13
14
  Initial `task-run.md`, active `task-continuation.md`, and active pipeline `task-retry.md` also instruct Codex to write or update the single active `tutti.artifact.json` manifest only when the task creates or updates a member-viewable visual artifact. The manifest must include a viewer-facing `artifact.title` and must set `artifact.network: true` when the preview loads remote browser resources. The manifest remains repo truth and is not reported through the structured output schema.
14
15
  Active task-bound follow-up still only starts continuation Runs from `Run.needs_human`. Pipeline self-correction retry happens before a terminal Run result is recorded and does not open clarification.
15
16
  Provider transient retry is separate from self-correction. If a retryable Codex app-server workspace-write failure occurs before usable structured output, Run pipeline may rerun the same prompt family once in a fresh run workspace: initial Runs stay on `task-run.md`, continuation Runs stay on `task-continuation.md`, and self-correction attempts stay on `task-retry.md`. This retry does not add `RunCorrectionContext` unless the failed attempt was already a self-correction attempt.
@@ -57,6 +57,8 @@ Use attached skills only when they help the current task:
57
57
 
58
58
  Human-uploaded reference material is kept in the repository under `docs/reference/`. If the task contract, project docs, or clarification answer makes a reference file relevant, read the actual repo file before relying on it. Do not infer reference contents from names, upload messages, media types, or paths.
59
59
 
60
+ `docs/reference/` is a user-visible file exchange area. Human uploads live under `docs/reference/files/` and `docs/reference/images/`. When this task produces files that project members should inspect directly, write them under `docs/reference/tutti/`. Use `docs/reference/tutti/<meaningful-folder>/...` when a folder name helps explain the output group; that folder name is shown directly in the References UI. Do not create ad hoc folders at the `docs/reference/` root. Files under `docs/reference/tutti/` are displayed automatically, so `user_note_candidate` may mention generated file names but should not include paths.
61
+
60
62
  # Documentation
61
63
 
62
64
  If this change affects stable project facts, usage, public behavior, interfaces, setup, project organization, maintenance context, or project working rules, update the relevant project documentation in the same worktree.
@@ -88,6 +90,8 @@ If the task creates or updates a user-viewable web page, static page, single-pag
88
90
 
89
91
  Write `summary` as a concise, human-readable result note for project members who may not inspect the code: what changed, what was found, or why the Run cannot continue. Do not narrate process, repeat structured Tutti status such as checks / docs / promotion / changed paths, or include secrets, host paths, raw logs, provider output, or long excerpts.
90
92
 
93
+ For `completed` and `completed_no_repo_changes`, also return `user_note_candidate`. Use a short user-facing sentence only when the final completion card should tell project members a conclusion, result, or generated file name directly. Use `null` when there is no distinct user-facing note. Do not repeat `summary`, and do not include file paths.
94
+
91
95
  # Output
92
96
 
93
97
  Return JSON matching the structured output schema. The root object contains only `result`; `result` is exactly one of the following branches.
@@ -98,7 +102,8 @@ Completed:
98
102
  {
99
103
  "result": {
100
104
  "completed": {
101
- "summary": "The clarified implementation is now complete and the relevant project notes reflect the result."
105
+ "summary": "The clarified implementation is now complete and the relevant project notes reflect the result.",
106
+ "user_note_candidate": "The generated comparison file is ready to review."
102
107
  }
103
108
  }
104
109
  }
@@ -110,7 +115,8 @@ Completed with no repository changes:
110
115
  {
111
116
  "result": {
112
117
  "completed_no_repo_changes": {
113
- "summary": "The clarified task is complete and did not require repository changes."
118
+ "summary": "The clarified task is complete and did not require repository changes.",
119
+ "user_note_candidate": null
114
120
  }
115
121
  }
116
122
  }
@@ -62,6 +62,8 @@ Use attached skills only when they help the current task:
62
62
 
63
63
  Human-uploaded reference material is kept in the repository under `docs/reference/`. If the task contract, project docs, or correction context makes a reference file relevant, read the actual repo file before relying on it. Do not infer reference contents from names, upload messages, media types, or paths.
64
64
 
65
+ `docs/reference/` is a user-visible file exchange area. Human uploads live under `docs/reference/files/` and `docs/reference/images/`. When this task produces files that project members should inspect directly, write them under `docs/reference/tutti/`. Use `docs/reference/tutti/<meaningful-folder>/...` when a folder name helps explain the output group; that folder name is shown directly in the References UI. Do not create ad hoc folders at the `docs/reference/` root. Files under `docs/reference/tutti/` are displayed automatically, so `user_note_candidate` may mention generated file names but should not include paths.
66
+
65
67
  # Documentation
66
68
 
67
69
  If this change affects stable project facts, usage, public behavior, interfaces, setup, project organization, maintenance context, or project working rules, update the relevant project documentation in the same worktree.
@@ -93,6 +95,8 @@ If the task creates or updates a user-viewable web page, static page, single-pag
93
95
 
94
96
  Write `summary` as a concise, human-readable result note for project members who may not inspect the code: what changed, what was found, or why the Run cannot continue. Do not narrate process, repeat structured Tutti status such as checks / docs / promotion / changed paths, or include secrets, host paths, raw logs, provider output, or long excerpts.
95
97
 
98
+ For `completed` and `completed_no_repo_changes`, also return `user_note_candidate`. Use a short user-facing sentence only when the final completion card should tell project members a conclusion, result, or generated file name directly. Use `null` when there is no distinct user-facing note. Do not repeat `summary`, and do not include file paths.
99
+
96
100
  # Output
97
101
 
98
102
  Return JSON matching the structured output schema. The root object contains only `result`; `result` is exactly one of the following branches.
@@ -103,7 +107,8 @@ Completed:
103
107
  {
104
108
  "result": {
105
109
  "completed": {
106
- "summary": "The task result is now complete within the frozen scope after correcting the previous candidate."
110
+ "summary": "The task result is now complete within the frozen scope after correcting the previous candidate.",
111
+ "user_note_candidate": "The corrected export file is ready to review."
107
112
  }
108
113
  }
109
114
  }
@@ -115,7 +120,8 @@ Completed with no repository changes:
115
120
  {
116
121
  "result": {
117
122
  "completed_no_repo_changes": {
118
- "summary": "The requested retry is complete and did not require repository changes."
123
+ "summary": "The requested retry is complete and did not require repository changes.",
124
+ "user_note_candidate": null
119
125
  }
120
126
  }
121
127
  }
@@ -44,6 +44,8 @@ Use attached skills only when they help the current task:
44
44
 
45
45
  Human-uploaded reference material is kept in the repository under `docs/reference/`. If the task contract or project docs make a reference file relevant, read the actual repo file before relying on it. Do not infer reference contents from names, upload messages, media types, or paths.
46
46
 
47
+ `docs/reference/` is a user-visible file exchange area. Human uploads live under `docs/reference/files/` and `docs/reference/images/`. When this task produces files that project members should inspect directly, write them under `docs/reference/tutti/`. Use `docs/reference/tutti/<meaningful-folder>/...` when a folder name helps explain the output group; that folder name is shown directly in the References UI. Do not create ad hoc folders at the `docs/reference/` root. Files under `docs/reference/tutti/` are displayed automatically, so `user_note_candidate` may mention generated file names but should not include paths.
48
+
47
49
  # Documentation
48
50
 
49
51
  If this change affects stable project facts, usage, public behavior, interfaces, setup, project organization, maintenance context, or project working rules, update the relevant project documentation in the same worktree.
@@ -75,6 +77,8 @@ If the task creates or updates a user-viewable web page, static page, single-pag
75
77
 
76
78
  Write `summary` as a concise, human-readable result note for project members who may not inspect the code: what changed, what was found, or why the Run cannot continue. Do not narrate process, repeat structured Tutti status such as checks / docs / promotion / changed paths, or include secrets, host paths, raw logs, provider output, or long excerpts.
77
79
 
80
+ For `completed` and `completed_no_repo_changes`, also return `user_note_candidate`. Use a short user-facing sentence only when the final completion card should tell project members a conclusion, result, or generated file name directly. Use `null` when there is no distinct user-facing note. Do not repeat `summary`, and do not include file paths.
81
+
78
82
  # Output
79
83
 
80
84
  Return JSON matching the structured output schema. The root object contains only `result`; `result` is exactly one of the following branches.
@@ -85,7 +89,8 @@ Completed:
85
89
  {
86
90
  "result": {
87
91
  "completed": {
88
- "summary": "The requested UI state is now available, with the related usage notes updated."
92
+ "summary": "The requested UI state is now available, with the related usage notes updated.",
93
+ "user_note_candidate": "The updated usage notes file is ready to review."
89
94
  }
90
95
  }
91
96
  }
@@ -97,7 +102,8 @@ Completed with no repository changes:
97
102
  {
98
103
  "result": {
99
104
  "completed_no_repo_changes": {
100
- "summary": "The requested review is complete and did not require repository changes."
105
+ "summary": "The requested review is complete and did not require repository changes.",
106
+ "user_note_candidate": null
101
107
  }
102
108
  }
103
109
  }