@xfey/tutti 0.1.110 → 0.1.111

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 (26) hide show
  1. package/README.md +1 -1
  2. package/dist/chat-assistant/index.js +7 -0
  3. package/dist/collaboration-ingestion/external-source.js +2 -0
  4. package/dist/collaboration-ingestion/main-chat.js +9 -2
  5. package/dist/collaboration-ingestion/types.d.ts +1 -0
  6. package/dist/control-plane/scratchpad-source-messages.js +9 -3
  7. package/dist/control-plane/task-source-context-types.d.ts +1 -1
  8. package/dist/control-plane/task-source-context.js +4 -2
  9. package/dist/server-shell/cli/relay-registration.js +1 -0
  10. package/dist/server-shell/http/routes/agent-context-reference-routes.js +1 -3
  11. package/node_modules/@tutti/relay-client/dist/host-control.d.ts +1 -0
  12. package/node_modules/@tutti/relay-client/dist/host-control.js +3 -0
  13. package/node_modules/@tutti/shared/dist/schemas/api/clarifications.d.ts +1 -0
  14. package/node_modules/@tutti/shared/dist/schemas/api/messages.d.ts +4 -0
  15. package/node_modules/@tutti/shared/dist/schemas/api/messages.js +1 -0
  16. package/node_modules/@tutti/shared/dist/schemas/api/viewer-reference.d.ts +1 -0
  17. package/node_modules/@tutti/shared/dist/schemas/internal/platform-integration.d.ts +43 -2
  18. package/node_modules/@tutti/shared/dist/schemas/internal/platform-integration.js +14 -2
  19. package/package.json +1 -1
  20. package/prompts/chat-assistant.md +1 -0
  21. package/prompts/procedures/scratchpad-refresh.md +22 -2
  22. package/prompts/procedures/task-compile.md +1 -0
  23. package/prompts/runs/task-execute.md +2 -0
  24. package/web/assets/{homepage-motion-scene-rxYjg-zc.js → homepage-motion-scene-TmkKf8wQ.js} +1 -1
  25. package/web/assets/{index-BrKWdtKZ.js → index-B1oL1p9_.js} +2 -2
  26. package/web/index.html +1 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  `apps/server` 是 Tutti 的项目 host service,也是机器级 Local Console 的进程入口。
6
6
 
7
- `0.1.110` 发布候选加入每次 Chat invocation 的外部资料核验规则、本地/外部 provenance、从实际读取证据派生的回答来源线索,以及隔离多轮模型 smoke;配套 F.3 增量支持群资料确认与普通云盘文件。需要同步 Web/Relay/Integration 后再升级 Host;实际发布与真人验收状态见同一[按需资料计划](../../docs/roadmap/feishu-on-demand-reference-plan.md)。历史快照不删除,读取线索不继承新鲜度或权限。
7
+ `0.1.110` 已发布每次 Chat invocation 的外部资料核验规则、本地/外部 provenance、从实际读取证据派生的回答来源线索,以及隔离多轮模型 smoke;配套 F.3 增量支持群资料确认与普通云盘文件。Web/Relay/Integration 已先行同步,registry byte match 与本机 CLI/Console/原在线 Host 更新通过;实际发布与剩余真人验收状态见同一[按需资料计划](../../docs/roadmap/feishu-on-demand-reference-plan.md)。历史快照不删除,读取线索不继承新鲜度或权限。
8
8
 
9
9
  已发布的 `0.1.109` 统一验证 Codex `skills/extraRoots/set` / `skills/list` 与实际 `SKILL.md` 文件身份;Chat 的安全阶段日志可通过 invocation ref 关联外部 Reference 读取。候选安装/升级、registry byte match、本机 CLI/Console/测试 Host 更新及更新后 Docx 真人读取闭环已通过;连续更新/同次 pin/附件/失权 live 矩阵仍独立跟踪。证据见[按需资料计划](../../docs/roadmap/feishu-on-demand-reference-plan.md),不以安装版本代替实际读取证据。
10
10
 
@@ -49,6 +49,7 @@ function assistantFailureMessage() {
49
49
  function messageToContext(message) {
50
50
  const authorDisplayName = message.author.display_name?.trim();
51
51
  return {
52
+ ...(message.refs?.development_operator === true ? { source_role: "operator" } : {}),
52
53
  ...(authorDisplayName === undefined || authorDisplayName === ""
53
54
  ? {}
54
55
  : { author_display_name: authorDisplayName }),
@@ -57,6 +58,8 @@ function messageToContext(message) {
57
58
  };
58
59
  }
59
60
  function messageRole(message) {
61
+ if (message.author.kind === "system" && message.refs?.development_operator === true)
62
+ return "operator";
60
63
  if (message.author.kind === "agent") {
61
64
  return "tutti";
62
65
  }
@@ -110,6 +113,10 @@ export class ReadOnlyChatAssistant {
110
113
  this.maxQueuedMentions = options.maxQueuedMentions ?? 8;
111
114
  }
112
115
  enqueue(input) {
116
+ if (input.message.author.kind !== "human" &&
117
+ !(input.message.author.kind === "system" && input.message.refs?.development_operator === true)) {
118
+ return { triggered: false };
119
+ }
113
120
  if (!containsTuttiMention(messageTextForTuttiMention(input.message))) {
114
121
  return { triggered: false };
115
122
  }
@@ -83,6 +83,7 @@ export function ingestTrustedConversationSource(options) {
83
83
  commandId: options.command.command_id,
84
84
  payload: { body: source.content.text },
85
85
  author: {
86
+ ...(options.command.actor.kind === "bot" ? { kind: "development_operator" } : {}),
86
87
  account_ref: options.command.actor.account_ref,
87
88
  display_name: options.command.actor.display_name,
88
89
  },
@@ -100,6 +101,7 @@ export function ingestTrustedConversationSource(options) {
100
101
  external_message_ref: source.locator.message_ref,
101
102
  binding_ref: options.command.binding_ref,
102
103
  receipt_key: options.command.receipt.receipt_key,
104
+ ...(options.command.actor.kind === "bot" ? { actor_kind: "bot" } : {}),
103
105
  ...(source.external_references === undefined
104
106
  ? {}
105
107
  : { external_references: source.external_references }),
@@ -10,6 +10,9 @@ export function ingestMainChatMessage(options) {
10
10
  payload: {
11
11
  ...options.payload,
12
12
  author_ref: options.author.account_ref,
13
+ ...(options.author.kind === "development_operator"
14
+ ? { author_kind: "development_operator" }
15
+ : {}),
13
16
  ...(options.idempotencyContext === undefined
14
17
  ? {}
15
18
  : { ingestion_context: options.idempotencyContext }),
@@ -23,12 +26,16 @@ export function ingestMainChatMessage(options) {
23
26
  const message = createMainChatMessage(tx, {
24
27
  body: materialized.body,
25
28
  author: {
26
- kind: "human",
29
+ kind: options.author.kind === "development_operator" ? "system" : "human",
27
30
  ref: options.author.account_ref,
28
31
  display_name: options.author.display_name,
29
32
  ...(options.author.avatar === undefined ? {} : { avatar: options.author.avatar }),
30
33
  },
31
- ...(materialized.refs === undefined ? {} : { refs: materialized.refs }),
34
+ ...(options.author.kind === "development_operator"
35
+ ? { refs: { ...materialized.refs, development_operator: true } }
36
+ : materialized.refs === undefined
37
+ ? {}
38
+ : { refs: materialized.refs }),
32
39
  ...(options.now === undefined ? {} : { now: options.now }),
33
40
  });
34
41
  options.afterCreate?.(tx, message);
@@ -1,6 +1,7 @@
1
1
  import type { AccountAvatarProjection } from "@tutti/shared/domain";
2
2
  import type { MessageProjection } from "@tutti/shared/schemas/api";
3
3
  export type TrustedCollaborationAuthor = {
4
+ kind?: "human" | "development_operator";
4
5
  account_ref: string;
5
6
  display_name: string;
6
7
  avatar?: AccountAvatarProjection;
@@ -19,7 +19,9 @@ export function shouldUseMessageAsScratchpadSource(message) {
19
19
  if (message.scope.kind !== "main_chat") {
20
20
  return false;
21
21
  }
22
- if (message.message_kind === "user_text" && message.author.kind === "human") {
22
+ if (message.message_kind === "user_text" &&
23
+ (message.author.kind === "human" ||
24
+ (message.author.kind === "system" && message.refs?.development_operator === true))) {
23
25
  return true;
24
26
  }
25
27
  if (message.message_kind === "agent_text" && message.author.kind === "agent") {
@@ -31,7 +33,11 @@ export function filterScratchpadSourceMessages(messages) {
31
33
  return messages.filter(shouldUseMessageAsScratchpadSource);
32
34
  }
33
35
  function compactRole(message) {
34
- return message.author.kind === "agent" ? "tutti" : "human";
36
+ return message.refs?.development_operator === true
37
+ ? "operator"
38
+ : message.author.kind === "agent"
39
+ ? "tutti"
40
+ : "human";
35
41
  }
36
42
  export function truncateTextMiddle(text, maxChars) {
37
43
  const trimmed = text.trim();
@@ -54,7 +60,7 @@ function sourceText(message) {
54
60
  return `Reference file (${reference.category}:${reference.name})\n${message.body}`;
55
61
  }
56
62
  function sourceAuthorDisplayName(message) {
57
- if (message.author.kind !== "human") {
63
+ if (message.author.kind !== "human" && message.refs?.development_operator !== true) {
58
64
  return undefined;
59
65
  }
60
66
  const displayName = message.author.display_name?.trim();
@@ -1,6 +1,6 @@
1
1
  import type { ClarificationRequestPayload, ExternalReferenceDescriptor } from "@tutti/shared/schemas/api";
2
2
  export type PromptSourceMessage = {
3
- role: "human" | "tutti";
3
+ role: "human" | "tutti" | "operator";
4
4
  author_display_name?: string;
5
5
  text: string;
6
6
  external_references?: ExternalReferenceDescriptor[];
@@ -8,10 +8,12 @@ function promptSourceMessage(db, source) {
8
8
  if (message.scope.kind !== "main_chat") {
9
9
  throw new Error("Task source message is outside main chat");
10
10
  }
11
- if (message.message_kind === "user_text" && message.author.kind === "human") {
11
+ if (message.message_kind === "user_text" &&
12
+ (message.author.kind === "human" ||
13
+ (message.author.kind === "system" && message.refs?.development_operator === true))) {
12
14
  const displayName = message.author.display_name?.trim();
13
15
  return {
14
- role: "human",
16
+ role: message.refs?.development_operator === true ? "operator" : "human",
15
17
  ...(displayName === undefined || displayName === ""
16
18
  ? {}
17
19
  : { author_display_name: displayName }),
@@ -37,6 +37,7 @@ export async function registerHostWithRelay(options) {
37
37
  joinToken: { mode: options.joinTokenMode ?? "rotate" },
38
38
  capabilities: {
39
39
  integration_source_ingestion_v1: true,
40
+ integration_development_bot_v1: true,
40
41
  integration_external_references_v1: true,
41
42
  integration_attachment_ingestion_v1: true,
42
43
  integration_managed_reference_ingestion_v1: true,
@@ -99,9 +99,7 @@ export function registerAgentContextReferenceRoutes(app, options) {
99
99
  request.log.warn({
100
100
  ...diagnosticFields,
101
101
  stage: "local_reference_unavailable",
102
- reason_code: error instanceof WorkspaceOpsError
103
- ? error.code
104
- : "reference_read_unavailable",
102
+ reason_code: error instanceof WorkspaceOpsError ? error.code : "reference_read_unavailable",
105
103
  elapsed_ms: Math.round(performance.now() - started),
106
104
  }, "Local Reference read unavailable");
107
105
  if (error instanceof WorkspaceOpsError) {
@@ -44,6 +44,7 @@ export type RegisterRelayHostConnectionPayload = {
44
44
  browser_secret_write: false;
45
45
  repo_viewer: boolean;
46
46
  integration_source_ingestion_v1?: boolean;
47
+ integration_development_bot_v1?: boolean;
47
48
  integration_external_references_v1?: boolean;
48
49
  integration_attachment_ingestion_v1?: boolean;
49
50
  integration_managed_reference_ingestion_v1?: boolean;
@@ -57,6 +57,9 @@ function createRegisterPayload(options) {
57
57
  browser_secret_write: false,
58
58
  repo_viewer: capabilities.repo_viewer ?? false,
59
59
  integration_source_ingestion_v1: capabilities.integration_source_ingestion_v1 ?? false,
60
+ ...(capabilities.integration_development_bot_v1 === true
61
+ ? { integration_development_bot_v1: true }
62
+ : {}),
60
63
  integration_external_references_v1: capabilities.integration_external_references_v1 ?? false,
61
64
  integration_attachment_ingestion_v1: capabilities.integration_attachment_ingestion_v1 ?? false,
62
65
  integration_managed_reference_ingestion_v1: capabilities.integration_managed_reference_ingestion_v1 ?? false,
@@ -507,6 +507,7 @@ export declare const SendClarificationRoundMessageResultSchema: import("@sinclai
507
507
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
508
508
  body: import("@sinclair/typebox").TString;
509
509
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
510
+ development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
510
511
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
511
512
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
512
513
  source_ref: import("@sinclair/typebox").TString;
@@ -133,6 +133,7 @@ export declare const ArtifactPreviewRefSchema: import("@sinclair/typebox").TObje
133
133
  run_result_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
134
134
  }>;
135
135
  export declare const MessageRefsSchema: import("@sinclair/typebox").TObject<{
136
+ development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
136
137
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
137
138
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
138
139
  source_ref: import("@sinclair/typebox").TString;
@@ -344,6 +345,7 @@ export declare const MessageProjectionSchema: import("@sinclair/typebox").TObjec
344
345
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
345
346
  body: import("@sinclair/typebox").TString;
346
347
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
348
+ development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
347
349
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
348
350
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
349
351
  source_ref: import("@sinclair/typebox").TString;
@@ -674,6 +676,7 @@ export declare const SendMainChatMessageResultSchema: import("@sinclair/typebox"
674
676
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
675
677
  body: import("@sinclair/typebox").TString;
676
678
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
679
+ development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
677
680
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
678
681
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
679
682
  source_ref: import("@sinclair/typebox").TString;
@@ -906,6 +909,7 @@ export declare const MessageCreatedEventPayloadSchema: import("@sinclair/typebox
906
909
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
907
910
  body: import("@sinclair/typebox").TString;
908
911
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
912
+ development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
909
913
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
910
914
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
911
915
  source_ref: import("@sinclair/typebox").TString;
@@ -125,6 +125,7 @@ export const ArtifactPreviewRefSchema = Type.Object({
125
125
  run_result_id: Type.Optional(RunResultIdSchema),
126
126
  }, { additionalProperties: false });
127
127
  export const MessageRefsSchema = Type.Object({
128
+ development_operator: Type.Optional(Type.Literal(true)),
128
129
  external_reference_reads: Type.Optional(Type.Array(ExternalReferenceRefSchema, { minItems: 1, maxItems: 16, uniqueItems: true })),
129
130
  external_references: Type.Optional(Type.Array(ExternalReferenceDescriptorSchema, { minItems: 1, maxItems: 16 })),
130
131
  task_id: Type.Optional(TaskIdSchema),
@@ -400,6 +400,7 @@ export declare const UploadReferenceFileResultSchema: import("@sinclair/typebox"
400
400
  message_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user_text">, import("@sinclair/typebox").TLiteral<"agent_text">, import("@sinclair/typebox").TLiteral<"system_notice">, import("@sinclair/typebox").TLiteral<"clarification_request">, import("@sinclair/typebox").TLiteral<"clarification_card">]>;
401
401
  body: import("@sinclair/typebox").TString;
402
402
  refs: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
403
+ development_operator: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TLiteral<true>>;
403
404
  external_reference_reads: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
404
405
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
405
406
  source_ref: import("@sinclair/typebox").TString;
@@ -65,6 +65,27 @@ export declare const TrustedSystemIntegrationActorContextSchema: import("@sincla
65
65
  binding_ref: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
66
66
  verified_at: import("@sinclair/typebox").TString;
67
67
  }>;
68
+ export declare const TrustedDevelopmentBotActorContextSchema: import("@sinclair/typebox").TObject<{
69
+ kind: import("@sinclair/typebox").TLiteral<"bot">;
70
+ purpose: import("@sinclair/typebox").TLiteral<"development_operator">;
71
+ channel: import("@sinclair/typebox").TLiteral<"platform_chat">;
72
+ account_ref: import("@sinclair/typebox").TString;
73
+ display_name: import("@sinclair/typebox").TString;
74
+ membership: import("@sinclair/typebox").TObject<{
75
+ relay_project_ref: import("@sinclair/typebox").TString;
76
+ label: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"owner">, import("@sinclair/typebox").TLiteral<"member">]>;
77
+ }>;
78
+ external_subject: import("@sinclair/typebox").TObject<{
79
+ installation: import("@sinclair/typebox").TObject<{
80
+ platform: import("@sinclair/typebox").TString;
81
+ installation_ref: import("@sinclair/typebox").TString;
82
+ }>;
83
+ subject_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"bot">, import("@sinclair/typebox").TLiteral<"app">, import("@sinclair/typebox").TLiteral<"system">]>;
84
+ subject_ref: import("@sinclair/typebox").TString;
85
+ }>;
86
+ binding_ref: import("@sinclair/typebox").TString;
87
+ verified_at: import("@sinclair/typebox").TString;
88
+ }>;
68
89
  export declare const TrustedIntegrationActorContextSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
69
90
  kind: import("@sinclair/typebox").TLiteral<"human">;
70
91
  account_ref: import("@sinclair/typebox").TString;
@@ -1447,7 +1468,7 @@ export declare const TrustedConversationSourceIngestionCommandSchema: import("@s
1447
1468
  received_at: import("@sinclair/typebox").TString;
1448
1469
  attempt: import("@sinclair/typebox").TInteger;
1449
1470
  }>;
1450
- actor: import("@sinclair/typebox").TObject<{
1471
+ actor: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
1451
1472
  kind: import("@sinclair/typebox").TLiteral<"human">;
1452
1473
  account_ref: import("@sinclair/typebox").TString;
1453
1474
  display_name: import("@sinclair/typebox").TString;
@@ -1466,7 +1487,27 @@ export declare const TrustedConversationSourceIngestionCommandSchema: import("@s
1466
1487
  }>;
1467
1488
  binding_ref: import("@sinclair/typebox").TString;
1468
1489
  verified_at: import("@sinclair/typebox").TString;
1469
- }>;
1490
+ }>, import("@sinclair/typebox").TObject<{
1491
+ kind: import("@sinclair/typebox").TLiteral<"bot">;
1492
+ purpose: import("@sinclair/typebox").TLiteral<"development_operator">;
1493
+ channel: import("@sinclair/typebox").TLiteral<"platform_chat">;
1494
+ account_ref: import("@sinclair/typebox").TString;
1495
+ display_name: import("@sinclair/typebox").TString;
1496
+ membership: import("@sinclair/typebox").TObject<{
1497
+ relay_project_ref: import("@sinclair/typebox").TString;
1498
+ label: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"owner">, import("@sinclair/typebox").TLiteral<"member">]>;
1499
+ }>;
1500
+ external_subject: import("@sinclair/typebox").TObject<{
1501
+ installation: import("@sinclair/typebox").TObject<{
1502
+ platform: import("@sinclair/typebox").TString;
1503
+ installation_ref: import("@sinclair/typebox").TString;
1504
+ }>;
1505
+ subject_kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"human">, import("@sinclair/typebox").TLiteral<"bot">, import("@sinclair/typebox").TLiteral<"app">, import("@sinclair/typebox").TLiteral<"system">]>;
1506
+ subject_ref: import("@sinclair/typebox").TString;
1507
+ }>;
1508
+ binding_ref: import("@sinclair/typebox").TString;
1509
+ verified_at: import("@sinclair/typebox").TString;
1510
+ }>]>;
1470
1511
  source: import("@sinclair/typebox").TObject<{
1471
1512
  external_references: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
1472
1513
  source_ref: import("@sinclair/typebox").TString;
@@ -74,6 +74,12 @@ export const TrustedSystemIntegrationActorContextSchema = Type.Object({
74
74
  binding_ref: Type.Optional(IntegrationOwnedRefSchema),
75
75
  verified_at: IsoDateTimeStringSchema,
76
76
  }, { additionalProperties: false });
77
+ export const TrustedDevelopmentBotActorContextSchema = Type.Object({
78
+ ...TrustedHumanIntegrationActorContextSchema.properties,
79
+ kind: Type.Literal("bot"),
80
+ purpose: Type.Literal("development_operator"),
81
+ channel: Type.Literal("platform_chat"),
82
+ }, { additionalProperties: false });
77
83
  export const TrustedIntegrationActorContextSchema = Type.Union([
78
84
  TrustedHumanIntegrationActorContextSchema,
79
85
  TrustedSystemIntegrationActorContextSchema,
@@ -452,7 +458,10 @@ export const TrustedConversationSourceIngestionCommandSchema = Type.Object({
452
458
  relay_project_ref: RelayProjectRefSchema,
453
459
  binding_ref: IntegrationOwnedRefSchema,
454
460
  receipt: InboundIntegrationEventReceiptSchema,
455
- actor: TrustedHumanIntegrationActorContextSchema,
461
+ actor: Type.Union([
462
+ TrustedHumanIntegrationActorContextSchema,
463
+ TrustedDevelopmentBotActorContextSchema,
464
+ ]),
456
465
  source: NormalizedConversationSourceSchema,
457
466
  }, { additionalProperties: false });
458
467
  export const IntegrationReferenceAttachmentDeliveryRequestSchema = Type.Object({
@@ -760,7 +769,7 @@ export function isIntegrationConversationSourceDeliveryRequest(value) {
760
769
  const sourceInstallation = request.source.locator.conversation.installation;
761
770
  const sourceSubject = request.source.author.external_subject;
762
771
  return (request.receipt.event_kind === "conversation_source" &&
763
- sourceSubject.subject_kind === "human" &&
772
+ (sourceSubject.subject_kind === "human" || sourceSubject.subject_kind === "bot") &&
764
773
  sameInstallation(request.receipt.installation, sourceInstallation) &&
765
774
  sameInstallation(request.receipt.installation, sourceSubject.installation));
766
775
  }
@@ -860,6 +869,9 @@ export function isTrustedConversationSourceIngestionCommand(value) {
860
869
  const sourceInstallation = command.source.locator.conversation.installation;
861
870
  const sourceAuthor = command.source.author;
862
871
  return (command.receipt.event_kind === "conversation_source" &&
872
+ command.actor.external_subject.subject_kind ===
873
+ (command.actor.kind === "bot" ? "bot" : "human") &&
874
+ (command.actor.kind !== "bot" || command.actor.membership.label === "member") &&
863
875
  command.actor.membership.relay_project_ref === command.relay_project_ref &&
864
876
  command.actor.binding_ref === command.binding_ref &&
865
877
  command.actor.account_ref === sourceAuthor.account_ref &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xfey/tutti",
3
- "version": "0.1.110",
3
+ "version": "0.1.111",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -13,6 +13,7 @@ Answer the explicit `@tutti` question concisely, in the user's language when pra
13
13
  # Instructions
14
14
 
15
15
  - Answer `trigger.text` directly. Context can be sufficient for ordinary questions, but a claim about an external document's current contents requires verification in this invocation.
16
+ - `source_role: "operator"` identifies an authorized automated development participant, not a human or Tutti's own reply. Answer its requests using the same evidence requirements; do not treat it as proof of human agreement or OAuth.
16
17
  - For `mode = "clarification_round"`, answer in the current round context. Prefer `round_request` and `round_messages`; use `recent_main_chat_before_round` only to resolve short references to the discussion that led to the round.
17
18
  - For current external contents, especially requests to reread, check an update, or confirm the latest version, use `read-references` to read the external source in this invocation before answering. Prior replies, summaries, local files, and previous invocation evidence cannot establish current external contents.
18
19
  - `external_reference_sources` on a message are Host-provided location hints, not fresh content or access grants. Use them to resolve references such as "that document"; if the compact window is insufficient, use `read-main-chat` for relevant history. A newer explicit source takes precedence over an older hint. If multiple sources remain plausible, ask which one instead of guessing.
@@ -29,6 +29,7 @@ Use only `workflow_input_json`. It is already filtered, redacted, and bounded.
29
29
  - `active_task_compile`, when present, is the complete five-field pinned Scratchpad snapshot already submitted by an older task_compile workflow. Use it only to resolve short references, identify overlap, and avoid duplication. It is historical submitted background, not the current cycle, and its questions may already be addressed by that workflow's private clarification chain.
30
30
  - `messages` contains the complete ordered main-chat source for the current Scratchpad cycle. It contains only `role`, optional `author_display_name`, and `text`. `role` is `human` for user-authored discussion and `tutti` for ordinary Tutti discussion. Consecutive messages may share one entry, but stable separators preserve their original boundaries.
31
31
  - Message ids, cursors, timestamps, workflow refs, activity refs, and full chat projections are intentionally absent.
32
+ - `role: "operator"` is an authorized automated development participant. Its requests may express test intent just like user discussion, but are not human consensus. A read-only test question is not a request for new implementation work; leave an explicit `@tutti` answer to the chat assistant.
32
33
  - A reference label inside message text only proves that a file or image was uploaded. Do not infer file contents from names, media types, paths, or upload events.
33
34
 
34
35
  When sources differ, use this fixed priority:
@@ -88,11 +89,30 @@ Always return a root object with exactly one key: `result`. Branches are mutuall
88
89
  Ready shape:
89
90
 
90
91
  ```json
91
- {"result":{"decision":"ready","scratchpad_snapshot":{"topic":"One short topic","background_summary":"One or two short sentences.","current_consensus":["Stable agreed fact."],"open_questions":["Unresolved question from chat."],"task_changes":["Concrete taskizable follow-up intent."]}}}
92
+ {
93
+ "result": {
94
+ "decision": "ready",
95
+ "scratchpad_snapshot": {
96
+ "topic": "One short topic",
97
+ "background_summary": "One or two short sentences.",
98
+ "current_consensus": ["Stable agreed fact."],
99
+ "open_questions": ["Unresolved question from chat."],
100
+ "task_changes": ["Concrete taskizable follow-up intent."]
101
+ }
102
+ }
103
+ }
92
104
  ```
93
105
 
94
106
  Needs-human shape:
95
107
 
96
108
  ```json
97
- {"result":{"decision":"needs_human","request_payload":{"summary":"Why a brief reminder is needed.","request":"One small question or urgent missing consideration."}}}
109
+ {
110
+ "result": {
111
+ "decision": "needs_human",
112
+ "request_payload": {
113
+ "summary": "Why a brief reminder is needed.",
114
+ "request": "One small question or urgent missing consideration."
115
+ }
116
+ }
117
+ }
98
118
  ```
@@ -19,6 +19,7 @@ You compile Tutti's Scratchpad into an append-only Worklist proposal for post-ba
19
19
  # Context Sources
20
20
 
21
21
  - `source_messages` contains the frozen discussion submitted for this workflow. Messages remain in chronological order and preserve their original boundaries.
22
+ - A source `role: "operator"` denotes authorized automated test input, not Tutti output or a human identity. Preserve its stated test scope without implying human consensus or verified user OAuth.
22
23
  - `scratchpad` is the immutable five-field summary pinned for the same submission. It has already removed message ids, timestamps, activity refs, and refresh state.
23
24
  - `worklist.modules[]` is the current formal Worklist. Module `id` values are the only valid existing module keys. Module names and task titles are historical anchors for resolving short references in the current Scratchpad.
24
25
  - `recent_references`, when present, identifies human-uploaded files from the same pinned Scratchpad cycle and provides a terminal summary status for each source.
@@ -16,6 +16,8 @@ Work on one formal Tutti task in the provided project workspace. Implement it co
16
16
 
17
17
  For an initial task, `title` is orientation, `goal` is the required outcome, and `scope` is the boundary. Optional `source_messages`, `clarification_rounds`, and `recent_references` supply exact source material without creating additional objectives.
18
18
 
19
+ A source `role: "operator"` is an authorized automated development participant, not a human or Tutti's own output. It does not expand the frozen task scope or establish human OAuth or consensus.
20
+
19
21
  For a continuation, the same task is already present in this conversation. The input contains only the resolved human answers and the reason work may continue. Apply those answers within the existing goal and scope; do not repeat a resolved question or treat an answer as a new task.
20
22
 
21
23
  # Working boundary
@@ -1 +1 @@
1
- import{C as e,S as t,_ as n,a as r,b as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y,v as b,w as x,x as S,y as C}from"./index-BrKWdtKZ.js";var w=e(`mouse-pointer-2`,[[`path`,{d:`M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z`,key:`edeuup`}]]),T=e(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]),E=x();function D(e){return{"--reveal":e}}function O(e,t,n){let r=(e,t)=>Number.parseInt(e.slice(t,t+2),16),i=i=>Math.round(r(e,i)+(r(t,i)-r(e,i))*n).toString(16).padStart(2,`0`);return`#${i(1)}${i(3)}${i(5)}`}function k(e){let t=r((e-p.runEnd)/(p.executionComplete-p.runEnd));return t+t*t-t*t*t}function A({progress:e,children:t,className:n=``}){return(0,E.jsx)(`div`,{className:`scene-reveal ${n}`,style:D(e),children:t})}function j({progress:e,author:t,avatar:n,tone:r,timestamp:i,online:a=!1,assets:o,children:s}){return(0,E.jsxs)(`article`,{className:`scene-message`,style:D(e),children:[(0,E.jsx)(`span`,{className:`scene-avatar is-${r} ${n===`tutti`?`is-tutti`:``} ${a?`is-online`:``}`,"aria-hidden":`true`,children:n===`tutti`?(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:o.tuttiAvatarSrc,alt:``}):(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:o.humanAvatars[n],alt:``})}),(0,E.jsxs)(`div`,{className:`scene-message-copy`,children:[(0,E.jsxs)(`header`,{children:[(0,E.jsx)(`strong`,{children:t}),(0,E.jsx)(`span`,{children:i})]}),(0,E.jsx)(`p`,{children:s})]})]})}function M({time:e,assets:r}){let i=e>=p.artifactLive,a=e>=p.artifactClick,o=e>=p.runEnd&&e<p.executionComplete,u=d(e,p.runEnd,19.2),f=d(e,p.artifactLive,30.92);return(0,E.jsxs)(`aside`,{className:`scene-sidebar`,children:[(0,E.jsx)(`button`,{className:`scene-brand`,type:`button`,"aria-label":`Tutti`,tabIndex:-1,children:(0,E.jsx)(`img`,{src:r.logoSrc,alt:``})}),(0,E.jsxs)(`div`,{className:`scene-nav-stack`,children:[(0,E.jsxs)(`nav`,{className:`scene-nav`,"aria-label":`Workspace pages`,children:[(0,E.jsx)(`button`,{className:a?``:`is-active`,type:`button`,"aria-label":`Chat`,tabIndex:-1,children:(0,E.jsx)(c,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Worklist`,tabIndex:-1,children:(0,E.jsx)(b,{"aria-hidden":`true`})}),(0,E.jsxs)(`button`,{className:a?`is-active`:``,type:`button`,"aria-label":`Artifacts`,tabIndex:-1,children:[(0,E.jsx)(l,{"aria-hidden":`true`}),i?(0,E.jsx)(`span`,{className:`scene-live-pill`,style:D(f),children:`Live`}):null]}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`References`,tabIndex:-1,children:(0,E.jsx)(C,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Skills`,tabIndex:-1,children:(0,E.jsx)(s,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Timeline`,tabIndex:-1,children:(0,E.jsx)(t,{"aria-hidden":`true`})})]}),o?(0,E.jsx)(`button`,{className:`scene-status-entry is-running`,style:D(u),type:`button`,"aria-label":`Task running`,tabIndex:-1,children:(0,E.jsx)(n,{"aria-hidden":`true`})}):null]}),(0,E.jsx)(`button`,{className:`scene-settings`,type:`button`,"aria-label":`Settings`,tabIndex:-1,children:(0,E.jsx)(h,{"aria-hidden":`true`})})]})}function N({time:e,assets:t}){let n=d(e,30.35,30.92);return(0,E.jsxs)(`section`,{className:`scene-panel scene-chat-panel`,children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(c,{"aria-hidden":`true`})}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`h2`,{children:`Morrow Studio`}),(0,E.jsx)(`p`,{children:`Ceramics storefront`})]}),(0,E.jsxs)(`span`,{className:`scene-members`,"aria-hidden":`true`,children:[(0,E.jsx)(`i`,{className:`is-green`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.fey,alt:``})}),(0,E.jsx)(`i`,{className:`is-blue`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.avery,alt:``})}),(0,E.jsx)(`i`,{className:`is-yellow`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.jun,alt:``})})]})]}),(0,E.jsxs)(`div`,{className:`scene-chat-stream`,children:[(0,E.jsx)(j,{progress:d(e,1.35,2.05),author:`Fey`,avatar:`fey`,tone:`green`,timestamp:`10:12`,online:!0,assets:t,children:`🏺 Let's build an online shop for our ceramics studio.`}),(0,E.jsx)(j,{progress:d(e,2.65,3.35),author:`Avery`,avatar:`avery`,tone:`blue`,timestamp:`10:13`,online:!0,assets:t,children:`✨ Keep it warm, minimal, and editorial.`}),(0,E.jsx)(j,{progress:d(e,3.95,4.65),author:`Jun`,avatar:`jun`,tone:`yellow`,timestamp:`10:14`,online:!0,assets:t,children:`🎨 Let people preview every piece in different glazes.`}),(0,E.jsx)(j,{progress:d(e,5.25,5.95),author:`Tutti`,avatar:`tutti`,tone:`green`,timestamp:`10:15`,assets:t,children:`Got it — I'll put it together. ✨`}),(0,E.jsxs)(`article`,{className:`scene-task-result`,style:D(n),children:[(0,E.jsx)(`span`,{className:`scene-task-result-rail`,"aria-hidden":`true`}),(0,E.jsx)(`span`,{className:`scene-task-result-icon`,"aria-hidden":`true`,children:(0,E.jsx)(S,{})}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`span`,{children:`Task completed`}),(0,E.jsx)(`strong`,{children:`Build ceramics storefront`}),(0,E.jsx)(`small`,{children:`Storefront`}),(0,E.jsx)(`p`,{children:`Warm editorial shopping and glaze previews are ready in Artifacts.`})]}),(0,E.jsx)(i,{className:`scene-task-result-chevron`,"aria-hidden":`true`})]})]}),(0,E.jsxs)(`div`,{className:`scene-composer`,"aria-hidden":`true`,children:[(0,E.jsx)(`span`,{children:`Write a message`}),(0,E.jsx)(T,{})]})]})}function P({progress:e,icon:t,children:n}){return(0,E.jsxs)(`div`,{className:`scene-scratchpad-row`,style:D(e),children:[(0,E.jsx)(`span`,{"aria-hidden":`true`,children:t}),(0,E.jsx)(`p`,{children:n})]})}function F({time:e}){return(0,E.jsxs)(`section`,{className:`scene-panel scene-scratchpad-panel`,style:{"--scratchpad-collapse":d(e,p.runEnd,19.18)},children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(v,{"aria-hidden":`true`})}),(0,E.jsx)(`h2`,{children:`Scratchpad`})]}),(0,E.jsxs)(`div`,{className:`scene-scratchpad-body`,children:[(0,E.jsxs)(A,{progress:d(e,8.95,10),className:`scene-scratchpad-intro`,children:[(0,E.jsx)(`h3`,{children:`Ceramics storefront`}),(0,E.jsx)(`p`,{children:`A warm, editorial storefront for a small-batch studio, centered on tactile product discovery.`})]}),(0,E.jsx)(A,{progress:d(e,9.85,10.65),className:`scene-scratchpad-label`,children:`Confirmed`}),(0,E.jsx)(P,{progress:d(e,10.4,11.25),icon:(0,E.jsx)(S,{}),children:`Product-first editorial layout with generous space`}),(0,E.jsx)(P,{progress:d(e,11.2,12.05),icon:(0,E.jsx)(S,{}),children:`Warm neutrals with quiet serif headlines`}),(0,E.jsx)(P,{progress:d(e,12,12.85),icon:(0,E.jsx)(S,{}),children:`Keep the collection small, curated, and story-led`}),(0,E.jsx)(A,{progress:d(e,12.75,13.55),className:`scene-scratchpad-label`,children:`Requested feature`}),(0,E.jsx)(P,{progress:d(e,13.3,14.2),icon:(0,E.jsx)(o,{}),children:`Preview every piece in clay, sage, and ink glazes`})]}),(0,E.jsxs)(`footer`,{className:`scene-scratchpad-footer`,style:D(d(e,15.7,16.8)),children:[(0,E.jsxs)(`span`,{className:`scene-writing-mark`,children:[(0,E.jsx)(`strong`,{children:`Updated`}),(0,E.jsx)(`span`,{children:`just now`})]}),(0,E.jsxs)(`button`,{className:`scene-run-button`,type:`button`,tabIndex:-1,children:[(0,E.jsx)(f,{"aria-hidden":`true`}),(0,E.jsx)(`span`,{children:`Run`})]})]})]})}function I(e,t){let n=Math.max(0,Math.floor((e-t)*50/5)*5);return`${Math.floor(n/60)}m${(n%60).toString().padStart(2,`0`)}s`}function L({time:e,scoreSrc:t}){let r=d(e,18.92,19.2),i=_(e),a=i.id===`complete`,o={prepare:p.runEnd,implement:p.executionPrepareEnd,validate:p.executionImplementEnd,update:p.executionValidateEnd,complete:p.executionComplete}[i.id],s=d(e,o,o+.32),c=k(e);return(0,E.jsx)(`div`,{className:`scene-execution`,style:{"--reveal":r,"--stage-reveal":s},children:(0,E.jsxs)(`article`,{className:`homepage-motion-panel homepage-motion-execution-panel homepage-motion-execution-card is-score-${a?`complete`:`running`}`,children:[(0,E.jsx)(`header`,{className:`homepage-motion-panel-header`,children:(0,E.jsxs)(`div`,{className:`homepage-motion-panel-title`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,"aria-hidden":`true`,children:(0,E.jsx)(y,{})}),(0,E.jsx)(`h3`,{children:`Tutti is working on`})]})}),(0,E.jsxs)(`div`,{className:`homepage-motion-execution-body`,children:[(0,E.jsxs)(`div`,{className:`homepage-motion-execution-step homepage-motion-execution-stage is-${a?`complete`:`running`} has-marker`,children:[(0,E.jsx)(`span`,{className:`homepage-motion-execution-marker ${a?`is-done`:`is-running`}`,"aria-hidden":`true`,children:a?(0,E.jsx)(S,{}):(0,E.jsx)(n,{})}),(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-content homepage-motion-execution-stage-copy`,children:(0,E.jsxs)(`span`,{className:`homepage-motion-execution-step-title`,children:[(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-label`,children:i.label}),a?null:(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-elapsed`,children:` (${I(e,o)})`})]})},i.id)]}),(0,E.jsx)(`div`,{className:`homepage-motion-running-score ${a?`is-complete`:``}`,role:`img`,"aria-label":`Ode to Joy score phrase`,children:(0,E.jsx)(`div`,{className:`homepage-motion-score-passage`,style:{"--score-translate-x":`${-395.3*c}px`},"aria-hidden":`true`,children:(0,E.jsx)(`img`,{src:t,alt:``,draggable:!1})})})]})]})})}function R({color:e,variant:t=`vase`,className:n=``}){let r={"--ceramic-color":e};return t===`cup`?(0,E.jsxs)(`svg`,{className:`ceramic-object is-cup ${n}`,viewBox:`0 0 260 260`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M54 64h132l-9 126c-2 26-20 42-46 42h-22c-26 0-44-16-46-42Z`}),(0,E.jsx)(`path`,{className:`ceramic-outline`,d:`M186 92h18c34 0 34 72 1 76h-27`}),(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`120`,cy:`64`,rx:`66`,ry:`13`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M78 90c5 62 4 91 20 114`})]}):t===`bowl`?(0,E.jsxs)(`svg`,{className:`ceramic-object is-bowl ${n}`,viewBox:`0 0 300 220`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`150`,cy:`55`,rx:`116`,ry:`24`}),(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M34 55c8 82 45 132 116 132S258 137 266 55c-42 25-190 25-232 0Z`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M72 82c18 45 40 70 70 82`}),(0,E.jsx)(`path`,{className:`ceramic-base`,d:`M112 185h76`})]}):(0,E.jsxs)(`svg`,{className:`ceramic-object is-vase ${n}`,viewBox:`0 0 320 420`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M116 56c7 38-17 61-36 96-31 56-28 157 5 199 33 42 117 42 150 0 33-42 36-143 5-199-19-35-43-58-36-96Z`}),(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`160`,cy:`56`,rx:`44`,ry:`12`}),(0,E.jsx)(`ellipse`,{className:`ceramic-base`,cx:`160`,cy:`365`,rx:`66`,ry:`13`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M108 153c-25 64-23 145 1 185`})]})}function z({time:e}){let t=d(e,p.artifactClick,33.25),n=d(e,34.25,34.52),r=d(e,34.88,35.15),i=d(e,35.55,35.82),a=g(e),o=O(`#d9cbb4`,`#c56f4f`,n);e>=34.88&&(o=O(`#c56f4f`,`#6f9275`,r)),e>=35.55&&(o=O(`#6f9275`,`#243a46`,i));let s=e>=35.55?`ink`:e>=34.88?`sage`:e>=34.25?`clay`:null,c={"--artifact-scroll":a};return(0,E.jsxs)(`section`,{className:`scene-panel scene-artifact-panel`,style:D(t),children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(l,{"aria-hidden":`true`})}),(0,E.jsx)(`h2`,{children:`Artifacts`}),(0,E.jsx)(`span`,{className:`scene-ready-tag`,children:`Ready`})]}),(0,E.jsx)(`div`,{className:`scene-artifact-canvas`,children:(0,E.jsxs)(`div`,{className:`artifact-page-frame`,style:c,children:[(0,E.jsxs)(`div`,{className:`artifact-page-nav`,children:[(0,E.jsx)(`strong`,{children:`Morrow`}),(0,E.jsx)(`span`,{children:`Objects · Journal · Studio`})]}),(0,E.jsxs)(`section`,{className:`artifact-hero`,children:[(0,E.jsxs)(`div`,{className:`artifact-hero-copy`,children:[(0,E.jsx)(`span`,{className:`artifact-eyebrow`,children:`Hand-finished in small batches`}),(0,E.jsx)(`h3`,{children:`Objects for slower days.`}),(0,E.jsx)(`p`,{children:`Quiet forms, warm glazes, and useful pieces made to live with.`}),(0,E.jsx)(`button`,{type:`button`,tabIndex:-1,children:`Explore the collection`})]}),(0,E.jsxs)(`div`,{className:`artifact-hero-object`,children:[(0,E.jsx)(R,{color:o}),(0,E.jsxs)(`div`,{className:`artifact-glaze-picker`,"aria-label":`Glaze preview`,children:[(0,E.jsx)(`span`,{children:`Glaze`}),(0,E.jsx)(`i`,{className:s===`clay`?`is-active is-clay`:`is-clay`}),(0,E.jsx)(`i`,{className:s===`sage`?`is-active is-sage`:`is-sage`}),(0,E.jsx)(`i`,{className:s===`ink`?`is-active is-ink`:`is-ink`})]})]})]}),(0,E.jsxs)(`section`,{className:`artifact-collection`,children:[(0,E.jsxs)(`header`,{children:[(0,E.jsx)(`span`,{children:`Selected pieces`}),(0,E.jsx)(`p`,{children:`Everyday forms shaped for the rituals around them.`})]}),(0,E.jsxs)(`div`,{className:`artifact-product-grid`,children:[(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#b9785f`,variant:`cup`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Low cup`}),(0,E.jsx)(`span`,{children:`Rust glaze`})]})]}),(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#819283`,variant:`vase`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Field vase`}),(0,E.jsx)(`span`,{children:`Sage glaze`})]})]}),(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#d5c7af`,variant:`bowl`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Gather bowl`}),(0,E.jsx)(`span`,{children:`Flax glaze`})]})]})]})]}),(0,E.jsxs)(`section`,{className:`artifact-studio`,children:[(0,E.jsx)(`span`,{children:`Made by hand · Meant for every day`}),(0,E.jsx)(`h3`,{children:`Useful things can still feel special.`}),(0,E.jsx)(`p`,{children:`We make a small number of considered objects, slowly and close to home.`}),(0,E.jsx)(`button`,{type:`button`,tabIndex:-1,children:`Visit the studio`})]}),(0,E.jsxs)(`footer`,{className:`artifact-page-footer`,children:[(0,E.jsx)(`strong`,{children:`Morrow Ceramics`}),(0,E.jsx)(`span`,{className:`artifact-built-with`,children:`Built with Tutti.`}),(0,E.jsx)(`span`,{children:`Small batch · Est. 2026`})]})]})})]})}function B(e,t,n){return e+(t-e)*n}function V(e,t,n,r,i){let a=d(e,t,n,m);return{x:B(r.x,i.x,a),y:B(r.y,i.y,a)}}function H(e,t,n){return e<t||e>n?0:Math.sin(Math.PI*((e-t)/(n-t)))}function U(e){if(e>=p.runCursorStart&&e<18.92){let t=V(e,p.runCursorStart,p.runCursorArrive,{x:86,y:76},{x:94.25,y:94.2});return{visible:!0,x:t.x,y:t.y,clickPulse:H(e,p.runClickStart,p.runEnd)}}if(e>=31&&e<33.45){let t=V(e,31,32.22,{x:50,y:58},{x:4,y:22.85});return{visible:!0,x:t.x,y:t.y,clickPulse:H(e,32.28,32.6)}}return{visible:!1,x:50,y:50,clickPulse:0}}function W({time:e,assets:t}){let n=u(e),r=U(e),i=a(e),o=d(e,.08,1.05,m);return(0,E.jsx)(`div`,{className:`motion-scene`,role:`img`,"aria-label":`Tutti workflow animation from team discussion to a generated ceramics storefront`,style:{opacity:i,visibility:i<=.001?`hidden`:`visible`},children:(0,E.jsxs)(`div`,{className:`motion-stage`,style:{opacity:o,transform:`translate(50%, 50%) scale(${n.scale}) translate(${-n.centerX*100}%, ${-n.centerY*100}%)`},children:[(0,E.jsx)(M,{time:e,assets:t}),(0,E.jsxs)(`div`,{className:`scene-workspace-layer`,children:[(0,E.jsx)(N,{time:e,assets:t}),(0,E.jsx)(F,{time:e}),(0,E.jsx)(L,{time:e,scoreSrc:t.scoreSrc})]}),(0,E.jsx)(z,{time:e}),(0,E.jsxs)(`span`,{className:`scene-cursor ${r.visible?`is-visible`:``}`,style:{left:`${r.x}%`,top:`${r.y}%`,"--click-pulse":r.clickPulse},"aria-hidden":`true`,children:[(0,E.jsx)(w,{}),(0,E.jsx)(`i`,{})]})]})})}export{W as HomepageMotionScene};
1
+ import{C as e,S as t,_ as n,a as r,b as i,c as a,d as o,f as s,g as c,h as l,i as u,l as d,m as f,n as p,o as m,p as h,r as g,s as _,t as v,u as y,v as b,w as x,x as S,y as C}from"./index-B1oL1p9_.js";var w=e(`mouse-pointer-2`,[[`path`,{d:`M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z`,key:`edeuup`}]]),T=e(`send`,[[`path`,{d:`M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z`,key:`1ffxy3`}],[`path`,{d:`m21.854 2.147-10.94 10.939`,key:`12cjpa`}]]),E=x();function D(e){return{"--reveal":e}}function O(e,t,n){let r=(e,t)=>Number.parseInt(e.slice(t,t+2),16),i=i=>Math.round(r(e,i)+(r(t,i)-r(e,i))*n).toString(16).padStart(2,`0`);return`#${i(1)}${i(3)}${i(5)}`}function k(e){let t=r((e-p.runEnd)/(p.executionComplete-p.runEnd));return t+t*t-t*t*t}function A({progress:e,children:t,className:n=``}){return(0,E.jsx)(`div`,{className:`scene-reveal ${n}`,style:D(e),children:t})}function j({progress:e,author:t,avatar:n,tone:r,timestamp:i,online:a=!1,assets:o,children:s}){return(0,E.jsxs)(`article`,{className:`scene-message`,style:D(e),children:[(0,E.jsx)(`span`,{className:`scene-avatar is-${r} ${n===`tutti`?`is-tutti`:``} ${a?`is-online`:``}`,"aria-hidden":`true`,children:n===`tutti`?(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:o.tuttiAvatarSrc,alt:``}):(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:o.humanAvatars[n],alt:``})}),(0,E.jsxs)(`div`,{className:`scene-message-copy`,children:[(0,E.jsxs)(`header`,{children:[(0,E.jsx)(`strong`,{children:t}),(0,E.jsx)(`span`,{children:i})]}),(0,E.jsx)(`p`,{children:s})]})]})}function M({time:e,assets:r}){let i=e>=p.artifactLive,a=e>=p.artifactClick,o=e>=p.runEnd&&e<p.executionComplete,u=d(e,p.runEnd,19.2),f=d(e,p.artifactLive,30.92);return(0,E.jsxs)(`aside`,{className:`scene-sidebar`,children:[(0,E.jsx)(`button`,{className:`scene-brand`,type:`button`,"aria-label":`Tutti`,tabIndex:-1,children:(0,E.jsx)(`img`,{src:r.logoSrc,alt:``})}),(0,E.jsxs)(`div`,{className:`scene-nav-stack`,children:[(0,E.jsxs)(`nav`,{className:`scene-nav`,"aria-label":`Workspace pages`,children:[(0,E.jsx)(`button`,{className:a?``:`is-active`,type:`button`,"aria-label":`Chat`,tabIndex:-1,children:(0,E.jsx)(c,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Worklist`,tabIndex:-1,children:(0,E.jsx)(b,{"aria-hidden":`true`})}),(0,E.jsxs)(`button`,{className:a?`is-active`:``,type:`button`,"aria-label":`Artifacts`,tabIndex:-1,children:[(0,E.jsx)(l,{"aria-hidden":`true`}),i?(0,E.jsx)(`span`,{className:`scene-live-pill`,style:D(f),children:`Live`}):null]}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`References`,tabIndex:-1,children:(0,E.jsx)(C,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Skills`,tabIndex:-1,children:(0,E.jsx)(s,{"aria-hidden":`true`})}),(0,E.jsx)(`button`,{type:`button`,"aria-label":`Timeline`,tabIndex:-1,children:(0,E.jsx)(t,{"aria-hidden":`true`})})]}),o?(0,E.jsx)(`button`,{className:`scene-status-entry is-running`,style:D(u),type:`button`,"aria-label":`Task running`,tabIndex:-1,children:(0,E.jsx)(n,{"aria-hidden":`true`})}):null]}),(0,E.jsx)(`button`,{className:`scene-settings`,type:`button`,"aria-label":`Settings`,tabIndex:-1,children:(0,E.jsx)(h,{"aria-hidden":`true`})})]})}function N({time:e,assets:t}){let n=d(e,30.35,30.92);return(0,E.jsxs)(`section`,{className:`scene-panel scene-chat-panel`,children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(c,{"aria-hidden":`true`})}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`h2`,{children:`Morrow Studio`}),(0,E.jsx)(`p`,{children:`Ceramics storefront`})]}),(0,E.jsxs)(`span`,{className:`scene-members`,"aria-hidden":`true`,children:[(0,E.jsx)(`i`,{className:`is-green`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.fey,alt:``})}),(0,E.jsx)(`i`,{className:`is-blue`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.avery,alt:``})}),(0,E.jsx)(`i`,{className:`is-yellow`,children:(0,E.jsx)(`img`,{className:`scene-avatar-image`,src:t.humanAvatars.jun,alt:``})})]})]}),(0,E.jsxs)(`div`,{className:`scene-chat-stream`,children:[(0,E.jsx)(j,{progress:d(e,1.35,2.05),author:`Fey`,avatar:`fey`,tone:`green`,timestamp:`10:12`,online:!0,assets:t,children:`🏺 Let's build an online shop for our ceramics studio.`}),(0,E.jsx)(j,{progress:d(e,2.65,3.35),author:`Avery`,avatar:`avery`,tone:`blue`,timestamp:`10:13`,online:!0,assets:t,children:`✨ Keep it warm, minimal, and editorial.`}),(0,E.jsx)(j,{progress:d(e,3.95,4.65),author:`Jun`,avatar:`jun`,tone:`yellow`,timestamp:`10:14`,online:!0,assets:t,children:`🎨 Let people preview every piece in different glazes.`}),(0,E.jsx)(j,{progress:d(e,5.25,5.95),author:`Tutti`,avatar:`tutti`,tone:`green`,timestamp:`10:15`,assets:t,children:`Got it — I'll put it together. ✨`}),(0,E.jsxs)(`article`,{className:`scene-task-result`,style:D(n),children:[(0,E.jsx)(`span`,{className:`scene-task-result-rail`,"aria-hidden":`true`}),(0,E.jsx)(`span`,{className:`scene-task-result-icon`,"aria-hidden":`true`,children:(0,E.jsx)(S,{})}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`span`,{children:`Task completed`}),(0,E.jsx)(`strong`,{children:`Build ceramics storefront`}),(0,E.jsx)(`small`,{children:`Storefront`}),(0,E.jsx)(`p`,{children:`Warm editorial shopping and glaze previews are ready in Artifacts.`})]}),(0,E.jsx)(i,{className:`scene-task-result-chevron`,"aria-hidden":`true`})]})]}),(0,E.jsxs)(`div`,{className:`scene-composer`,"aria-hidden":`true`,children:[(0,E.jsx)(`span`,{children:`Write a message`}),(0,E.jsx)(T,{})]})]})}function P({progress:e,icon:t,children:n}){return(0,E.jsxs)(`div`,{className:`scene-scratchpad-row`,style:D(e),children:[(0,E.jsx)(`span`,{"aria-hidden":`true`,children:t}),(0,E.jsx)(`p`,{children:n})]})}function F({time:e}){return(0,E.jsxs)(`section`,{className:`scene-panel scene-scratchpad-panel`,style:{"--scratchpad-collapse":d(e,p.runEnd,19.18)},children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(v,{"aria-hidden":`true`})}),(0,E.jsx)(`h2`,{children:`Scratchpad`})]}),(0,E.jsxs)(`div`,{className:`scene-scratchpad-body`,children:[(0,E.jsxs)(A,{progress:d(e,8.95,10),className:`scene-scratchpad-intro`,children:[(0,E.jsx)(`h3`,{children:`Ceramics storefront`}),(0,E.jsx)(`p`,{children:`A warm, editorial storefront for a small-batch studio, centered on tactile product discovery.`})]}),(0,E.jsx)(A,{progress:d(e,9.85,10.65),className:`scene-scratchpad-label`,children:`Confirmed`}),(0,E.jsx)(P,{progress:d(e,10.4,11.25),icon:(0,E.jsx)(S,{}),children:`Product-first editorial layout with generous space`}),(0,E.jsx)(P,{progress:d(e,11.2,12.05),icon:(0,E.jsx)(S,{}),children:`Warm neutrals with quiet serif headlines`}),(0,E.jsx)(P,{progress:d(e,12,12.85),icon:(0,E.jsx)(S,{}),children:`Keep the collection small, curated, and story-led`}),(0,E.jsx)(A,{progress:d(e,12.75,13.55),className:`scene-scratchpad-label`,children:`Requested feature`}),(0,E.jsx)(P,{progress:d(e,13.3,14.2),icon:(0,E.jsx)(o,{}),children:`Preview every piece in clay, sage, and ink glazes`})]}),(0,E.jsxs)(`footer`,{className:`scene-scratchpad-footer`,style:D(d(e,15.7,16.8)),children:[(0,E.jsxs)(`span`,{className:`scene-writing-mark`,children:[(0,E.jsx)(`strong`,{children:`Updated`}),(0,E.jsx)(`span`,{children:`just now`})]}),(0,E.jsxs)(`button`,{className:`scene-run-button`,type:`button`,tabIndex:-1,children:[(0,E.jsx)(f,{"aria-hidden":`true`}),(0,E.jsx)(`span`,{children:`Run`})]})]})]})}function I(e,t){let n=Math.max(0,Math.floor((e-t)*50/5)*5);return`${Math.floor(n/60)}m${(n%60).toString().padStart(2,`0`)}s`}function L({time:e,scoreSrc:t}){let r=d(e,18.92,19.2),i=_(e),a=i.id===`complete`,o={prepare:p.runEnd,implement:p.executionPrepareEnd,validate:p.executionImplementEnd,update:p.executionValidateEnd,complete:p.executionComplete}[i.id],s=d(e,o,o+.32),c=k(e);return(0,E.jsx)(`div`,{className:`scene-execution`,style:{"--reveal":r,"--stage-reveal":s},children:(0,E.jsxs)(`article`,{className:`homepage-motion-panel homepage-motion-execution-panel homepage-motion-execution-card is-score-${a?`complete`:`running`}`,children:[(0,E.jsx)(`header`,{className:`homepage-motion-panel-header`,children:(0,E.jsxs)(`div`,{className:`homepage-motion-panel-title`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,"aria-hidden":`true`,children:(0,E.jsx)(y,{})}),(0,E.jsx)(`h3`,{children:`Tutti is working on`})]})}),(0,E.jsxs)(`div`,{className:`homepage-motion-execution-body`,children:[(0,E.jsxs)(`div`,{className:`homepage-motion-execution-step homepage-motion-execution-stage is-${a?`complete`:`running`} has-marker`,children:[(0,E.jsx)(`span`,{className:`homepage-motion-execution-marker ${a?`is-done`:`is-running`}`,"aria-hidden":`true`,children:a?(0,E.jsx)(S,{}):(0,E.jsx)(n,{})}),(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-content homepage-motion-execution-stage-copy`,children:(0,E.jsxs)(`span`,{className:`homepage-motion-execution-step-title`,children:[(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-label`,children:i.label}),a?null:(0,E.jsx)(`span`,{className:`homepage-motion-execution-step-elapsed`,children:` (${I(e,o)})`})]})},i.id)]}),(0,E.jsx)(`div`,{className:`homepage-motion-running-score ${a?`is-complete`:``}`,role:`img`,"aria-label":`Ode to Joy score phrase`,children:(0,E.jsx)(`div`,{className:`homepage-motion-score-passage`,style:{"--score-translate-x":`${-395.3*c}px`},"aria-hidden":`true`,children:(0,E.jsx)(`img`,{src:t,alt:``,draggable:!1})})})]})]})})}function R({color:e,variant:t=`vase`,className:n=``}){let r={"--ceramic-color":e};return t===`cup`?(0,E.jsxs)(`svg`,{className:`ceramic-object is-cup ${n}`,viewBox:`0 0 260 260`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M54 64h132l-9 126c-2 26-20 42-46 42h-22c-26 0-44-16-46-42Z`}),(0,E.jsx)(`path`,{className:`ceramic-outline`,d:`M186 92h18c34 0 34 72 1 76h-27`}),(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`120`,cy:`64`,rx:`66`,ry:`13`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M78 90c5 62 4 91 20 114`})]}):t===`bowl`?(0,E.jsxs)(`svg`,{className:`ceramic-object is-bowl ${n}`,viewBox:`0 0 300 220`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`150`,cy:`55`,rx:`116`,ry:`24`}),(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M34 55c8 82 45 132 116 132S258 137 266 55c-42 25-190 25-232 0Z`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M72 82c18 45 40 70 70 82`}),(0,E.jsx)(`path`,{className:`ceramic-base`,d:`M112 185h76`})]}):(0,E.jsxs)(`svg`,{className:`ceramic-object is-vase ${n}`,viewBox:`0 0 320 420`,style:r,"aria-hidden":`true`,children:[(0,E.jsx)(`path`,{className:`ceramic-main`,d:`M116 56c7 38-17 61-36 96-31 56-28 157 5 199 33 42 117 42 150 0 33-42 36-143 5-199-19-35-43-58-36-96Z`}),(0,E.jsx)(`ellipse`,{className:`ceramic-rim`,cx:`160`,cy:`56`,rx:`44`,ry:`12`}),(0,E.jsx)(`ellipse`,{className:`ceramic-base`,cx:`160`,cy:`365`,rx:`66`,ry:`13`}),(0,E.jsx)(`path`,{className:`ceramic-highlight`,d:`M108 153c-25 64-23 145 1 185`})]})}function z({time:e}){let t=d(e,p.artifactClick,33.25),n=d(e,34.25,34.52),r=d(e,34.88,35.15),i=d(e,35.55,35.82),a=g(e),o=O(`#d9cbb4`,`#c56f4f`,n);e>=34.88&&(o=O(`#c56f4f`,`#6f9275`,r)),e>=35.55&&(o=O(`#6f9275`,`#243a46`,i));let s=e>=35.55?`ink`:e>=34.88?`sage`:e>=34.25?`clay`:null,c={"--artifact-scroll":a};return(0,E.jsxs)(`section`,{className:`scene-panel scene-artifact-panel`,style:D(t),children:[(0,E.jsxs)(`header`,{className:`scene-panel-header`,children:[(0,E.jsx)(`span`,{className:`scene-icon-tile`,children:(0,E.jsx)(l,{"aria-hidden":`true`})}),(0,E.jsx)(`h2`,{children:`Artifacts`}),(0,E.jsx)(`span`,{className:`scene-ready-tag`,children:`Ready`})]}),(0,E.jsx)(`div`,{className:`scene-artifact-canvas`,children:(0,E.jsxs)(`div`,{className:`artifact-page-frame`,style:c,children:[(0,E.jsxs)(`div`,{className:`artifact-page-nav`,children:[(0,E.jsx)(`strong`,{children:`Morrow`}),(0,E.jsx)(`span`,{children:`Objects · Journal · Studio`})]}),(0,E.jsxs)(`section`,{className:`artifact-hero`,children:[(0,E.jsxs)(`div`,{className:`artifact-hero-copy`,children:[(0,E.jsx)(`span`,{className:`artifact-eyebrow`,children:`Hand-finished in small batches`}),(0,E.jsx)(`h3`,{children:`Objects for slower days.`}),(0,E.jsx)(`p`,{children:`Quiet forms, warm glazes, and useful pieces made to live with.`}),(0,E.jsx)(`button`,{type:`button`,tabIndex:-1,children:`Explore the collection`})]}),(0,E.jsxs)(`div`,{className:`artifact-hero-object`,children:[(0,E.jsx)(R,{color:o}),(0,E.jsxs)(`div`,{className:`artifact-glaze-picker`,"aria-label":`Glaze preview`,children:[(0,E.jsx)(`span`,{children:`Glaze`}),(0,E.jsx)(`i`,{className:s===`clay`?`is-active is-clay`:`is-clay`}),(0,E.jsx)(`i`,{className:s===`sage`?`is-active is-sage`:`is-sage`}),(0,E.jsx)(`i`,{className:s===`ink`?`is-active is-ink`:`is-ink`})]})]})]}),(0,E.jsxs)(`section`,{className:`artifact-collection`,children:[(0,E.jsxs)(`header`,{children:[(0,E.jsx)(`span`,{children:`Selected pieces`}),(0,E.jsx)(`p`,{children:`Everyday forms shaped for the rituals around them.`})]}),(0,E.jsxs)(`div`,{className:`artifact-product-grid`,children:[(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#b9785f`,variant:`cup`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Low cup`}),(0,E.jsx)(`span`,{children:`Rust glaze`})]})]}),(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#819283`,variant:`vase`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Field vase`}),(0,E.jsx)(`span`,{children:`Sage glaze`})]})]}),(0,E.jsxs)(`article`,{children:[(0,E.jsx)(R,{color:`#d5c7af`,variant:`bowl`}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:`Gather bowl`}),(0,E.jsx)(`span`,{children:`Flax glaze`})]})]})]})]}),(0,E.jsxs)(`section`,{className:`artifact-studio`,children:[(0,E.jsx)(`span`,{children:`Made by hand · Meant for every day`}),(0,E.jsx)(`h3`,{children:`Useful things can still feel special.`}),(0,E.jsx)(`p`,{children:`We make a small number of considered objects, slowly and close to home.`}),(0,E.jsx)(`button`,{type:`button`,tabIndex:-1,children:`Visit the studio`})]}),(0,E.jsxs)(`footer`,{className:`artifact-page-footer`,children:[(0,E.jsx)(`strong`,{children:`Morrow Ceramics`}),(0,E.jsx)(`span`,{className:`artifact-built-with`,children:`Built with Tutti.`}),(0,E.jsx)(`span`,{children:`Small batch · Est. 2026`})]})]})})]})}function B(e,t,n){return e+(t-e)*n}function V(e,t,n,r,i){let a=d(e,t,n,m);return{x:B(r.x,i.x,a),y:B(r.y,i.y,a)}}function H(e,t,n){return e<t||e>n?0:Math.sin(Math.PI*((e-t)/(n-t)))}function U(e){if(e>=p.runCursorStart&&e<18.92){let t=V(e,p.runCursorStart,p.runCursorArrive,{x:86,y:76},{x:94.25,y:94.2});return{visible:!0,x:t.x,y:t.y,clickPulse:H(e,p.runClickStart,p.runEnd)}}if(e>=31&&e<33.45){let t=V(e,31,32.22,{x:50,y:58},{x:4,y:22.85});return{visible:!0,x:t.x,y:t.y,clickPulse:H(e,32.28,32.6)}}return{visible:!1,x:50,y:50,clickPulse:0}}function W({time:e,assets:t}){let n=u(e),r=U(e),i=a(e),o=d(e,.08,1.05,m);return(0,E.jsx)(`div`,{className:`motion-scene`,role:`img`,"aria-label":`Tutti workflow animation from team discussion to a generated ceramics storefront`,style:{opacity:i,visibility:i<=.001?`hidden`:`visible`},children:(0,E.jsxs)(`div`,{className:`motion-stage`,style:{opacity:o,transform:`translate(50%, 50%) scale(${n.scale}) translate(${-n.centerX*100}%, ${-n.centerY*100}%)`},children:[(0,E.jsx)(M,{time:e,assets:t}),(0,E.jsxs)(`div`,{className:`scene-workspace-layer`,children:[(0,E.jsx)(N,{time:e,assets:t}),(0,E.jsx)(F,{time:e}),(0,E.jsx)(L,{time:e,scoreSrc:t.scoreSrc})]}),(0,E.jsx)(z,{time:e}),(0,E.jsxs)(`span`,{className:`scene-cursor ${r.visible?`is-visible`:``}`,style:{left:`${r.x}%`,top:`${r.y}%`,"--click-pulse":r.clickPulse},"aria-hidden":`true`,children:[(0,E.jsx)(w,{}),(0,E.jsx)(`i`,{})]})]})})}export{W as HomepageMotionScene};