@undefineds.co/linx 0.3.15 → 0.3.16

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.
@@ -7,7 +7,7 @@ import { decideThreadControlEvent } from '../../../vendor/agent-runtime/dist/thr
7
7
  import { createLinxPodSyncScope } from '../../../vendor/agent-runtime/dist/sync.js';
8
8
  import { insertExactRecordOnce, resolvePodResourceTemplateValue, upsertExactRecord, } from '@undefineds.co/drizzle-solid';
9
9
  import { getDefaultPodDataSession } from '../pod-data-session.js';
10
- import { ContactClass, ContactType, chatRepository, agentResource, contactResource, deliveryResource, ideaResource, issueResource, messageResource, reportResource, runResource, runStepResource, sessionResource, taskResource, threadRepository, } from '../models.js';
10
+ import { ContactClass, ContactType, chatRepository, agentResource, contactResource, deliveryResource, ideaResource, issueResource, messageResource, runResource, runStepResource, sessionResource, taskResource, threadRepository, } from '../models.js';
11
11
  import { pathToWorkspaceUri } from '../pi-adapter/pod-mirror-mapping.js';
12
12
  import { getSymphonyHome } from './archive.js';
13
13
  const SYMPHONY_CHAT_ID = 'symphony';
@@ -16,191 +16,6 @@ const SYMPHONY_CONTACT_ID = 'symphony';
16
16
  const SYMPHONY_POLICY_VERSION = 'linx-symphony-session/v1';
17
17
  const SYMPHONY_WORKER_POD_ACCESS_POLICY_VERSION = 'linx-symphony-worker-pod-access/v1';
18
18
  const SYMPHONY_ARCHIVE_PROVENANCE_VERSION = 'linx-symphony-archive/v1';
19
- function ensureTrailingSlash(value) {
20
- return value.endsWith('/') ? value : `${value}/`;
21
- }
22
- function podBaseUrlFromWebId(webId) {
23
- const marker = '/profile/card#me';
24
- if (webId.includes(marker)) {
25
- return `${webId.slice(0, webId.indexOf(marker) + 1)}`;
26
- }
27
- const url = new URL(webId);
28
- return `${url.origin}/`;
29
- }
30
- function podFileUrlFromWebId(webId, path) {
31
- return new URL(path.replace(/^\/+/, ''), podBaseUrlFromWebId(webId)).toString();
32
- }
33
- function podFileUrl(podSession, path) {
34
- return new URL(path.replace(/^\/+/, ''), ensureTrailingSlash(podSession.podUrl)).toString();
35
- }
36
- async function writePodFileToSession(session, file) {
37
- const url = podFileUrl(session, file.path);
38
- await ensurePodResourceContainers(session.fetch, url);
39
- const response = await session.fetch(url, {
40
- method: 'PUT',
41
- headers: { 'Content-Type': file.contentType },
42
- body: file.content.endsWith('\n') ? file.content : `${file.content}\n`,
43
- });
44
- if (!response.ok) {
45
- const details = await response.text().catch(() => '');
46
- const suffix = details.trim() ? ` - ${details.trim().slice(0, 500)}` : '';
47
- throw new Error(`Failed to write Symphony Pod file ${url}: ${response.status} ${response.statusText}${suffix}`);
48
- }
49
- }
50
- async function ensurePodResourceContainers(fetcher, resourceUrl) {
51
- for (const containerUrl of containerUrlsForResource(resourceUrl)) {
52
- const existing = await fetcher(containerUrl, { method: 'HEAD' }).catch(() => null);
53
- if (existing?.ok)
54
- continue;
55
- if (existing && existing.status !== 404 && existing.status !== 405)
56
- continue;
57
- const response = await fetcher(containerUrl, {
58
- method: 'PUT',
59
- headers: {
60
- Link: '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"',
61
- 'Content-Type': 'text/turtle; charset=utf-8',
62
- },
63
- body: '',
64
- });
65
- if (!response.ok && response.status !== 409) {
66
- throw new Error(`Failed to ensure Symphony Pod container ${containerUrl}: ${response.status} ${response.statusText}`);
67
- }
68
- }
69
- }
70
- function containerUrlsForResource(resourceUrl) {
71
- const url = new URL(resourceUrl);
72
- const parts = url.pathname.split('/').filter(Boolean);
73
- const containers = [];
74
- let path = '/';
75
- for (let index = 0; index < parts.length - 1; index += 1) {
76
- path += `${parts[index]}/`;
77
- containers.push(new URL(path, url.origin).toString());
78
- }
79
- return containers;
80
- }
81
- function datePathParts(input) {
82
- const date = safeDate(input);
83
- return {
84
- yyyy: String(date.getUTCFullYear()),
85
- MM: String(date.getUTCMonth() + 1).padStart(2, '0'),
86
- dd: String(date.getUTCDate()).padStart(2, '0'),
87
- };
88
- }
89
- function buildSymphonyIssueDocumentPath(issue) {
90
- return `/.data/issues/${buildSymphonyIssueId(issue)}/issue.md`;
91
- }
92
- function buildSymphonyIdeaDocumentPath(idea) {
93
- const { yyyy, MM, dd } = datePathParts(idea.createdAt);
94
- return `/.data/ideas/${yyyy}/${MM}/${dd}/${getSymphonyArchiveKey(idea.uri)}/idea.md`;
95
- }
96
- function buildSymphonyReportDocumentPath(worker) {
97
- const { yyyy, MM, dd } = datePathParts(worker.session.completedAt ?? worker.session.updatedAt);
98
- return `/.data/reports/${yyyy}/${MM}/${dd}/${getSymphonyArchiveKey(worker.session.uri)}-report.md`;
99
- }
100
- function renderMarkdownList(items) {
101
- const values = (items ?? []).map((item) => item.trim()).filter(Boolean);
102
- return values.length > 0 ? values.map((item) => `- ${item}`).join('\n') : '- None recorded.';
103
- }
104
- function renderSymphonyIssueMarkdown(plan) {
105
- const issue = plan.issue;
106
- const sections = [
107
- `# ${issue.title || buildSymphonyIssueId(issue)}`,
108
- '',
109
- '## Summary',
110
- issue.description?.trim() || issue.title || 'No summary recorded.',
111
- '',
112
- '## Status',
113
- `- Status: ${issue.status}`,
114
- `- Priority: ${issue.priority}`,
115
- `- Source: ${issue.source}`,
116
- '',
117
- '## Acceptance Criteria',
118
- renderMarkdownList(plan.workers.flatMap((worker) => worker.taskRecord.acceptanceCriteria ?? [])),
119
- '',
120
- '## Tasks',
121
- renderMarkdownList(plan.workers.map((worker) => `${worker.taskRecord.title}: ${worker.taskRecord.objective}`)),
122
- '',
123
- '## Source Context',
124
- `- Chat: ${issue.chat ?? plan.session.chat ?? 'not recorded'}`,
125
- `- Thread: ${issue.thread ?? plan.session.thread ?? 'not recorded'}`,
126
- `- Messages: ${(issue.messages ?? []).join(', ') || 'not recorded'}`,
127
- '',
128
- '## Control Records',
129
- `- Issue: ${issue.uri}`,
130
- ...plan.workers.flatMap((worker) => [
131
- `- Task: ${worker.task}`,
132
- `- Delivery: ${worker.delivery.uri}`,
133
- `- Session: ${worker.session.uri}`,
134
- ]),
135
- ];
136
- return sections.join('\n');
137
- }
138
- function renderSymphonyIdeaMarkdown(idea) {
139
- return [
140
- `# ${idea.summary || getSymphonyArchiveKey(idea.uri)}`,
141
- '',
142
- '## Input',
143
- idea.input?.trim() || idea.summary || 'No input recorded.',
144
- '',
145
- '## Current Understanding',
146
- idea.currentUnderstanding?.trim() || 'No current understanding recorded.',
147
- '',
148
- '## Open Questions',
149
- renderMarkdownList(idea.openQuestions),
150
- '',
151
- '## Conflicts',
152
- renderMarkdownList(idea.conflicts),
153
- '',
154
- '## Next Step',
155
- idea.nextStep?.trim() || 'No next step recorded.',
156
- '',
157
- '## Source Context',
158
- `- Status: ${idea.status}`,
159
- `- Commitment: ${idea.commitment}`,
160
- `- Chat: ${idea.chat ?? 'not recorded'}`,
161
- `- Thread: ${idea.thread ?? 'not recorded'}`,
162
- `- Messages: ${(idea.messages ?? []).join(', ') || 'not recorded'}`,
163
- `- Idea: ${idea.uri}`,
164
- ].join('\n');
165
- }
166
- function renderSymphonyReportMarkdown(plan, worker, stage) {
167
- const status = worker.session.status === 'failed' || stage === 'failed' ? 'failed' : 'completed';
168
- const summary = status === 'completed'
169
- ? `${worker.taskRecord.title} completed.`
170
- : `${worker.taskRecord.title} failed: ${worker.session.error ?? worker.delivery.error ?? 'worker did not complete successfully.'}`;
171
- return [
172
- `# ${worker.taskRecord.title} — ${status}`,
173
- '',
174
- '## Summary',
175
- summary,
176
- '',
177
- '## Outcome',
178
- `- Status: ${status}`,
179
- `- Backend: ${worker.session.backend}`,
180
- `- Agent: ${worker.session.target.agent ?? worker.delivery.targetAgent}`,
181
- `- Auto mode session: ${worker.session.autoModeSessionId ?? 'not recorded'}`,
182
- `- Exit code: ${worker.session.exitCode ?? 'not recorded'}`,
183
- '',
184
- '## Task',
185
- worker.taskRecord.objective,
186
- '',
187
- '## Acceptance Criteria',
188
- renderMarkdownList(worker.taskRecord.acceptanceCriteria),
189
- '',
190
- '## Linked Control Records',
191
- `- Issue: ${buildSymphonyIssueId(plan.issue)}`,
192
- `- Task: ${worker.task}`,
193
- `- Delivery: ${worker.delivery.uri}`,
194
- `- Session: ${worker.session.uri}`,
195
- `- Run status: ${worker.session.status}`,
196
- '',
197
- ...(worker.session.error || worker.delivery.error || worker.taskRecord.error ? [
198
- '## Error',
199
- worker.session.error ?? worker.delivery.error ?? worker.taskRecord.error ?? '',
200
- '',
201
- ] : []),
202
- ].join('\n');
203
- }
204
19
  function normalizeSymphonyRunPlan(plan) {
205
20
  const workers = Array.isArray(plan.workers) && plan.workers.length > 0
206
21
  ? plan.workers
@@ -304,14 +119,12 @@ async function createDefaultRuntime() {
304
119
  issueResource: models.issueResource,
305
120
  taskResource: models.taskResource,
306
121
  deliveryResource: models.deliveryResource,
307
- reportResource: models.reportResource,
308
122
  runResource: models.runResource,
309
123
  runStepResource: models.runStepResource,
310
124
  agentResource: models.agentResource,
311
- contactResource: models.contactTable,
125
+ contactResource: models.contactResource,
312
126
  auditResource: models.auditResource,
313
127
  inboxNotificationResource: models.inboxNotificationResource,
314
- writePodFile: writePodFileToSession,
315
128
  };
316
129
  }
317
130
  function selectTargetChatIri(value, webId, plan) {
@@ -398,13 +211,6 @@ function buildSymphonyReportDeliveryIri(webId, worker) {
398
211
  createdAt: safeDate(worker.session.completedAt ?? worker.session.updatedAt),
399
212
  });
400
213
  }
401
- function buildSymphonyReportIri(webId, worker) {
402
- return reportResource.buildIri(webId, {
403
- id: `${getSymphonyArchiveKey(worker.session.uri)}-report`,
404
- task: buildSymphonyTaskIri(webId, worker.task),
405
- createdAt: safeDate(worker.session.completedAt ?? worker.session.updatedAt),
406
- });
407
- }
408
214
  function buildSymphonyRunIri(webId, worker) {
409
215
  return runResource.buildIri(webId, {
410
216
  id: getSymphonyArchiveKey(worker.session.uri),
@@ -1002,11 +808,8 @@ function buildSymphonyIssueRow(plan, webId) {
1002
808
  const updatedAt = safeDate(plan.issue.updatedAt);
1003
809
  return {
1004
810
  id: buildSymphonyIssueId(plan.issue),
1005
- // File-primary: title remains a compact index label for existing Issue schemas.
1006
- // The full problem statement and acceptance narrative live in issue.md.
1007
811
  title: plan.issue.title,
1008
- document: podFileUrlFromWebId(webId, buildSymphonyIssueDocumentPath(plan.issue)),
1009
- description: undefined,
812
+ description: plan.issue.description,
1010
813
  status: plan.issue.status,
1011
814
  priority: plan.issue.priority,
1012
815
  labels: ['symphony'],
@@ -1027,17 +830,15 @@ function buildSymphonyIdeaRow(idea, webId) {
1027
830
  return {
1028
831
  id: getSymphonyArchiveKey(idea.uri),
1029
832
  summary: idea.summary,
1030
- document: podFileUrlFromWebId(webId, buildSymphonyIdeaDocumentPath(idea)),
1031
- // File-primary: the source text lives in idea.md; TTL keeps only routing/index facts.
1032
- input: undefined,
833
+ input: idea.input,
1033
834
  status: idea.status,
1034
835
  commitment: idea.commitment,
1035
836
  affectedArea: idea.affectedArea,
1036
- currentUnderstanding: undefined,
1037
- openQuestions: undefined,
837
+ currentUnderstanding: idea.currentUnderstanding,
838
+ openQuestions: idea.openQuestions,
1038
839
  related: idea.relatedRecords,
1039
- conflicts: undefined,
1040
- nextStep: undefined,
840
+ conflicts: idea.conflicts,
841
+ nextStep: idea.nextStep,
1041
842
  promotedTo: idea.promotedTo,
1042
843
  chat: idea.chat,
1043
844
  thread: idea.thread,
@@ -1045,8 +846,6 @@ function buildSymphonyIdeaRow(idea, webId) {
1045
846
  createdBy: webId,
1046
847
  metadata: {
1047
848
  surface: 'symphony',
1048
- filePrimary: true,
1049
- documentPath: buildSymphonyIdeaDocumentPath(idea),
1050
849
  ...buildSymphonyArchiveMetadata({ idea: idea.uri }),
1051
850
  },
1052
851
  createdAt,
@@ -1166,61 +965,6 @@ function buildSymphonyDeliveryRow(plan, webId, worker) {
1166
965
  updatedAt,
1167
966
  };
1168
967
  }
1169
- function buildSymphonyReportRow(plan, webId, worker, stage) {
1170
- const completedAt = safeDate(worker.session.completedAt ?? worker.session.updatedAt);
1171
- const workerAgent = agentResource.buildIri(webId, {
1172
- id: buildWorkerAgentId(worker.session.backend, worker.session.target.agent),
1173
- });
1174
- const run = buildSymphonyRunIri(webId, worker);
1175
- const task = buildSymphonyTaskIri(webId, worker.task);
1176
- const status = worker.session.status === 'failed' || stage === 'failed' ? 'failed' : 'completed';
1177
- const summary = status === 'completed'
1178
- ? `${worker.taskRecord.title} completed.`
1179
- : `${worker.taskRecord.title} failed: ${worker.session.error ?? worker.delivery.error ?? 'worker did not complete successfully.'}`;
1180
- return {
1181
- id: reportResource.buildId({
1182
- id: `${getSymphonyArchiveKey(worker.session.uri)}-report`,
1183
- task,
1184
- createdAt: completedAt,
1185
- }),
1186
- reportKind: 'handoff',
1187
- status: 'published',
1188
- outcome: status === 'completed' ? 'accepted' : 'blocked',
1189
- about: run,
1190
- issue: buildSymphonyIssueIri(webId, plan.issue),
1191
- task,
1192
- delivery: buildSymphonyDeliveryIri(webId, worker),
1193
- run,
1194
- thread: selectWorkerThreadIri(plan, webId, worker),
1195
- evidence: [
1196
- buildSymphonyRunStepIri(webId, worker, stage),
1197
- ],
1198
- summary,
1199
- actor: workerAgent,
1200
- source: podFileUrlFromWebId(webId, buildSymphonyReportDocumentPath(worker)),
1201
- metricFacts: {
1202
- backend: worker.session.backend,
1203
- agent: worker.session.target.agent,
1204
- autoModeSessionId: worker.session.autoModeSessionId,
1205
- exitCode: worker.session.exitCode,
1206
- },
1207
- metadata: {
1208
- surface: 'symphony',
1209
- filePrimary: true,
1210
- reportFile: buildSymphonyReportDocumentPath(worker),
1211
- reportDelivery: buildSymphonyReportDeliveryIri(webId, worker),
1212
- ...buildSymphonyArchiveMetadata({
1213
- issue: plan.issue.uri,
1214
- task: worker.task,
1215
- delivery: worker.delivery.uri,
1216
- session: worker.session.uri,
1217
- }),
1218
- },
1219
- createdAt: completedAt,
1220
- publishedAt: completedAt,
1221
- updatedAt: completedAt,
1222
- };
1223
- }
1224
968
  function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1225
969
  const completedAt = safeDate(worker.session.completedAt ?? worker.session.updatedAt);
1226
970
  const workerAgent = agentResource.buildIri(webId, {
@@ -1228,7 +972,6 @@ function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1228
972
  });
1229
973
  const secretaryAgent = agentResource.buildIri(webId, { id: SYMPHONY_SECRETARY_AGENT_ID });
1230
974
  const run = buildSymphonyRunIri(webId, worker);
1231
- const report = buildSymphonyReportIri(webId, worker);
1232
975
  const task = buildSymphonyTaskIri(webId, worker.task);
1233
976
  const originalDelivery = buildSymphonyDeliveryIri(webId, worker);
1234
977
  const status = worker.session.status === 'failed' || stage === 'failed' ? 'failed' : 'completed';
@@ -1251,7 +994,7 @@ function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1251
994
  targetThread: selectTargetThreadIri(plan.issue.thread ?? worker.session.target?.thread, webId, plan),
1252
995
  targetSession: buildSymphonyControlSessionUri(webId, plan),
1253
996
  actor: workerAgent,
1254
- object: report,
997
+ object: run,
1255
998
  objective: summary,
1256
999
  payload: {
1257
1000
  kind: 'symphony_report',
@@ -1260,7 +1003,6 @@ function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1260
1003
  issue: buildSymphonyIssueIri(webId, plan.issue),
1261
1004
  task,
1262
1005
  delivery: originalDelivery,
1263
- report,
1264
1006
  reportDelivery: buildSymphonyReportDeliveryIri(webId, worker),
1265
1007
  session: buildSymphonyControlSessionUri(webId, plan),
1266
1008
  run,
@@ -1269,7 +1011,6 @@ function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1269
1011
  autoModeSessionId: worker.session.autoModeSessionId,
1270
1012
  exitCode: worker.session.exitCode,
1271
1013
  error: worker.session.error ?? worker.delivery.error ?? worker.taskRecord.error,
1272
- reportFile: buildSymphonyReportDocumentPath(worker),
1273
1014
  evidence: {
1274
1015
  statusMessage: buildSymphonyMessageUri(webId, plan, buildStatusMessageRow(plan, webId, stage)),
1275
1016
  runStep: buildSymphonyRunStepIri(webId, worker, stage),
@@ -1289,8 +1030,6 @@ function buildSymphonyReportDeliveryRow(plan, webId, worker, stage) {
1289
1030
  session: worker.session.uri,
1290
1031
  }),
1291
1032
  reportKind: 'worker-completion',
1292
- filePrimary: true,
1293
- reportFile: buildSymphonyReportDocumentPath(worker),
1294
1033
  },
1295
1034
  error: status === 'failed' ? worker.session.error ?? worker.delivery.error ?? worker.taskRecord.error : undefined,
1296
1035
  createdAt: completedAt,
@@ -1632,7 +1371,6 @@ async function upsertIssue(db, runtime, row) {
1632
1371
  await upsertExactRecord(db, runtime.issueResource, { id: row.id }, row, {
1633
1372
  title: row.title,
1634
1373
  description: row.description,
1635
- document: row.document,
1636
1374
  status: row.status,
1637
1375
  priority: row.priority,
1638
1376
  labels: row.labels,
@@ -1647,7 +1385,6 @@ async function upsertIssue(db, runtime, row) {
1647
1385
  async function upsertIdea(db, runtime, row) {
1648
1386
  await upsertExactRecord(db, runtime.ideaResource, { id: row.id }, row, {
1649
1387
  summary: row.summary,
1650
- document: row.document,
1651
1388
  input: row.input,
1652
1389
  status: row.status,
1653
1390
  commitment: row.commitment,
@@ -1682,32 +1419,6 @@ async function upsertTask(db, runtime, row) {
1682
1419
  updatedAt: row.updatedAt,
1683
1420
  });
1684
1421
  }
1685
- async function upsertReport(db, runtime, row) {
1686
- await upsertExactRecord(db, runtime.reportResource, {
1687
- id: row.id,
1688
- task: row.task,
1689
- createdAt: row.createdAt,
1690
- }, row, {
1691
- reportKind: row.reportKind,
1692
- status: row.status,
1693
- outcome: row.outcome,
1694
- about: row.about,
1695
- issue: row.issue,
1696
- task: row.task,
1697
- delivery: row.delivery,
1698
- run: row.run,
1699
- thread: row.thread,
1700
- evidence: row.evidence,
1701
- summary: row.summary,
1702
- reviewer: row.reviewer,
1703
- actor: row.actor,
1704
- source: row.source,
1705
- metricFacts: row.metricFacts,
1706
- metadata: row.metadata,
1707
- publishedAt: row.publishedAt,
1708
- updatedAt: row.updatedAt,
1709
- });
1710
- }
1711
1422
  async function upsertDelivery(db, runtime, row) {
1712
1423
  await upsertExactRecord(db, runtime.deliveryResource, { id: row.id }, row, {
1713
1424
  kind: row.kind,
@@ -1827,7 +1538,6 @@ function collectSymphonyProjectionResources(webId, plan, stages) {
1827
1538
  add('runStep', buildSymphonyRunStepIri(webId, worker, stage));
1828
1539
  }
1829
1540
  if (worker.session.status === 'completed' || worker.session.status === 'failed') {
1830
- add('report', buildSymphonyReportIri(webId, worker));
1831
1541
  add('delivery', buildSymphonyReportDeliveryIri(webId, worker));
1832
1542
  }
1833
1543
  }
@@ -1902,7 +1612,6 @@ export async function persistSymphonyControlStateToPod(plan, options = {}) {
1902
1612
  stages,
1903
1613
  latestMessage,
1904
1614
  shouldUpsertChat: !normalizedPlan.session.target?.chat,
1905
- podSession,
1906
1615
  }),
1907
1616
  });
1908
1617
  return {
@@ -1976,8 +1685,6 @@ function resolveProjectionResourceModel(runtime, kind) {
1976
1685
  return runtime.taskResource;
1977
1686
  if (kind === 'delivery')
1978
1687
  return runtime.deliveryResource;
1979
- if (kind === 'report')
1980
- return runtime.reportResource;
1981
1688
  if (kind === 'run')
1982
1689
  return runtime.runResource;
1983
1690
  if (kind === 'runStep')
@@ -2115,18 +1822,7 @@ export async function persistSymphonyIdeaToPod(idea, options = {}) {
2115
1822
  },
2116
1823
  },
2117
1824
  {
2118
- id: 'symphony.idea.write-file-primary-document',
2119
- kind: 'upsert',
2120
- apply: async () => {
2121
- await runtime.writePodFile?.(podSession, {
2122
- path: buildSymphonyIdeaDocumentPath(idea),
2123
- content: renderSymphonyIdeaMarkdown(idea),
2124
- contentType: 'text/markdown; charset=utf-8',
2125
- });
2126
- },
2127
- },
2128
- {
2129
- id: 'symphony.idea.upsert-meta',
1825
+ id: 'symphony.idea.upsert',
2130
1826
  kind: 'upsert',
2131
1827
  apply: () => upsertIdea(db, runtime, buildSymphonyIdeaRow(idea, podSession.webId)),
2132
1828
  },
@@ -2406,7 +2102,6 @@ function buildSymphonyProjectionOperations(input) {
2406
2102
  input.runtime.issueResource,
2407
2103
  input.runtime.taskResource,
2408
2104
  input.runtime.deliveryResource,
2409
- input.runtime.reportResource,
2410
2105
  input.runtime.runResource,
2411
2106
  input.runtime.runStepResource,
2412
2107
  input.runtime.agentResource,
@@ -2417,18 +2112,7 @@ function buildSymphonyProjectionOperations(input) {
2417
2112
  },
2418
2113
  },
2419
2114
  {
2420
- id: 'symphony.write-file-primary-documents',
2421
- kind: 'upsert',
2422
- apply: async () => {
2423
- await input.runtime.writePodFile?.(input.podSession, {
2424
- path: buildSymphonyIssueDocumentPath(input.plan.issue),
2425
- content: renderSymphonyIssueMarkdown(input.plan),
2426
- contentType: 'text/markdown; charset=utf-8',
2427
- });
2428
- },
2429
- },
2430
- {
2431
- id: 'symphony.upsert-issue-meta',
2115
+ id: 'symphony.upsert-issue',
2432
2116
  kind: 'upsert',
2433
2117
  apply: () => upsertIssue(input.db, input.runtime, buildSymphonyIssueRow(input.plan, input.webId)),
2434
2118
  },
@@ -2501,22 +2185,6 @@ function buildSymphonyReportOperations(input) {
2501
2185
  }
2502
2186
  const terminalStage = input.stage;
2503
2187
  return input.plan.workers.flatMap((worker, index) => [
2504
- {
2505
- id: `symphony.write-report-file:${index + 1}`,
2506
- kind: 'upsert',
2507
- apply: async () => {
2508
- await input.runtime.writePodFile?.(input.podSession, {
2509
- path: buildSymphonyReportDocumentPath(worker),
2510
- content: renderSymphonyReportMarkdown(input.plan, worker, terminalStage),
2511
- contentType: 'text/markdown; charset=utf-8',
2512
- });
2513
- },
2514
- },
2515
- {
2516
- id: `symphony.upsert-report:${index + 1}`,
2517
- kind: 'upsert',
2518
- apply: () => upsertReport(input.db, input.runtime, buildSymphonyReportRow(input.plan, input.webId, worker, terminalStage)),
2519
- },
2520
2188
  {
2521
2189
  id: `symphony.upsert-report-delivery:${index + 1}`,
2522
2190
  kind: 'upsert',