@agent-native/core 0.147.0 → 0.148.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
  3. package/corpus/templates/analytics/DEVELOPING.md +50 -3
  4. package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
  5. package/corpus/templates/analytics/app/i18n/index.ts +14 -29
  6. package/corpus/templates/analytics/app/i18n-data.ts +10 -10
  7. package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
  8. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
  9. package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
  10. package/corpus/templates/analytics/server/db/schema.ts +23 -0
  11. package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
  12. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
  13. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
  14. package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
  15. package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
  16. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
  17. package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
  18. package/corpus/templates/analytics/server/plugins/db.ts +42 -0
  19. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
  20. package/corpus/templates/assets/app/i18n/index.ts +14 -29
  21. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
  22. package/corpus/templates/brain/app/i18n/index.ts +14 -29
  23. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
  24. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  25. package/corpus/templates/chat/app/i18n/index.ts +14 -29
  26. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
  27. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
  28. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
  29. package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
  30. package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
  31. package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
  32. package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
  33. package/corpus/templates/clips/desktop/src/app.tsx +1 -1
  34. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
  35. package/corpus/templates/content/app/i18n/index.ts +14 -29
  36. package/corpus/templates/crm/app/i18n/index.ts +14 -29
  37. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
  38. package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
  39. package/corpus/templates/design/actions/import-code.ts +2 -43
  40. package/corpus/templates/design/app/i18n/index.ts +14 -29
  41. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
  42. package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
  43. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
  44. package/corpus/templates/factory/AGENTS.md +40 -49
  45. package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
  46. package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
  47. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
  48. package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
  49. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
  50. package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
  51. package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
  52. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  53. package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
  54. package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
  55. package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
  56. package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
  57. package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
  58. package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
  59. package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
  60. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
  61. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
  62. package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
  63. package/corpus/templates/factory/app/routes/factory.tsx +95 -42
  64. package/corpus/templates/factory/server/db/schema.ts +37 -0
  65. package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
  66. package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
  67. package/corpus/templates/factory/server/triage/audit.ts +79 -0
  68. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
  69. package/corpus/templates/forms/app/i18n/index.ts +14 -29
  70. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
  71. package/corpus/templates/macros/app/i18n/index.ts +14 -29
  72. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
  73. package/corpus/templates/mail/app/i18n/index.ts +14 -29
  74. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
  75. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
  76. package/corpus/templates/plan/app/i18n/index.ts +14 -29
  77. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
  78. package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
  79. package/corpus/templates/slides/actions/import-code.ts +2 -43
  80. package/corpus/templates/slides/app/i18n/index.ts +14 -29
  81. package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
  82. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
  83. package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
  84. package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
  85. package/corpus/templates/tasks/app/i18n/index.ts +14 -29
  86. package/dist/agent/engine/ai-sdk-engine.js +2 -1
  87. package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
  88. package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
  89. package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
  90. package/dist/agent/engine/provider-endpoint-validation.js +26 -0
  91. package/dist/agent/engine/provider-env-vars.d.ts +1 -1
  92. package/dist/agent/engine/provider-env-vars.js +1 -1
  93. package/dist/agent/engine/registry.d.ts +8 -6
  94. package/dist/agent/engine/registry.js +37 -24
  95. package/dist/agent/tool-search.d.ts +1 -0
  96. package/dist/agent/tool-search.js +17 -1
  97. package/dist/automations/service.js +4 -10
  98. package/dist/brand-kit/brand-signals.d.ts +13 -0
  99. package/dist/brand-kit/brand-signals.js +15 -0
  100. package/dist/brand-kit/index.d.ts +2 -2
  101. package/dist/brand-kit/index.js +1 -1
  102. package/dist/cli/plan-blocks.d.ts +3 -18
  103. package/dist/cli/plan-blocks.js +2 -95
  104. package/dist/cli/plan-publish-store.d.ts +2 -61
  105. package/dist/cli/plan-publish-store.js +2 -127
  106. package/dist/cli/skills-content/connection.d.ts +1 -1
  107. package/dist/cli/skills-content/connection.js +1 -52
  108. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  109. package/dist/cli/skills-content/visual-recap-skill.js +1 -553
  110. package/dist/client/agent-engine-key.d.ts +14 -4
  111. package/dist/client/agent-engine-key.js +51 -5
  112. package/dist/client/agent-provider-catalog.d.ts +20 -0
  113. package/dist/client/agent-provider-catalog.js +100 -0
  114. package/dist/client/blocks/index.d.ts +1 -0
  115. package/dist/client/blocks/index.js +1 -0
  116. package/dist/client/blocks/library/diagram.js +1 -1
  117. package/dist/client/blocks/library/sanitize-html.js +66 -2
  118. package/dist/client/blocks/library/wireframe-kit.js +69 -0
  119. package/dist/client/chat/run-recovery.js +4 -48
  120. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  121. package/dist/client/chat-first/apps-rail.js +4 -4
  122. package/dist/client/chat-first/copy.js +1 -0
  123. package/dist/client/chat-first/types.d.ts +1 -0
  124. package/dist/client/chat-first.js +4 -3
  125. package/dist/client/i18n.d.ts +14 -0
  126. package/dist/client/i18n.js +18 -0
  127. package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
  128. package/dist/client/settings/ProviderSetupForm.js +145 -0
  129. package/dist/client/settings/SettingsPanel.js +52 -49
  130. package/dist/client/settings/index.d.ts +2 -0
  131. package/dist/client/settings/index.js +2 -0
  132. package/dist/coding-tools/run-code.d.ts +5 -0
  133. package/dist/coding-tools/run-code.js +196 -36
  134. package/dist/coding-tools/tool-orchestration.d.ts +10 -0
  135. package/dist/coding-tools/tool-orchestration.js +107 -0
  136. package/dist/collab/routes.d.ts +1 -1
  137. package/dist/jobs/frontmatter.d.ts +9 -0
  138. package/dist/jobs/frontmatter.js +16 -0
  139. package/dist/jobs/scheduler.js +8 -8
  140. package/dist/jobs/tools.d.ts +1 -1
  141. package/dist/jobs/tools.js +2 -7
  142. package/dist/localization/default-messages.d.ts +20 -0
  143. package/dist/localization/default-messages.js +25 -5
  144. package/dist/notifications/routes.d.ts +3 -3
  145. package/dist/observability/routes.d.ts +2 -2
  146. package/dist/onboarding/app-profile.js +1 -1
  147. package/dist/progress/routes.d.ts +1 -1
  148. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  149. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  150. package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
  151. package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
  152. package/dist/server/agent-chat/run-code-tools.js +3 -1
  153. package/dist/server/agent-chat-plugin.js +6 -6
  154. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  155. package/dist/server/agent-engine-api-key-route.js +43 -12
  156. package/dist/server/agents-bundle.js +2 -1
  157. package/dist/server/auth.js +21 -5
  158. package/dist/server/credential-provider.js +1 -0
  159. package/dist/server/design-token-utils.d.ts +18 -0
  160. package/dist/server/design-token-utils.js +31 -0
  161. package/dist/server/onboarding-html.js +22 -2
  162. package/dist/server/realtime-token.d.ts +1 -1
  163. package/dist/styles/blocks.css +132 -0
  164. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  165. package/dist/templates/chat/app/i18n/index.ts +14 -29
  166. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  167. package/dist/templates/default/app/i18n/index.ts +14 -29
  168. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  169. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  170. package/dist/triggers/dispatcher.js +1 -8
  171. package/docs/content/actions.mdx +4 -1
  172. package/docs/content/agent-surfaces.mdx +8 -6
  173. package/docs/content/automations.mdx +1 -1
  174. package/docs/content/database.mdx +6 -1
  175. package/docs/content/docs-components.mdx +22 -14
  176. package/docs/content/drop-in-agent.mdx +1 -1
  177. package/docs/content/environment-variables.mdx +39 -38
  178. package/docs/content/getting-started-actions.mdx +5 -4
  179. package/docs/content/getting-started-pages.mdx +7 -6
  180. package/docs/content/getting-started.mdx +4 -3
  181. package/docs/content/notifications.mdx +6 -6
  182. package/docs/content/progress.mdx +5 -5
  183. package/docs/content/routing.mdx +3 -1
  184. package/docs/content/server-database.mdx +13 -4
  185. package/docs/content/server-overview.mdx +9 -9
  186. package/docs/content/server-plugins.mdx +10 -4
  187. package/docs/content/server-routes.mdx +7 -2
  188. package/docs/content/tracking.mdx +4 -4
  189. package/docs/content/what-is-agent-native.mdx +4 -4
  190. package/package.json +4 -4
  191. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  192. package/src/templates/chat/app/i18n/index.ts +14 -29
  193. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  194. package/src/templates/default/app/i18n/index.ts +14 -29
  195. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  196. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  197. package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
@@ -16,6 +16,7 @@ import {
16
16
  workspaceMemberIdentityFromContext,
17
17
  } from "../server/lib/require-workspace-member.js";
18
18
  import { createAiServicesGitReadClient } from "../server/triage/ai-services-git.js";
19
+ import { recordFactoryAudit } from "../server/triage/audit.js";
19
20
  import { createGitHubClient } from "../server/triage/github-client.js";
20
21
  import { stableId } from "../server/triage/ids.js";
21
22
  import {
@@ -231,6 +232,34 @@ export default defineAction({
231
232
  factoryTriggered,
232
233
  });
233
234
 
235
+ await recordFactoryAudit(
236
+ context,
237
+ { userEmail, orgId },
238
+ {
239
+ action: "govern-agent-native-pull-request",
240
+ kind: "governance",
241
+ status: governance.autoApprove ? "success" : "skipped",
242
+ itemId: itemId ?? null,
243
+ source: "github",
244
+ sourceUrl: pullRequest.htmlUrl,
245
+ summary: governance.reason,
246
+ details: {
247
+ repo,
248
+ pullRequestNumber,
249
+ clearBug,
250
+ productUxImplications,
251
+ internalBuilderMember: internalMember.isMember,
252
+ factoryTriggered,
253
+ checksPassed,
254
+ reviewFeedbackHandled,
255
+ autoApprove: governance.autoApprove,
256
+ autoMerge: governance.autoMerge,
257
+ ownerOwnedArea: governance.ownerOwnedArea ?? null,
258
+ guardResults: governance.guardResults,
259
+ },
260
+ },
261
+ );
262
+
234
263
  if (itemId) {
235
264
  const item = (
236
265
  await getDb()
@@ -338,6 +367,19 @@ export default defineAction({
338
367
  }
339
368
 
340
369
  if (!governance.autoMerge) {
370
+ await recordFactoryAudit(
371
+ context,
372
+ { userEmail, orgId },
373
+ {
374
+ action: "govern-agent-native-pull-request",
375
+ kind: "external_action",
376
+ itemId: itemId ?? null,
377
+ source: "github",
378
+ sourceUrl: approvalUrl,
379
+ summary: "Approved the pull request after governance checks passed.",
380
+ details: { repo, pullRequestNumber, approvalUrl },
381
+ },
382
+ );
341
383
  return {
342
384
  ok: true,
343
385
  action: "approved",
@@ -374,6 +416,19 @@ export default defineAction({
374
416
  })
375
417
  .where(and(eq(triageItems.id, itemId), eq(triageItems.orgId, orgId)));
376
418
  }
419
+ await recordFactoryAudit(
420
+ context,
421
+ { userEmail, orgId },
422
+ {
423
+ action: "govern-agent-native-pull-request",
424
+ kind: "external_action",
425
+ itemId: itemId ?? null,
426
+ source: "github",
427
+ sourceUrl: pullRequest.htmlUrl,
428
+ summary: "Merged the pull request after governance checks passed.",
429
+ details: { repo, pullRequestNumber, approvalUrl, mergeSha: merge.sha },
430
+ },
431
+ );
377
432
  return {
378
433
  ok: true,
379
434
  action: "merged",
@@ -7,6 +7,7 @@ import {
7
7
  requireWorkspaceMember,
8
8
  workspaceMemberIdentityFromContext,
9
9
  } from "../server/lib/require-workspace-member.js";
10
+ import { recordFactoryAudit } from "../server/triage/audit.js";
10
11
  import { pullRequestSnapshotToEnvelope } from "../server/triage/github-ingestion.js";
11
12
  import { itemDedupeKey } from "../server/triage/ids.js";
12
13
  import type {
@@ -90,6 +91,26 @@ export default defineAction({
90
91
  },
91
92
  });
92
93
 
94
+ await recordFactoryAudit(
95
+ context,
96
+ { userEmail, orgId },
97
+ {
98
+ action: "ingest-github-observation",
99
+ kind: "observed",
100
+ itemId: id,
101
+ source: envelope.source,
102
+ sourceUrl: envelope.sourceUrl,
103
+ summary: envelope.title,
104
+ details: {
105
+ repository: envelope.repository,
106
+ pullRequestNumber: envelope.pullRequestNumber,
107
+ coverage: envelope.coverage,
108
+ reviewCount: input.reviews.length,
109
+ checkCount: input.checks.length,
110
+ },
111
+ },
112
+ );
113
+
93
114
  return {
94
115
  ok: true,
95
116
  id,
@@ -0,0 +1,118 @@
1
+ import { defineAction } from "@agent-native/core/action";
2
+ import {
3
+ listAutomationDefinitions,
4
+ listAutomationRuns,
5
+ } from "@agent-native/core/triggers";
6
+ import { and, desc, eq, inArray } from "drizzle-orm";
7
+ import { z } from "zod";
8
+
9
+ import { getDb } from "../server/db/index.js";
10
+ import { factoryAuditEvents } from "../server/db/schema.js";
11
+ import {
12
+ requireWorkspaceMember,
13
+ workspaceMemberIdentityFromContext,
14
+ } from "../server/lib/require-workspace-member.js";
15
+
16
+ export default defineAction({
17
+ description:
18
+ "List recent Factory automation runs with the bounded source observations, decisions, and external actions recorded for each run.",
19
+ agentTool: false,
20
+ schema: z.object({
21
+ factoryId: z.string().trim().min(1).optional(),
22
+ automation: z.string().trim().min(1).optional(),
23
+ limit: z.coerce.number().int().min(1).max(50).default(20),
24
+ }),
25
+ http: { method: "GET" },
26
+ readOnly: true,
27
+ run: async ({ automation, limit }, context) => {
28
+ const { userEmail, orgId } = await requireWorkspaceMember(
29
+ workspaceMemberIdentityFromContext(context),
30
+ );
31
+ const definitions = await listAutomationDefinitions(
32
+ { userEmail, orgId, appId: "factory" },
33
+ "organization",
34
+ );
35
+ const factoryDefinitions = definitions.filter(
36
+ ({ meta, name }) =>
37
+ meta.domain === "factory" && (!automation || name === automation),
38
+ );
39
+ const runGroups = await Promise.all(
40
+ factoryDefinitions.map(async ({ name, resource }) =>
41
+ listAutomationRuns({
42
+ owners: [resource.owner],
43
+ automation: name,
44
+ appId: "factory",
45
+ limit,
46
+ }),
47
+ ),
48
+ );
49
+ const runs = runGroups.flat().sort((a, b) => b.startedAt - a.startedAt);
50
+ const boundedRuns = runs.slice(0, limit);
51
+ const runIds = boundedRuns
52
+ .map((run) => run.runId)
53
+ .filter((runId): runId is string => Boolean(runId));
54
+
55
+ const db = getDb();
56
+ const events = runIds.length
57
+ ? await db
58
+ .select()
59
+ .from(factoryAuditEvents)
60
+ .where(
61
+ and(
62
+ eq(factoryAuditEvents.orgId, orgId),
63
+ inArray(factoryAuditEvents.automationRunId, runIds),
64
+ ),
65
+ )
66
+ .orderBy(desc(factoryAuditEvents.createdAt))
67
+ : [];
68
+ const eventsByRun = new Map<string, typeof events>();
69
+ for (const event of events) {
70
+ if (!event.automationRunId) continue;
71
+ const current = eventsByRun.get(event.automationRunId) ?? [];
72
+ current.push(event);
73
+ eventsByRun.set(event.automationRunId, current);
74
+ }
75
+
76
+ return {
77
+ runs: boundedRuns.map((run) => ({
78
+ id: run.id,
79
+ automation: run.automation,
80
+ runId: run.runId,
81
+ threadId: run.threadId,
82
+ status: run.status,
83
+ startedAt: run.startedAt,
84
+ finishedAt: run.finishedAt,
85
+ error: run.error,
86
+ events: (eventsByRun.get(run.runId ?? "") ?? []).map((event) => ({
87
+ id: event.id,
88
+ automationRunId: event.automationRunId,
89
+ automationThreadId: event.automationThreadId,
90
+ automationName: event.automationName,
91
+ itemId: event.itemId,
92
+ source: event.source,
93
+ sourceUrl: event.sourceUrl,
94
+ action: event.action,
95
+ kind: event.kind,
96
+ status: event.status,
97
+ summary: event.summary,
98
+ details: parseDetails(event.detailsJson),
99
+ createdAt: event.createdAt,
100
+ })),
101
+ })),
102
+ count: boundedRuns.length,
103
+ };
104
+ },
105
+ });
106
+
107
+ function parseDetails(value: string): Record<string, unknown> {
108
+ let parsed: unknown;
109
+ try {
110
+ parsed = JSON.parse(value);
111
+ } catch {
112
+ throw new Error("Factory audit details are unreadable.");
113
+ }
114
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
115
+ throw new Error("Factory audit details are unreadable.");
116
+ }
117
+ return parsed as Record<string, unknown>;
118
+ }
@@ -22,7 +22,7 @@ export default defineAction({
22
22
  workspaceMemberIdentityFromContext(context),
23
23
  );
24
24
  const definitions = await listAutomationDefinitions(
25
- { userEmail, orgId },
25
+ { userEmail, orgId, appId: "factory" },
26
26
  "organization",
27
27
  );
28
28
  return Promise.all(
@@ -45,6 +45,7 @@ export default defineAction({
45
45
  runs: await listAutomationRuns({
46
46
  owners: [resource.owner],
47
47
  automation: name,
48
+ appId: "factory",
48
49
  limit: 20,
49
50
  }),
50
51
  })),
@@ -8,6 +8,7 @@ import {
8
8
  requireWorkspaceMember,
9
9
  workspaceMemberIdentityFromContext,
10
10
  } from "../server/lib/require-workspace-member.js";
11
+ import { recordFactoryAudit } from "../server/triage/audit.js";
11
12
  import {
12
13
  triageItemStatusSchema,
13
14
  triageSourceSchema,
@@ -24,7 +25,7 @@ export default defineAction({
24
25
  http: { method: "GET" },
25
26
  readOnly: true,
26
27
  run: async ({ status, source, limit }, context) => {
27
- const { orgId } = await requireWorkspaceMember(
28
+ const { userEmail, orgId } = await requireWorkspaceMember(
28
29
  workspaceMemberIdentityFromContext(context),
29
30
  );
30
31
  const db = getDb();
@@ -54,7 +55,7 @@ export default defineAction({
54
55
  }
55
56
  }
56
57
 
57
- return items.map((item) => {
58
+ const listedItems = items.map((item) => {
58
59
  const latestDecision = latestByItem.get(item.id);
59
60
  return {
60
61
  id: item.id,
@@ -86,5 +87,26 @@ export default defineAction({
86
87
  : null,
87
88
  };
88
89
  });
90
+
91
+ for (const item of listedItems) {
92
+ await recordFactoryAudit(
93
+ context,
94
+ { userEmail, orgId },
95
+ {
96
+ action: "list-triage-items",
97
+ kind: "read",
98
+ itemId: item.itemId,
99
+ source: item.source,
100
+ sourceUrl: item.sourceUrl,
101
+ summary: item.title,
102
+ details: {
103
+ status: item.status,
104
+ coverage: item.coverage,
105
+ decision: item.latestDecision?.outcome ?? null,
106
+ },
107
+ },
108
+ );
109
+ }
110
+ return listedItems;
89
111
  },
90
112
  });
@@ -9,6 +9,7 @@ import {
9
9
  requireWorkspaceMember,
10
10
  workspaceMemberIdentityFromContext,
11
11
  } from "../server/lib/require-workspace-member.js";
12
+ import { recordFactoryAudit } from "../server/triage/audit.js";
12
13
  import { createGitHubClient } from "../server/triage/github-client.js";
13
14
  import { itemDedupeKey } from "../server/triage/ids.js";
14
15
  import { mergeTriageMetadata } from "../server/triage/metadata.js";
@@ -193,6 +194,65 @@ export default defineAction({
193
194
  }
194
195
  });
195
196
 
197
+ if (issues.length === 0 && pullRequests.length === 0) {
198
+ await recordFactoryAudit(
199
+ context,
200
+ { userEmail, orgId },
201
+ {
202
+ action: "poll-github-sources",
203
+ kind: "observed",
204
+ source: "github",
205
+ summary: "No open GitHub issues or pull requests were observed.",
206
+ details: { repository: repositoryName },
207
+ },
208
+ );
209
+ } else {
210
+ for (const issue of issues) {
211
+ await recordFactoryAudit(
212
+ context,
213
+ { userEmail, orgId },
214
+ {
215
+ action: "poll-github-sources",
216
+ kind: "observed",
217
+ itemId: itemDedupeKey(
218
+ {
219
+ source: "github_issue",
220
+ externalId: `${repositoryName}#${issue.number}`,
221
+ },
222
+ orgId,
223
+ ),
224
+ source: "github_issue",
225
+ sourceUrl: issue.htmlUrl,
226
+ summary: issue.title,
227
+ details: { repository: repositoryName, number: issue.number },
228
+ },
229
+ );
230
+ }
231
+ for (const pullRequest of pullRequests) {
232
+ await recordFactoryAudit(
233
+ context,
234
+ { userEmail, orgId },
235
+ {
236
+ action: "poll-github-sources",
237
+ kind: "observed",
238
+ itemId: itemDedupeKey(
239
+ {
240
+ source: "github",
241
+ externalId: `${repositoryName}#${pullRequest.number}`,
242
+ repository: repositoryName,
243
+ pullRequestNumber: pullRequest.number,
244
+ },
245
+ orgId,
246
+ ),
247
+ source: "github",
248
+ sourceUrl: pullRequest.htmlUrl,
249
+ summary: pullRequest.title,
250
+ details: { repository: repositoryName, number: pullRequest.number },
251
+ },
252
+ );
253
+ }
254
+ }
255
+
196
256
  return {
197
257
  ok: true,
198
258
  repository: repositoryName,
@@ -9,6 +9,7 @@ import {
9
9
  requireWorkspaceMember,
10
10
  workspaceMemberIdentityFromContext,
11
11
  } from "../server/lib/require-workspace-member.js";
12
+ import { recordFactoryAudit } from "../server/triage/audit.js";
12
13
  import { itemDedupeKey } from "../server/triage/ids.js";
13
14
  import { mergeTriageMetadata } from "../server/triage/metadata.js";
14
15
  import { createSentryClient } from "../server/triage/sentry-client.js";
@@ -151,6 +152,44 @@ export default defineAction({
151
152
  .where(and(eq(triageConfig.id, orgId), eq(triageConfig.orgId, orgId)));
152
153
  });
153
154
 
155
+ if (observedIssues.length === 0) {
156
+ await recordFactoryAudit(
157
+ context,
158
+ { userEmail, orgId },
159
+ {
160
+ action: "poll-sentry-errors",
161
+ kind: "observed",
162
+ source: "sentry",
163
+ summary: "No unresolved Sentry errors were observed.",
164
+ details: { sentryOrgSlug: config.sentryOrgSlug },
165
+ },
166
+ );
167
+ } else {
168
+ for (const issue of observedIssues) {
169
+ await recordFactoryAudit(
170
+ context,
171
+ { userEmail, orgId },
172
+ {
173
+ action: "poll-sentry-errors",
174
+ kind: "observed",
175
+ itemId: itemDedupeKey(
176
+ { source: "sentry", externalId: issue.id },
177
+ orgId,
178
+ ),
179
+ source: "sentry",
180
+ sourceUrl: issue.permalink,
181
+ summary: issue.title,
182
+ details: {
183
+ shortId: issue.shortId,
184
+ level: issue.level,
185
+ count: issue.count,
186
+ projectSlug: issue.projectSlug,
187
+ },
188
+ },
189
+ );
190
+ }
191
+ }
192
+
154
193
  return {
155
194
  ok: true,
156
195
  observed: observedIssues.length,
@@ -4,10 +4,12 @@ import { z } from "zod";
4
4
 
5
5
  import { getDb } from "../server/db/index.js";
6
6
  import { triageConfig, triageItems } from "../server/db/schema.js";
7
+ import { requireFactoryAutomation } from "../server/lib/require-factory-automation.js";
7
8
  import {
8
9
  requireWorkspaceMember,
9
10
  workspaceMemberIdentityFromContext,
10
11
  } from "../server/lib/require-workspace-member.js";
12
+ import { recordFactoryAudit } from "../server/triage/audit.js";
11
13
  import { itemDedupeKey } from "../server/triage/ids.js";
12
14
  import { pollSlackChannel } from "../server/triage/slack-poller.js";
13
15
 
@@ -17,11 +19,16 @@ export default defineAction({
17
19
  schema: z.object({
18
20
  channelId: z.string().trim().min(1).max(128).optional(),
19
21
  }),
20
- http: { method: "POST" },
22
+ http: false,
21
23
  run: async ({ channelId: requestedChannelId }, context) => {
22
24
  const { userEmail, orgId } = await requireWorkspaceMember(
23
25
  workspaceMemberIdentityFromContext(context),
24
26
  );
27
+ await requireFactoryAutomation(
28
+ context,
29
+ { userEmail, orgId },
30
+ "sourcePolling",
31
+ );
25
32
  const db = getDb();
26
33
  const config = (
27
34
  await db
@@ -106,6 +113,43 @@ export default defineAction({
106
113
  }
107
114
  });
108
115
 
116
+ if (result.envelopes.length === 0) {
117
+ await recordFactoryAudit(
118
+ context,
119
+ { userEmail, orgId },
120
+ {
121
+ action: "poll-slack-channel",
122
+ kind: "observed",
123
+ source: "slack",
124
+ summary: "No new Slack feedback was observed.",
125
+ details: {
126
+ channelId,
127
+ coverage: result.hasMore ? "partial" : "complete",
128
+ },
129
+ },
130
+ );
131
+ } else {
132
+ for (const envelope of result.envelopes) {
133
+ await recordFactoryAudit(
134
+ context,
135
+ { userEmail, orgId },
136
+ {
137
+ action: "poll-slack-channel",
138
+ kind: "observed",
139
+ itemId: itemDedupeKey(envelope, orgId),
140
+ source: envelope.source,
141
+ sourceUrl: envelope.sourceUrl ?? null,
142
+ summary: envelope.summary ?? envelope.title,
143
+ details: {
144
+ channelId,
145
+ threadTs: envelope.threadTs ?? null,
146
+ coverage: envelope.coverage,
147
+ },
148
+ },
149
+ );
150
+ }
151
+ }
152
+
109
153
  return {
110
154
  ok: true,
111
155
  source: "slack",
@@ -24,7 +24,7 @@ export default defineAction({
24
24
  workspaceMemberIdentityFromContext(context),
25
25
  );
26
26
  const definitions = await listAutomationDefinitions(
27
- { userEmail, orgId },
27
+ { userEmail, orgId, appId: "factory" },
28
28
  "organization",
29
29
  );
30
30
  const definition = definitions.find(
@@ -32,7 +32,7 @@ export default defineAction({
32
32
  workspaceMemberIdentityFromContext(context),
33
33
  );
34
34
  const definitions = await listAutomationDefinitions(
35
- { userEmail, orgId },
35
+ { userEmail, orgId, appId: "factory" },
36
36
  "organization",
37
37
  );
38
38
  const definition = definitions.find(
@@ -46,7 +46,7 @@ export default defineAction({
46
46
  );
47
47
  }
48
48
  const updated = await updateAutomation(
49
- { userEmail, orgId },
49
+ { userEmail, orgId, appId: "factory" },
50
50
  {
51
51
  name: definition.name,
52
52
  scope: "organization",
@@ -14,6 +14,7 @@ import {
14
14
  requireWorkspaceMember,
15
15
  workspaceMemberIdentityFromContext,
16
16
  } from "../server/lib/require-workspace-member.js";
17
+ import { recordFactoryAudit } from "../server/triage/audit.js";
17
18
  import { startBuilderRun } from "../server/triage/builder-executor.js";
18
19
  import { stableId } from "../server/triage/ids.js";
19
20
  import {
@@ -182,6 +183,26 @@ export default defineAction({
182
183
  : reason,
183
184
  guardResults,
184
185
  });
186
+ await recordFactoryAudit(
187
+ context,
188
+ { userEmail, orgId },
189
+ {
190
+ action: "start-builder-for-item",
191
+ kind: "decision",
192
+ itemId,
193
+ source: item.source,
194
+ sourceUrl: item.sourceUrl,
195
+ status: blocked ? "skipped" : "success",
196
+ summary: blocked ? "Factory kept this item for manual review." : reason,
197
+ details: {
198
+ decisionId,
199
+ clearBug,
200
+ productUxImplications,
201
+ ownerOwnedArea: ownerOwnedArea ?? null,
202
+ guardResults,
203
+ },
204
+ },
205
+ );
185
206
  if (blocked) {
186
207
  await db
187
208
  .update(triageItems)
@@ -332,6 +353,19 @@ export default defineAction({
332
353
  updatedAt: new Date().toISOString(),
333
354
  })
334
355
  .where(and(eq(triageItems.id, itemId), eq(triageItems.orgId, orgId)));
356
+ await recordFactoryAudit(
357
+ context,
358
+ { userEmail, orgId },
359
+ {
360
+ action: "start-builder-for-item",
361
+ kind: "external_action",
362
+ itemId,
363
+ source: item.source,
364
+ sourceUrl: item.sourceUrl,
365
+ summary: "Tagged Builder in the Slack thread and requested a PR.",
366
+ details: { provider: "bot-tag", runId },
367
+ },
368
+ );
335
369
  return {
336
370
  ok: true,
337
371
  started: true,
@@ -385,6 +419,23 @@ export default defineAction({
385
419
  updatedAt: new Date().toISOString(),
386
420
  })
387
421
  .where(and(eq(triageItems.id, itemId), eq(triageItems.orgId, orgId)));
422
+ await recordFactoryAudit(
423
+ context,
424
+ { userEmail, orgId },
425
+ {
426
+ action: "start-builder-for-item",
427
+ kind: "external_action",
428
+ itemId,
429
+ source: item.source,
430
+ sourceUrl: item.sourceUrl,
431
+ summary: "Submitted the clear bug to Builder.",
432
+ details: {
433
+ provider: "builder-http",
434
+ runId,
435
+ providerTaskId: result.providerTaskId ?? null,
436
+ },
437
+ },
438
+ );
388
439
  return {
389
440
  ok: true,
390
441
  started: true,