@xdsjs/dossierx-daemon 0.1.13 → 0.1.15

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 (2) hide show
  1. package/dist/index.js +1484 -199
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1,26 +1,912 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { mkdir as mkdir7, stat as stat4 } from "fs/promises";
4
+ import { mkdir as mkdir9, stat as stat5 } from "fs/promises";
5
5
  import os3 from "os";
6
- import path10 from "path";
6
+ import path14 from "path";
7
7
  import { Command } from "commander";
8
- import { DOSSIERX_DEFAULT_WORKSPACE_PATH } from "@xdsjs/dossierx-workspace";
8
+
9
+ // ../../node_modules/.pnpm/@xdsjs+dossierx-workspace@0.1.1/node_modules/@xdsjs/dossierx-workspace/dist/index.js
10
+ import path from "path";
11
+ import { createHash } from "crypto";
12
+ import { mkdir, readdir, readFile, stat, writeFile } from "fs/promises";
13
+ import path2 from "path";
14
+
15
+ // ../../node_modules/.pnpm/@xdsjs+dossierx-shared@0.1.5/node_modules/@xdsjs/dossierx-shared/dist/index.js
16
+ import { z } from "zod";
17
+ import { z as z2 } from "zod";
18
+ import { z as z3 } from "zod";
19
+ import { z as z4 } from "zod";
20
+ import { z as z5 } from "zod";
21
+ import { z as z6 } from "zod";
22
+ import { z as z7 } from "zod";
23
+ import { z as z8 } from "zod";
24
+ import { z as z9 } from "zod";
25
+ import { z as z10 } from "zod";
26
+ var MarketSchema = z.enum(["us", "hk", "cn"]);
27
+ var TickerSchema = z.string().min(1).max(16).transform((value) => value.trim().toUpperCase());
28
+ var ISO_DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
29
+ var ISODateTimeSchema = z.string().refine(
30
+ (value) => ISO_DATE_TIME_PATTERN.test(value) && !Number.isNaN(Date.parse(value)),
31
+ "Invalid ISO datetime"
32
+ );
33
+ var JsonObjectSchema = z.record(z.string(), z.unknown());
34
+ var MachineStatusSchema = z2.enum([
35
+ "offline",
36
+ "online",
37
+ "idle",
38
+ "running",
39
+ "error"
40
+ ]);
41
+ var DaemonCapabilitiesSchema = z2.object({
42
+ git: z2.boolean().default(false),
43
+ node: z2.boolean().default(false),
44
+ python: z2.boolean().default(false),
45
+ financialReports: z2.boolean().default(false),
46
+ financialReportsNotebookLm: z2.boolean().default(false),
47
+ financialReportsSecHtmlRenderer: z2.boolean().default(false),
48
+ investWikiRuntime: z2.boolean().default(false),
49
+ codex: z2.boolean().default(false),
50
+ claude: z2.boolean().default(false)
51
+ });
52
+ var WorkspaceStatusSchema = z3.enum(["ready", "missing", "error"]);
53
+ var MachineTopicSchema = z4.string().regex(/^machine:[a-f0-9-]+$/);
54
+ var TaskAvailableEventSchema = z4.object({
55
+ event: z4.literal("task_available"),
56
+ payload: z4.object({
57
+ taskId: z4.string().uuid(),
58
+ createdAt: ISODateTimeSchema
59
+ })
60
+ });
61
+ var TaskCancelledEventSchema = z4.object({
62
+ event: z4.literal("task_cancelled"),
63
+ payload: z4.object({
64
+ taskId: z4.string().uuid()
65
+ })
66
+ });
67
+ var RealtimeEventSchema = z4.discriminatedUnion("event", [
68
+ TaskAvailableEventSchema,
69
+ TaskCancelledEventSchema
70
+ ]);
71
+ var ManifestPageTypeSchema = z5.enum([
72
+ "right_business",
73
+ "right_people",
74
+ "right_price",
75
+ "wiki",
76
+ "article",
77
+ "source_note"
78
+ ]);
79
+ var ManifestPageSchema = z5.object({
80
+ type: ManifestPageTypeSchema,
81
+ title: z5.string(),
82
+ path: z5.string(),
83
+ size: z5.number().int().nonnegative(),
84
+ hash: z5.string(),
85
+ updatedAt: ISODateTimeSchema
86
+ });
87
+ var CompanyManifestSchema = z5.object({
88
+ schemaVersion: z5.literal(1),
89
+ ticker: TickerSchema,
90
+ market: MarketSchema,
91
+ updatedAt: ISODateTimeSchema,
92
+ commitSha: z5.string().optional(),
93
+ pages: z5.array(ManifestPageSchema)
94
+ });
95
+ var TaskStatusSchema = z6.enum([
96
+ "queued",
97
+ "claimed",
98
+ "running",
99
+ "succeeded",
100
+ "failed",
101
+ "cancelled"
102
+ ]);
103
+ var TaskTypeSchema = z6.enum([
104
+ "mock.write_company_report",
105
+ "workspace.scan",
106
+ "invest_wiki.init_company_vault",
107
+ "invest_wiki.status",
108
+ "invest_wiki.sync",
109
+ "codex.run_invest_wiki_flow",
110
+ "financial_reports.sync_reports",
111
+ "financial_reports.ingest_notebook",
112
+ "financial_reports.extract_facts",
113
+ "financial_reports.refresh_company"
114
+ ]);
115
+ var MockWriteCompanyReportPayloadSchema = z6.object({
116
+ ticker: TickerSchema,
117
+ market: MarketSchema.default("us"),
118
+ companyName: z6.string().optional()
119
+ });
120
+ var WorkspaceScanPayloadSchema = z6.object({});
121
+ var InvestWikiInitCompanyVaultPayloadSchema = z6.object({
122
+ ticker: TickerSchema,
123
+ market: MarketSchema.default("us"),
124
+ companyName: z6.string().trim().min(1),
125
+ cik: z6.string().trim().min(1).optional(),
126
+ exchange: z6.string().trim().min(1).optional()
127
+ });
128
+ var InvestWikiStatusPayloadSchema = z6.object({
129
+ ticker: TickerSchema
130
+ });
131
+ var InvestWikiSyncPayloadSchema = z6.object({
132
+ ticker: TickerSchema,
133
+ dryRun: z6.boolean().default(false)
134
+ });
135
+ var CodexRunInvestWikiFlowPayloadSchema = z6.object({
136
+ ticker: TickerSchema,
137
+ market: z6.literal("us").default("us"),
138
+ companyName: z6.string().trim().min(1).optional(),
139
+ cik: z6.string().trim().min(1).optional(),
140
+ exchange: z6.string().trim().min(1).optional()
141
+ });
142
+ var FinancialReportMarketSchema = z6.enum(["US", "A", "H"]);
143
+ var FinancialReportTypeSchema = z6.enum([
144
+ "annual",
145
+ "half_year",
146
+ "q1",
147
+ "q3"
148
+ ]);
149
+ var FinancialReportListingSchema = z6.object({
150
+ market: FinancialReportMarketSchema,
151
+ ticker: z6.string().trim().min(1).max(32).transform((value) => value.toUpperCase()),
152
+ exchange: z6.string().trim().min(1).optional(),
153
+ currency: z6.string().trim().min(1).optional(),
154
+ primary: z6.boolean().default(false)
155
+ });
156
+ var FinancialReportCninfoIdentifierSchema = z6.object({
157
+ stockCode: z6.string().trim().min(1),
158
+ orgId: z6.string().trim().min(1),
159
+ column: z6.enum(["sse", "szse", "hke"])
160
+ });
161
+ var FinancialReportIssuerIdentifiersSchema = z6.object({
162
+ cik: z6.string().trim().min(1).optional(),
163
+ cninfoCode: z6.string().trim().min(1).optional(),
164
+ hkexStockCode: z6.string().trim().min(1).optional(),
165
+ cninfo: FinancialReportCninfoIdentifierSchema.optional(),
166
+ lei: z6.string().trim().min(1).optional(),
167
+ isin: z6.string().trim().min(1).optional()
168
+ }).default({});
169
+ function primaryFinancialReportMarket(listings) {
170
+ return listings.find((listing) => listing.primary)?.market ?? listings[0]?.market;
171
+ }
172
+ var FinancialReportIssuerPayloadSchema = z6.object({
173
+ issuerId: z6.string().trim().min(1),
174
+ companyId: z6.string().trim().min(1),
175
+ displayName: z6.string().trim().min(1),
176
+ legalName: z6.string().trim().min(1),
177
+ domicile: z6.string().trim().min(1).optional(),
178
+ listings: z6.array(FinancialReportListingSchema).min(1),
179
+ identifiers: FinancialReportIssuerIdentifiersSchema
180
+ }).superRefine((issuer, context) => {
181
+ const market = primaryFinancialReportMarket(issuer.listings);
182
+ if (market === "US" && !issuer.identifiers.cik) {
183
+ context.addIssue({
184
+ code: "custom",
185
+ path: ["identifiers", "cik"],
186
+ message: "US financial report issuers require SEC CIK"
187
+ });
188
+ }
189
+ if ((market === "A" || market === "H") && !issuer.identifiers.cninfo) {
190
+ context.addIssue({
191
+ code: "custom",
192
+ path: ["identifiers", "cninfo"],
193
+ message: "A/H financial report issuers require CNinfo identifiers"
194
+ });
195
+ }
196
+ });
197
+ var FinancialReportYearsSchema = z6.array(z6.number().int().min(1990).max(2100)).min(1);
198
+ var FinancialReportTypesPayloadSchema = z6.array(FinancialReportTypeSchema).min(1).optional();
199
+ var FinancialReportsSyncPayloadSchema = z6.object({
200
+ issuer: FinancialReportIssuerPayloadSchema,
201
+ fiscalYears: FinancialReportYearsSchema,
202
+ reportTypes: FinancialReportTypesPayloadSchema
203
+ });
204
+ var FinancialReportsIngestNotebookPayloadSchema = z6.object({
205
+ issuer: FinancialReportIssuerPayloadSchema,
206
+ manifestPath: z6.string().trim().min(1),
207
+ factsAsOf: z6.string().trim().min(1).optional(),
208
+ notebookTitle: z6.string().trim().min(1).optional()
209
+ });
210
+ var FinancialReportsExtractFactsPayloadSchema = FinancialReportsIngestNotebookPayloadSchema;
211
+ var FinancialReportsRefreshCompanyPayloadSchema = z6.object({
212
+ issuer: FinancialReportIssuerPayloadSchema,
213
+ fiscalYears: FinancialReportYearsSchema,
214
+ reportTypes: FinancialReportTypesPayloadSchema,
215
+ factsAsOf: z6.string().trim().min(1).optional(),
216
+ notebookTitle: z6.string().trim().min(1).optional()
217
+ });
218
+ var TaskSchema = z6.discriminatedUnion("type", [
219
+ z6.object({
220
+ id: z6.string().uuid(),
221
+ type: z6.literal("mock.write_company_report"),
222
+ payload: MockWriteCompanyReportPayloadSchema
223
+ }),
224
+ z6.object({
225
+ id: z6.string().uuid(),
226
+ type: z6.literal("workspace.scan"),
227
+ payload: WorkspaceScanPayloadSchema
228
+ }),
229
+ z6.object({
230
+ id: z6.string().uuid(),
231
+ type: z6.literal("invest_wiki.init_company_vault"),
232
+ payload: InvestWikiInitCompanyVaultPayloadSchema
233
+ }),
234
+ z6.object({
235
+ id: z6.string().uuid(),
236
+ type: z6.literal("invest_wiki.status"),
237
+ payload: InvestWikiStatusPayloadSchema
238
+ }),
239
+ z6.object({
240
+ id: z6.string().uuid(),
241
+ type: z6.literal("invest_wiki.sync"),
242
+ payload: InvestWikiSyncPayloadSchema
243
+ }),
244
+ z6.object({
245
+ id: z6.string().uuid(),
246
+ type: z6.literal("codex.run_invest_wiki_flow"),
247
+ payload: CodexRunInvestWikiFlowPayloadSchema
248
+ }),
249
+ z6.object({
250
+ id: z6.string().uuid(),
251
+ type: z6.literal("financial_reports.sync_reports"),
252
+ payload: FinancialReportsSyncPayloadSchema
253
+ }),
254
+ z6.object({
255
+ id: z6.string().uuid(),
256
+ type: z6.literal("financial_reports.ingest_notebook"),
257
+ payload: FinancialReportsIngestNotebookPayloadSchema
258
+ }),
259
+ z6.object({
260
+ id: z6.string().uuid(),
261
+ type: z6.literal("financial_reports.extract_facts"),
262
+ payload: FinancialReportsExtractFactsPayloadSchema
263
+ }),
264
+ z6.object({
265
+ id: z6.string().uuid(),
266
+ type: z6.literal("financial_reports.refresh_company"),
267
+ payload: FinancialReportsRefreshCompanyPayloadSchema
268
+ })
269
+ ]);
270
+ var TaskEventLevelSchema = z6.enum([
271
+ "debug",
272
+ "info",
273
+ "warn",
274
+ "error"
275
+ ]);
276
+ var TaskEventInputSchema = z6.object({
277
+ level: TaskEventLevelSchema.default("info"),
278
+ message: z6.string().min(1).max(2e3),
279
+ data: z6.record(z6.string(), z6.unknown()).default({})
280
+ });
281
+ var CoverageStateSchema = z7.enum(["complete", "incomplete", "unknown"]);
282
+ var CoverageBlockingReasonSchema = z7.object({
283
+ code: z7.string().trim().min(1),
284
+ message: z7.string().trim().min(1),
285
+ expectationId: z7.string().trim().min(1)
286
+ });
287
+ var CoverageSummarySchema = z7.object({
288
+ requiredTotal: z7.number().int().nonnegative().optional(),
289
+ requiredFound: z7.number().int().nonnegative().optional(),
290
+ requiredMissing: z7.number().int().nonnegative().optional(),
291
+ requiredFailed: z7.number().int().nonnegative().optional(),
292
+ optionalTotal: z7.number().int().nonnegative().optional()
293
+ });
294
+ var FinancialReportCoverageStatusSchema = z7.enum([
295
+ "complete",
296
+ "partial",
297
+ "incomplete"
298
+ ]);
299
+ var FinancialReportsTaskResultSchema = z7.object({
300
+ schemaVersion: z7.literal("financial-reports/task-result/v1"),
301
+ issuerId: z7.string().trim().min(1),
302
+ companyId: z7.string().trim().min(1),
303
+ ticker: z7.string().trim().min(1),
304
+ manifestPath: z7.string().trim().min(1).optional(),
305
+ manifestHash: z7.string().regex(/^sha256:[a-f0-9]{64}$/i).optional(),
306
+ notebookPath: z7.string().trim().min(1).optional(),
307
+ factsBundlePath: z7.string().trim().min(1).optional(),
308
+ wikiPath: z7.string().trim().min(1).optional(),
309
+ reportCount: z7.number().int().nonnegative().optional(),
310
+ coverageStatus: FinancialReportCoverageStatusSchema.optional(),
311
+ blockingReasons: z7.array(z7.string().trim().min(1)).default([])
312
+ });
313
+ var GitSnapshotSchema = z7.object({
314
+ status: z7.enum(["published", "unchanged"]),
315
+ commitSha: z7.string().optional(),
316
+ previousCommitSha: z7.string().optional(),
317
+ treeHash: z7.string(),
318
+ branch: z7.string(),
319
+ pushed: z7.boolean(),
320
+ remoteUrl: z7.string().optional(),
321
+ generatedAt: z7.string()
322
+ });
323
+ var TaskResultSchema = z7.object({
324
+ generatedFiles: z7.array(z7.string()).default([]),
325
+ manifestPath: z7.string().optional(),
326
+ manifest: CompanyManifestSchema.optional(),
327
+ commitSha: z7.string().optional(),
328
+ gitSnapshot: GitSnapshotSchema.optional(),
329
+ schemaVersion: z7.string().optional(),
330
+ runId: z7.string().optional(),
331
+ bundlePath: z7.string().optional(),
332
+ sourceInventoryPath: z7.string().optional(),
333
+ qualityReportPath: z7.string().optional(),
334
+ coverageState: CoverageStateSchema.optional(),
335
+ commercialReportAllowed: z7.boolean().optional(),
336
+ blockingReasons: z7.array(CoverageBlockingReasonSchema).default([]),
337
+ coverageSummary: CoverageSummarySchema.optional(),
338
+ financialReports: FinancialReportsTaskResultSchema.optional()
339
+ });
340
+ var AgentRuntimeSchema = z8.enum(["codex_cli"]);
341
+ var AgentStatusSchema = z8.enum(["ready", "disabled", "error"]);
342
+ var AgentReasoningEffortSchema = z8.enum([
343
+ "low",
344
+ "medium",
345
+ "high",
346
+ "xhigh"
347
+ ]);
348
+ var AgentAllowedTaskTypeSchema = z8.enum([
349
+ "invest_wiki.init_company_vault",
350
+ "invest_wiki.sync",
351
+ "codex.run_invest_wiki_flow",
352
+ "financial_reports.sync_reports",
353
+ "financial_reports.ingest_notebook",
354
+ "financial_reports.extract_facts",
355
+ "financial_reports.refresh_company"
356
+ ]);
357
+ var AgentConfigSchema = z8.object({
358
+ defaultSkill: z8.string().trim().min(1).default("invest-wiki-flow"),
359
+ workspaceRoot: z8.string().trim().min(1).default("~/dossierx"),
360
+ networkAccess: z8.boolean().default(true),
361
+ allowOutsideWorkspace: z8.boolean().default(false),
362
+ codexCommand: z8.string().trim().min(1).default("codex"),
363
+ codexVersion: z8.string().trim().min(1).optional(),
364
+ codexSandbox: z8.enum(["workspace-write", "danger-full-access"]).default("danger-full-access"),
365
+ allowedTaskTypes: z8.array(AgentAllowedTaskTypeSchema).default([
366
+ "invest_wiki.init_company_vault",
367
+ "invest_wiki.sync",
368
+ "codex.run_invest_wiki_flow"
369
+ ])
370
+ });
371
+ var CreateAgentRequestSchema = z8.object({
372
+ machineId: z8.string().uuid(),
373
+ name: z8.string().trim().min(1).max(120),
374
+ description: z8.string().trim().max(3e3).optional(),
375
+ runtime: AgentRuntimeSchema.default("codex_cli"),
376
+ model: z8.string().trim().min(1).max(80).default("gpt-5.5"),
377
+ reasoningEffort: AgentReasoningEffortSchema.default("medium"),
378
+ config: z8.unknown().optional().transform((value) => AgentConfigSchema.parse(value ?? {}))
379
+ });
380
+ var UpdateAgentRequestSchema = z8.object({
381
+ machineId: z8.string().uuid(),
382
+ name: z8.string().trim().min(1).max(120),
383
+ description: z8.string().trim().max(3e3).optional(),
384
+ model: z8.string().trim().min(1).max(80),
385
+ reasoningEffort: AgentReasoningEffortSchema,
386
+ config: z8.unknown().transform((value) => AgentConfigSchema.parse(value ?? {}))
387
+ });
388
+ var DaemonBootstrapRequestSchema = z9.object({
389
+ hostname: z9.string(),
390
+ os: z9.string(),
391
+ workspacePath: z9.string(),
392
+ daemonVersion: z9.string(),
393
+ capabilities: DaemonCapabilitiesSchema
394
+ });
395
+ var DaemonBootstrapResponseSchema = z9.object({
396
+ machineId: z9.string().uuid(),
397
+ workspaceId: z9.string().uuid(),
398
+ realtime: z9.object({
399
+ topic: MachineTopicSchema,
400
+ private: z9.boolean().default(false)
401
+ }),
402
+ polling: z9.object({
403
+ fallbackIntervalMs: z9.number().int().positive()
404
+ }),
405
+ limits: z9.object({
406
+ maxEventBatchSize: z9.number().int().positive(),
407
+ maxPayloadBytes: z9.number().int().positive()
408
+ })
409
+ });
410
+ var DaemonHeartbeatRequestSchema = z9.object({
411
+ machineId: z9.string().uuid(),
412
+ workspacePath: z9.string(),
413
+ status: MachineStatusSchema,
414
+ capabilities: DaemonCapabilitiesSchema,
415
+ currentTaskId: z9.string().uuid().optional()
416
+ });
417
+ var DaemonHeartbeatResponseSchema = z9.object({
418
+ ok: z9.boolean(),
419
+ nextHeartbeatMs: z9.number().int().positive()
420
+ });
421
+ var ClaimTaskRequestSchema = z9.object({
422
+ machineId: z9.string().uuid(),
423
+ maxTasks: z9.number().int().min(1).max(1).default(1)
424
+ });
425
+ var ClaimedTaskAgentSchema = z9.object({
426
+ id: z9.string().uuid(),
427
+ runtime: AgentRuntimeSchema,
428
+ model: z9.string().trim().min(1),
429
+ reasoningEffort: AgentReasoningEffortSchema,
430
+ config: AgentConfigSchema
431
+ });
432
+ var ClaimTaskResponseSchema = z9.object({
433
+ task: TaskSchema.nullable(),
434
+ agent: ClaimedTaskAgentSchema.nullable().default(null),
435
+ retryAfterMs: z9.number().int().positive()
436
+ });
437
+ var AppendTaskEventsRequestSchema = z9.object({
438
+ events: z9.array(TaskEventInputSchema).min(1).max(50)
439
+ });
440
+ var AppendTaskEventsResponseSchema = z9.object({
441
+ ok: z9.boolean()
442
+ });
443
+ var CompleteTaskRequestSchema = z9.object({
444
+ result: TaskResultSchema.prefault({})
445
+ });
446
+ var CompleteTaskResponseSchema = z9.object({
447
+ ok: z9.boolean()
448
+ });
449
+ var FailTaskRequestSchema = z9.object({
450
+ error: z9.object({
451
+ code: z9.string(),
452
+ message: z9.string(),
453
+ step: z9.string().optional(),
454
+ recoverable: z9.boolean().default(false)
455
+ })
456
+ });
457
+ var FailTaskResponseSchema = z9.object({
458
+ ok: z9.boolean()
459
+ });
460
+ var DaemonErrorCodeSchema = z10.enum([
461
+ "AUTH_FAILED",
462
+ "WORKSPACE_NOT_FOUND",
463
+ "WORKSPACE_ACCESS_DENIED",
464
+ "RUNTIME_NOT_FOUND",
465
+ "COMMAND_FAILED",
466
+ "TASK_CANCELLED",
467
+ "GIT_FAILED",
468
+ "GIT_PUSH_DENIED",
469
+ "NETWORK_ERROR",
470
+ "VALIDATION_ERROR",
471
+ "UNKNOWN"
472
+ ]);
473
+
474
+ // ../../node_modules/.pnpm/@xdsjs+dossierx-workspace@0.1.1/node_modules/@xdsjs/dossierx-workspace/dist/index.js
475
+ import { readFile as readFile2 } from "fs/promises";
476
+ import path3 from "path";
477
+ import { z as z11 } from "zod";
478
+ function resolveInsideWorkspace(root, relativePath) {
479
+ if (!path.isAbsolute(root)) {
480
+ throw new Error("Workspace root must be absolute");
481
+ }
482
+ if (path.isAbsolute(relativePath)) {
483
+ throw new Error("Path must be relative to workspace");
484
+ }
485
+ const resolvedRoot = path.resolve(root);
486
+ const resolvedTarget = path.resolve(root, relativePath);
487
+ if (resolvedTarget !== resolvedRoot && !resolvedTarget.startsWith(resolvedRoot + path.sep)) {
488
+ throw new Error("Path escapes workspace");
489
+ }
490
+ return resolvedTarget;
491
+ }
492
+ function sha256Text(content) {
493
+ return `sha256:${createHash("sha256").update(content).digest("hex")}`;
494
+ }
495
+ var DOSSIERX_CONFIG_DIR = "~/.dossierx";
496
+ var DOSSIERX_DEFAULT_WORKSPACE_PATH = "~/dossierx";
497
+ function normalizeTicker(ticker) {
498
+ return ticker.trim().toUpperCase();
499
+ }
500
+ function companyRoot(ticker) {
501
+ return `companies/${normalizeTicker(ticker)}`;
502
+ }
503
+ function companyManifestPath(ticker) {
504
+ return `${companyRoot(ticker)}/manifest.json`;
505
+ }
506
+ function rightRoot(ticker) {
507
+ return `${companyRoot(ticker)}/right`;
508
+ }
509
+ function rightBusinessPath(ticker) {
510
+ return `${rightRoot(ticker)}/right-business.md`;
511
+ }
512
+ function rightPeoplePath(ticker) {
513
+ return `${rightRoot(ticker)}/right-people.md`;
514
+ }
515
+ function rightPricePath(ticker) {
516
+ return `${rightRoot(ticker)}/right-price.md`;
517
+ }
518
+ function investWikiRoot(ticker) {
519
+ return companyRoot(ticker);
520
+ }
521
+ function investWikiConfigPath(ticker) {
522
+ return `${investWikiRoot(ticker)}/.llm-wiki-invest/config.toml`;
523
+ }
524
+ function wikiRoot(ticker) {
525
+ return `${companyRoot(ticker)}/wiki`;
526
+ }
527
+ function sourcesRoot(ticker) {
528
+ return `${companyRoot(ticker)}/sources`;
529
+ }
530
+ function articlesRoot(ticker) {
531
+ return `${companyRoot(ticker)}/articles`;
532
+ }
533
+ function financialReportsRoot(ticker) {
534
+ return `${companyRoot(ticker)}/financial-reports`;
535
+ }
536
+ function financialReportsIndexPath(ticker) {
537
+ return `${financialReportsRoot(ticker)}/report-index.json`;
538
+ }
539
+ var INVEST_WIKI_TOP_LEVEL_FILES = [
540
+ "AGENTS.md",
541
+ "CLAUDE.md",
542
+ "wiki-agent.md",
543
+ "wiki-log.md",
544
+ "wiki-purpose.md",
545
+ "wiki-schema.md"
546
+ ];
547
+ var MANIFEST_TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
548
+ ".md",
549
+ ".txt",
550
+ ".toml",
551
+ ".json",
552
+ ".yml",
553
+ ".yaml"
554
+ ]);
555
+ function manifestTitle(relativePath) {
556
+ return path2.basename(relativePath);
557
+ }
558
+ function canIncludeFile(relativePath) {
559
+ if (relativePath.endsWith("/manifest.json")) {
560
+ return false;
561
+ }
562
+ return MANIFEST_TEXT_EXTENSIONS.has(path2.extname(relativePath).toLowerCase());
563
+ }
564
+ async function collectDirectoryCandidates(input, depth = 0) {
565
+ const maxDepth = 3;
566
+ if (depth > maxDepth) {
567
+ return [];
568
+ }
569
+ const absoluteRoot = resolveInsideWorkspace(
570
+ input.workspaceRoot,
571
+ input.rootRelativePath
572
+ );
573
+ let entries;
574
+ try {
575
+ entries = await readdir(absoluteRoot, { withFileTypes: true });
576
+ } catch (error) {
577
+ if (error.code === "ENOENT") {
578
+ return [];
579
+ }
580
+ throw error;
581
+ }
582
+ const candidates = [];
583
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
584
+ if (entry.name.startsWith(".")) {
585
+ continue;
586
+ }
587
+ const relativePath = `${input.rootRelativePath}/${entry.name}`;
588
+ if (entry.isDirectory()) {
589
+ candidates.push(
590
+ ...await collectDirectoryCandidates(
591
+ {
592
+ workspaceRoot: input.workspaceRoot,
593
+ rootRelativePath: relativePath,
594
+ type: input.type
595
+ },
596
+ depth + 1
597
+ )
598
+ );
599
+ continue;
600
+ }
601
+ if (!entry.isFile() || !canIncludeFile(relativePath)) {
602
+ continue;
603
+ }
604
+ candidates.push({
605
+ type: input.type,
606
+ title: manifestTitle(relativePath),
607
+ relativePath
608
+ });
609
+ }
610
+ return candidates;
611
+ }
612
+ async function scanCompanyManifest(input) {
613
+ const ticker = normalizeTicker(input.ticker);
614
+ const staticCandidates = [
615
+ {
616
+ type: "right_business",
617
+ title: "Right Business",
618
+ relativePath: rightBusinessPath(ticker)
619
+ },
620
+ {
621
+ type: "right_people",
622
+ title: "Right People",
623
+ relativePath: rightPeoplePath(ticker)
624
+ },
625
+ {
626
+ type: "right_price",
627
+ title: "Right Price",
628
+ relativePath: rightPricePath(ticker)
629
+ },
630
+ {
631
+ type: "wiki",
632
+ title: "Invest Wiki Vault",
633
+ relativePath: investWikiConfigPath(ticker)
634
+ }
635
+ ];
636
+ const topLevelCandidates = INVEST_WIKI_TOP_LEVEL_FILES.map((fileName) => ({
637
+ type: "wiki",
638
+ title: fileName,
639
+ relativePath: `${companyRoot(ticker)}/${fileName}`
640
+ }));
641
+ const directoryCandidates = (await Promise.all([
642
+ collectDirectoryCandidates({
643
+ workspaceRoot: input.workspaceRoot,
644
+ rootRelativePath: wikiRoot(ticker),
645
+ type: "wiki"
646
+ }),
647
+ collectDirectoryCandidates({
648
+ workspaceRoot: input.workspaceRoot,
649
+ rootRelativePath: sourcesRoot(ticker),
650
+ type: "source_note"
651
+ }),
652
+ collectDirectoryCandidates({
653
+ workspaceRoot: input.workspaceRoot,
654
+ rootRelativePath: articlesRoot(ticker),
655
+ type: "article"
656
+ }),
657
+ collectDirectoryCandidates({
658
+ workspaceRoot: input.workspaceRoot,
659
+ rootRelativePath: financialReportsRoot(ticker),
660
+ type: "source_note"
661
+ })
662
+ ])).flat();
663
+ const candidates = [
664
+ ...staticCandidates,
665
+ ...topLevelCandidates,
666
+ ...directoryCandidates
667
+ ];
668
+ const pages = [];
669
+ const seenPaths = /* @__PURE__ */ new Set();
670
+ for (const candidate of candidates) {
671
+ if (seenPaths.has(candidate.relativePath)) {
672
+ continue;
673
+ }
674
+ seenPaths.add(candidate.relativePath);
675
+ const absolutePath = resolveInsideWorkspace(
676
+ input.workspaceRoot,
677
+ candidate.relativePath
678
+ );
679
+ try {
680
+ const [fileStat, content] = await Promise.all([
681
+ stat(absolutePath),
682
+ readFile(absolutePath, "utf8")
683
+ ]);
684
+ if (!fileStat.isFile()) {
685
+ continue;
686
+ }
687
+ pages.push({
688
+ type: candidate.type,
689
+ title: candidate.title,
690
+ path: candidate.relativePath,
691
+ size: Buffer.byteLength(content),
692
+ hash: sha256Text(content),
693
+ updatedAt: fileStat.mtime.toISOString()
694
+ });
695
+ } catch (error) {
696
+ if (error.code !== "ENOENT") {
697
+ throw error;
698
+ }
699
+ }
700
+ }
701
+ const parsed = CompanyManifestSchema.parse({
702
+ schemaVersion: 1,
703
+ ticker,
704
+ market: input.market,
705
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
706
+ commitSha: input.commitSha,
707
+ pages
708
+ });
709
+ return parsed;
710
+ }
711
+ async function buildCompanyManifest(input) {
712
+ const ticker = normalizeTicker(input.ticker);
713
+ const parsed = await scanCompanyManifest(input);
714
+ const manifestRelativePath = companyManifestPath(ticker);
715
+ const manifestAbsolutePath = resolveInsideWorkspace(
716
+ input.workspaceRoot,
717
+ manifestRelativePath
718
+ );
719
+ await mkdir(path2.dirname(manifestAbsolutePath), { recursive: true });
720
+ await writeFile(manifestAbsolutePath, `${JSON.stringify(parsed, null, 2)}
721
+ `);
722
+ return parsed;
723
+ }
724
+ var COVERAGE_CONTRACT_SCHEMA_VERSION = "coverage-contract/v0";
725
+ var CoveragePresetSchema = z11.object({
726
+ id: z11.string().min(1),
727
+ version: z11.string().min(1)
728
+ });
729
+ var CoverageCompanySchema = z11.object({
730
+ ticker: z11.string().min(1),
731
+ name: z11.string().min(1).optional(),
732
+ market: z11.enum(["us", "hk", "cn"]).optional()
733
+ });
734
+ var CoverageBundleSchema = z11.object({
735
+ schemaVersion: z11.string().min(1),
736
+ runId: z11.string().min(1),
737
+ completedAt: z11.string().min(1),
738
+ company: CoverageCompanySchema,
739
+ preset: CoveragePresetSchema,
740
+ files: z11.object({
741
+ manifest: z11.literal("manifest.json"),
742
+ sourceInventory: z11.literal("source_inventory.json"),
743
+ qualityReport: z11.literal("quality_report.json"),
744
+ result: z11.literal("result.json")
745
+ })
746
+ });
747
+ var CoverageBlockingReasonSchema2 = z11.object({
748
+ code: z11.enum([
749
+ "missing_required_source",
750
+ "failed_required_source",
751
+ "skipped_required_source",
752
+ "required_source_needs_review"
753
+ ]),
754
+ message: z11.string().min(1),
755
+ expectationId: z11.string().min(1)
756
+ });
757
+ var CoverageQualityReportSchema = z11.object({
758
+ schemaVersion: z11.string().min(1),
759
+ runId: z11.string().min(1),
760
+ preset: CoveragePresetSchema,
761
+ commercialReportAllowed: z11.boolean(),
762
+ summary: z11.object({
763
+ requiredTotal: z11.number().int().nonnegative(),
764
+ requiredFound: z11.number().int().nonnegative(),
765
+ requiredMissing: z11.number().int().nonnegative(),
766
+ requiredFailed: z11.number().int().nonnegative(),
767
+ optionalTotal: z11.number().int().nonnegative()
768
+ }),
769
+ blockingReasons: z11.array(CoverageBlockingReasonSchema2)
770
+ });
771
+ var CoverageSourceInventoryItemSchema = z11.object({
772
+ expectationId: z11.string().min(1),
773
+ label: z11.string().min(1),
774
+ required: z11.boolean(),
775
+ authority: z11.string().min(1),
776
+ documentType: z11.string().min(1),
777
+ asOf: z11.string().min(1),
778
+ period: z11.string().min(1),
779
+ selectionRule: z11.string().min(1),
780
+ status: z11.enum(["found", "missing", "failed", "skipped", "not_applicable"]),
781
+ manualSupplementAllowed: z11.boolean(),
782
+ sourceId: z11.string().optional(),
783
+ contentHash: z11.string().optional(),
784
+ materializedPath: z11.string().optional(),
785
+ sourceDate: z11.string().optional(),
786
+ filingDate: z11.string().optional(),
787
+ errorCode: z11.string().optional(),
788
+ reason: z11.string().optional(),
789
+ message: z11.string().optional()
790
+ }).superRefine((item, context) => {
791
+ if (item.status === "found") {
792
+ for (const field of ["sourceId", "contentHash", "materializedPath"]) {
793
+ if (!item[field]) {
794
+ context.addIssue({
795
+ code: "custom",
796
+ message: `found source inventory item requires ${field}`,
797
+ path: [field]
798
+ });
799
+ }
800
+ }
801
+ return;
802
+ }
803
+ if (!item.errorCode) {
804
+ context.addIssue({
805
+ code: "custom",
806
+ message: "non-found source inventory item requires errorCode",
807
+ path: ["errorCode"]
808
+ });
809
+ }
810
+ if (!item.reason && !item.message) {
811
+ context.addIssue({
812
+ code: "custom",
813
+ message: "non-found source inventory item requires reason or message",
814
+ path: ["reason"]
815
+ });
816
+ }
817
+ });
818
+ var CoverageSourceInventorySchema = z11.object({
819
+ schemaVersion: z11.string().min(1),
820
+ runId: z11.string().min(1),
821
+ preset: CoveragePresetSchema,
822
+ items: z11.array(CoverageSourceInventoryItemSchema)
823
+ });
824
+ async function readJsonFile(absolutePath) {
825
+ return JSON.parse(await readFile2(absolutePath, "utf8"));
826
+ }
827
+ function assertSupportedSchemaVersion(value, label) {
828
+ if (value !== COVERAGE_CONTRACT_SCHEMA_VERSION) {
829
+ throw new Error(
830
+ `Unsupported coverage contract schema version in ${label}: ${value}`
831
+ );
832
+ }
833
+ }
834
+ function parseBundle(value) {
835
+ try {
836
+ return CoverageBundleSchema.parse(value);
837
+ } catch (error) {
838
+ throw new Error(
839
+ `Invalid coverage bundle: ${error instanceof Error ? error.message : String(error)}`
840
+ );
841
+ }
842
+ }
843
+ function parseQualityReport(value) {
844
+ try {
845
+ return CoverageQualityReportSchema.parse(value);
846
+ } catch (error) {
847
+ throw new Error(
848
+ `Invalid quality_report.json: ${error instanceof Error ? error.message : String(error)}`
849
+ );
850
+ }
851
+ }
852
+ function parseSourceInventory(value) {
853
+ try {
854
+ return CoverageSourceInventorySchema.parse(value);
855
+ } catch (error) {
856
+ throw new Error(
857
+ `Invalid source_inventory.json: ${error instanceof Error ? error.message : String(error)}`
858
+ );
859
+ }
860
+ }
861
+ function relativeRunFile(bundlePath, fileName) {
862
+ return path3.posix.join(path3.posix.dirname(bundlePath), fileName);
863
+ }
864
+ async function readCoverageContractBundle(input) {
865
+ const bundleAbsolutePath = resolveInsideWorkspace(
866
+ input.workspaceRoot,
867
+ input.bundlePath
868
+ );
869
+ const bundle = parseBundle(await readJsonFile(bundleAbsolutePath));
870
+ assertSupportedSchemaVersion(bundle.schemaVersion, "bundle.json");
871
+ const qualityReportPath = relativeRunFile(
872
+ input.bundlePath,
873
+ bundle.files.qualityReport
874
+ );
875
+ const sourceInventoryPath = relativeRunFile(
876
+ input.bundlePath,
877
+ bundle.files.sourceInventory
878
+ );
879
+ const qualityReport = parseQualityReport(
880
+ await readJsonFile(
881
+ resolveInsideWorkspace(input.workspaceRoot, qualityReportPath)
882
+ )
883
+ );
884
+ const sourceInventory = parseSourceInventory(
885
+ await readJsonFile(
886
+ resolveInsideWorkspace(input.workspaceRoot, sourceInventoryPath)
887
+ )
888
+ );
889
+ assertSupportedSchemaVersion(
890
+ qualityReport.schemaVersion,
891
+ "quality_report.json"
892
+ );
893
+ assertSupportedSchemaVersion(
894
+ sourceInventory.schemaVersion,
895
+ "source_inventory.json"
896
+ );
897
+ return {
898
+ bundle,
899
+ qualityReport,
900
+ sourceInventory,
901
+ files: {
902
+ bundlePath: input.bundlePath,
903
+ qualityReportPath,
904
+ sourceInventoryPath
905
+ }
906
+ };
907
+ }
9
908
 
10
909
  // src/api/client.ts
11
- import {
12
- AppendTaskEventsRequestSchema,
13
- AppendTaskEventsResponseSchema,
14
- ClaimTaskResponseSchema,
15
- CompleteTaskRequestSchema,
16
- CompleteTaskResponseSchema,
17
- DaemonBootstrapRequestSchema,
18
- DaemonBootstrapResponseSchema,
19
- DaemonHeartbeatRequestSchema,
20
- DaemonHeartbeatResponseSchema,
21
- FailTaskRequestSchema,
22
- FailTaskResponseSchema
23
- } from "@xdsjs/dossierx-shared";
24
910
  var ApiClient = class {
25
911
  serverUrl;
26
912
  machineKey;
@@ -30,8 +916,8 @@ var ApiClient = class {
30
916
  this.machineKey = options.machineKey;
31
917
  this.fetchImpl = options.fetchImpl ?? fetch;
32
918
  }
33
- async post(path11, body, schema) {
34
- const response = await this.fetchImpl(`${this.serverUrl}${path11}`, {
919
+ async post(path15, body, schema) {
920
+ const response = await this.fetchImpl(`${this.serverUrl}${path15}`, {
35
921
  method: "POST",
36
922
  headers: {
37
923
  authorization: `Bearer ${this.machineKey}`,
@@ -496,61 +1382,476 @@ function createCodexRunnerFromOptions(options, env = process.env) {
496
1382
  }
497
1383
 
498
1384
  // src/git-mirror.ts
499
- import path2 from "path";
500
- import {
501
- publishCompanySnapshot
502
- } from "@xdsjs/dossierx-git-mirror";
1385
+ import path6 from "path";
1386
+
1387
+ // ../../node_modules/.pnpm/@xdsjs+dossierx-git-mirror@0.1.2/node_modules/@xdsjs/dossierx-git-mirror/dist/index.js
1388
+ import path32 from "path";
1389
+ import { mkdir as mkdir2, readdir as readdir2 } from "fs/promises";
1390
+ import path4 from "path";
1391
+ import { execa as execa2 } from "execa";
1392
+ import { lstat, mkdir as mkdir22, readFile as readFile3, rm, writeFile as writeFile2 } from "fs/promises";
1393
+ import path22 from "path";
1394
+ import { createHash as createHash2 } from "crypto";
1395
+ import { lstat as lstat2, readFile as readFile22 } from "fs/promises";
1396
+ var GitMirrorError = class extends Error {
1397
+ code;
1398
+ step;
1399
+ constructor(code, message, step) {
1400
+ super(message);
1401
+ this.name = "GitMirrorError";
1402
+ this.code = code;
1403
+ this.step = step;
1404
+ }
1405
+ };
1406
+ function validationError(message, step = "git_mirror.snapshot") {
1407
+ return new GitMirrorError("GIT_MIRROR_VALIDATION_ERROR", message, step);
1408
+ }
1409
+ function commandError(message, step = "git_mirror.git") {
1410
+ return new GitMirrorError("GIT_MIRROR_COMMAND_ERROR", message, step);
1411
+ }
1412
+ async function git(input, args) {
1413
+ const result = await execa2(input.gitCommand ?? "git", args, {
1414
+ cwd: input.cwd,
1415
+ reject: false
1416
+ });
1417
+ if (result.exitCode !== 0) {
1418
+ throw commandError(
1419
+ `git ${args.join(" ")} failed: ${result.stderr || result.stdout}`,
1420
+ "git_mirror.git"
1421
+ );
1422
+ }
1423
+ return result.stdout.trim();
1424
+ }
1425
+ async function pathExists(absolutePath) {
1426
+ try {
1427
+ await readdir2(absolutePath);
1428
+ return true;
1429
+ } catch (error) {
1430
+ if (error.code === "ENOENT") {
1431
+ return false;
1432
+ }
1433
+ throw error;
1434
+ }
1435
+ }
1436
+ async function isEmptyDirectory(absolutePath) {
1437
+ try {
1438
+ const entries = await readdir2(absolutePath);
1439
+ return entries.length === 0;
1440
+ } catch (error) {
1441
+ if (error.code === "ENOENT") {
1442
+ return true;
1443
+ }
1444
+ throw error;
1445
+ }
1446
+ }
1447
+ async function ensureGitRepository(input) {
1448
+ const gitDir = path4.join(input.mirrorRoot, ".git");
1449
+ if (!await pathExists(gitDir)) {
1450
+ if (input.remoteUrl) {
1451
+ await mkdir2(path4.dirname(input.mirrorRoot), { recursive: true });
1452
+ if (!await isEmptyDirectory(input.mirrorRoot)) {
1453
+ throw validationError(
1454
+ "Git mirror root must be empty when cloning a remote repository",
1455
+ "git_mirror.git.init"
1456
+ );
1457
+ }
1458
+ const result = await execa2(
1459
+ input.gitCommand ?? "git",
1460
+ ["clone", input.remoteUrl, input.mirrorRoot],
1461
+ { reject: false }
1462
+ );
1463
+ if (result.exitCode !== 0) {
1464
+ throw commandError(
1465
+ `git clone failed: ${result.stderr || result.stdout}`,
1466
+ "git_mirror.git.clone"
1467
+ );
1468
+ }
1469
+ await git({ cwd: input.mirrorRoot, gitCommand: input.gitCommand }, [
1470
+ "checkout",
1471
+ "-B",
1472
+ input.branch
1473
+ ]);
1474
+ } else {
1475
+ await mkdir2(input.mirrorRoot, { recursive: true });
1476
+ await git({ cwd: input.mirrorRoot, gitCommand: input.gitCommand }, ["init"]);
1477
+ await git({ cwd: input.mirrorRoot, gitCommand: input.gitCommand }, [
1478
+ "checkout",
1479
+ "-B",
1480
+ input.branch
1481
+ ]);
1482
+ }
1483
+ } else {
1484
+ await git({ cwd: input.mirrorRoot, gitCommand: input.gitCommand }, [
1485
+ "checkout",
1486
+ "-B",
1487
+ input.branch
1488
+ ]);
1489
+ }
1490
+ await git({ cwd: input.mirrorRoot, gitCommand: input.gitCommand }, [
1491
+ "config",
1492
+ "user.name",
1493
+ input.authorName
1494
+ ]);
1495
+ await git({ cwd: input.mirrorRoot, gitCommand: input.gitCommand }, [
1496
+ "config",
1497
+ "user.email",
1498
+ input.authorEmail
1499
+ ]);
1500
+ if (input.remoteUrl) {
1501
+ const currentRemote = await execa2(
1502
+ input.gitCommand ?? "git",
1503
+ ["remote", "get-url", "origin"],
1504
+ { cwd: input.mirrorRoot, reject: false }
1505
+ );
1506
+ if (currentRemote.exitCode === 0) {
1507
+ if (currentRemote.stdout.trim() !== input.remoteUrl) {
1508
+ await git({ cwd: input.mirrorRoot, gitCommand: input.gitCommand }, [
1509
+ "remote",
1510
+ "set-url",
1511
+ "origin",
1512
+ input.remoteUrl
1513
+ ]);
1514
+ }
1515
+ } else {
1516
+ await git({ cwd: input.mirrorRoot, gitCommand: input.gitCommand }, [
1517
+ "remote",
1518
+ "add",
1519
+ "origin",
1520
+ input.remoteUrl
1521
+ ]);
1522
+ }
1523
+ }
1524
+ }
1525
+ async function gitRevParseHead(input) {
1526
+ const result = await execa2(input.gitCommand ?? "git", ["rev-parse", "HEAD"], {
1527
+ cwd: input.cwd,
1528
+ reject: false
1529
+ });
1530
+ return result.exitCode === 0 ? result.stdout.trim() : void 0;
1531
+ }
1532
+ async function stageCompany(input) {
1533
+ await git(input, ["add", "--", input.companyRoot]);
1534
+ }
1535
+ async function stagedPaths(input) {
1536
+ const output = await git(input, ["diff", "--cached", "--name-only"]);
1537
+ return output ? output.split("\n").filter(Boolean) : [];
1538
+ }
1539
+ async function commit(input) {
1540
+ await git(input, ["commit", "-m", input.message]);
1541
+ }
1542
+ async function push(input) {
1543
+ await git(input, ["push", "-u", "origin", input.branch]);
1544
+ }
1545
+ function sha256Text2(content) {
1546
+ return `sha256:${createHash2("sha256").update(content).digest("hex")}`;
1547
+ }
1548
+ function treeHashForManifest(manifest) {
1549
+ const lines = manifest.pages.map((page) => `${page.path}\0${page.hash}\0${page.size}`).sort((a, b) => a.localeCompare(b));
1550
+ return sha256Text2(`${lines.join("\n")}
1551
+ `);
1552
+ }
1553
+ function snapshotMetadataPath(ticker) {
1554
+ return `${companyRoot(ticker)}/.dossierx/snapshot.json`;
1555
+ }
1556
+ async function buildCompanySnapshot(input) {
1557
+ const ticker = normalizeTicker(input.company.ticker);
1558
+ const manifest = await buildCompanyManifest({
1559
+ workspaceRoot: input.workspaceRoot,
1560
+ ticker,
1561
+ market: input.company.market
1562
+ });
1563
+ const manifestPath = companyManifestPath(ticker);
1564
+ const files = [];
1565
+ for (const page of manifest.pages) {
1566
+ const absolutePath = resolveInsideWorkspace(input.workspaceRoot, page.path);
1567
+ const fileStat = await lstat(absolutePath);
1568
+ if (fileStat.isSymbolicLink()) {
1569
+ throw validationError(`Manifest page cannot be a symlink: ${page.path}`);
1570
+ }
1571
+ if (!fileStat.isFile()) {
1572
+ throw validationError(`Manifest page is not a regular file: ${page.path}`);
1573
+ }
1574
+ files.push({
1575
+ relativePath: page.path,
1576
+ hash: page.hash,
1577
+ size: page.size
1578
+ });
1579
+ }
1580
+ return {
1581
+ manifest,
1582
+ manifestPath,
1583
+ treeHash: treeHashForManifest(manifest),
1584
+ files
1585
+ };
1586
+ }
1587
+ async function copyTextFile(input) {
1588
+ const from = resolveInsideWorkspace(input.fromRoot, input.relativePath);
1589
+ const to = resolveInsideWorkspace(input.toRoot, input.relativePath);
1590
+ const fileStat = await lstat(from);
1591
+ if (fileStat.isSymbolicLink()) {
1592
+ throw validationError(`Snapshot file cannot be a symlink: ${input.relativePath}`);
1593
+ }
1594
+ if (!fileStat.isFile()) {
1595
+ throw validationError(`Snapshot file is not a regular file: ${input.relativePath}`);
1596
+ }
1597
+ await mkdir22(path22.dirname(to), { recursive: true });
1598
+ await writeFile2(to, await readFile3(from));
1599
+ }
1600
+ async function copyCompanySnapshot(input) {
1601
+ const companyRelativeRoot = companyRoot(input.snapshot.manifest.ticker);
1602
+ await rm(resolveInsideWorkspace(input.mirrorRoot, companyRelativeRoot), {
1603
+ recursive: true,
1604
+ force: true
1605
+ });
1606
+ for (const file of input.snapshot.files) {
1607
+ await copyTextFile({
1608
+ fromRoot: input.workspaceRoot,
1609
+ toRoot: input.mirrorRoot,
1610
+ relativePath: file.relativePath
1611
+ });
1612
+ }
1613
+ await copyTextFile({
1614
+ fromRoot: input.workspaceRoot,
1615
+ toRoot: input.mirrorRoot,
1616
+ relativePath: input.snapshot.manifestPath
1617
+ });
1618
+ const metadataAbsolutePath = resolveInsideWorkspace(
1619
+ input.mirrorRoot,
1620
+ snapshotMetadataPath(input.snapshot.manifest.ticker)
1621
+ );
1622
+ await mkdir22(path22.dirname(metadataAbsolutePath), { recursive: true });
1623
+ await writeFile2(
1624
+ metadataAbsolutePath,
1625
+ `${JSON.stringify(input.metadata, null, 2)}
1626
+ `
1627
+ );
1628
+ }
1629
+ async function readSnapshotMetadata(input) {
1630
+ try {
1631
+ const metadata = JSON.parse(
1632
+ await readFile3(
1633
+ resolveInsideWorkspace(
1634
+ input.mirrorRoot,
1635
+ snapshotMetadataPath(input.ticker)
1636
+ ),
1637
+ "utf8"
1638
+ )
1639
+ );
1640
+ return metadata.schemaVersion === 1 ? metadata : null;
1641
+ } catch (error) {
1642
+ if (error.code === "ENOENT") {
1643
+ return null;
1644
+ }
1645
+ throw error;
1646
+ }
1647
+ }
1648
+ async function verifyCompanySnapshot(input) {
1649
+ const ticker = normalizeTicker(input.company.ticker);
1650
+ const manifestPath = companyManifestPath(ticker);
1651
+ const manifest = CompanyManifestSchema.parse(
1652
+ JSON.parse(
1653
+ await readFile22(resolveInsideWorkspace(input.mirrorRoot, manifestPath), "utf8")
1654
+ )
1655
+ );
1656
+ if (manifest.ticker !== ticker || manifest.market !== input.company.market) {
1657
+ throw validationError("Mirror manifest company identity does not match");
1658
+ }
1659
+ for (const page of manifest.pages) {
1660
+ const absolutePath = resolveInsideWorkspace(input.mirrorRoot, page.path);
1661
+ const fileStat = await lstat2(absolutePath);
1662
+ if (fileStat.isSymbolicLink()) {
1663
+ throw validationError(`Mirror page cannot be a symlink: ${page.path}`);
1664
+ }
1665
+ if (!fileStat.isFile()) {
1666
+ throw validationError(`Mirror page is not a regular file: ${page.path}`);
1667
+ }
1668
+ const content = await readFile22(absolutePath, "utf8");
1669
+ const size = Buffer.byteLength(content);
1670
+ const hash = sha256Text2(content);
1671
+ if (size !== page.size || hash !== page.hash) {
1672
+ throw validationError(`Mirror page hash mismatch: ${page.path}`);
1673
+ }
1674
+ }
1675
+ const treeHash = treeHashForManifest(manifest);
1676
+ if (input.expectedTreeHash && treeHash !== input.expectedTreeHash) {
1677
+ throw validationError("Mirror tree hash does not match expected tree hash");
1678
+ }
1679
+ return { ok: true, manifest, treeHash };
1680
+ }
1681
+ async function publishCompanySnapshot(input) {
1682
+ const ticker = normalizeTicker(input.company.ticker);
1683
+ const branch = input.branch ?? "main";
1684
+ const mirrorRoot = path32.resolve(input.mirrorRoot);
1685
+ const workspaceRoot = path32.resolve(input.workspaceRoot);
1686
+ const authorName = input.authorName ?? "DossierX daemon";
1687
+ const authorEmail = input.authorEmail ?? "dossierx@local";
1688
+ const gitOptions = { cwd: mirrorRoot, gitCommand: input.gitCommand };
1689
+ const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
1690
+ await ensureGitRepository({
1691
+ mirrorRoot,
1692
+ remoteUrl: input.remoteUrl,
1693
+ branch,
1694
+ gitCommand: input.gitCommand,
1695
+ authorName,
1696
+ authorEmail
1697
+ });
1698
+ const previousCommitSha = await gitRevParseHead(gitOptions);
1699
+ const snapshot = await buildCompanySnapshot({
1700
+ workspaceRoot,
1701
+ company: { ticker, market: input.company.market }
1702
+ });
1703
+ const existingMetadata = await readSnapshotMetadata({ mirrorRoot, ticker });
1704
+ if (existingMetadata?.treeHash === snapshot.treeHash) {
1705
+ try {
1706
+ await verifyCompanySnapshot({
1707
+ mirrorRoot,
1708
+ company: { ticker, market: input.company.market },
1709
+ expectedTreeHash: snapshot.treeHash
1710
+ });
1711
+ return {
1712
+ status: "unchanged",
1713
+ ticker,
1714
+ market: input.company.market,
1715
+ manifestPath: snapshot.manifestPath,
1716
+ commitSha: previousCommitSha,
1717
+ previousCommitSha,
1718
+ treeHash: snapshot.treeHash,
1719
+ branch,
1720
+ pushed: false,
1721
+ remoteUrl: input.remoteUrl,
1722
+ generatedAt
1723
+ };
1724
+ } catch {
1725
+ }
1726
+ }
1727
+ const metadata = {
1728
+ schemaVersion: 1,
1729
+ ticker,
1730
+ market: input.company.market,
1731
+ taskId: input.taskId,
1732
+ treeHash: snapshot.treeHash,
1733
+ generatedAt
1734
+ };
1735
+ await copyCompanySnapshot({
1736
+ workspaceRoot,
1737
+ mirrorRoot,
1738
+ snapshot,
1739
+ metadata
1740
+ });
1741
+ await verifyCompanySnapshot({
1742
+ mirrorRoot,
1743
+ company: { ticker, market: input.company.market },
1744
+ expectedTreeHash: snapshot.treeHash
1745
+ });
1746
+ const companyRelativeRoot = companyRoot(ticker);
1747
+ await stageCompany({ ...gitOptions, companyRoot: companyRelativeRoot });
1748
+ const staged = await stagedPaths(gitOptions);
1749
+ const invalidStagedPath = staged.find(
1750
+ (relativePath) => !relativePath.startsWith(`${companyRelativeRoot}/`)
1751
+ );
1752
+ if (invalidStagedPath) {
1753
+ throw validationError(
1754
+ `Git mirror staged a file outside ${companyRelativeRoot}: ${invalidStagedPath}`,
1755
+ "git_mirror.git.stage"
1756
+ );
1757
+ }
1758
+ if (staged.length === 0) {
1759
+ return {
1760
+ status: "unchanged",
1761
+ ticker,
1762
+ market: input.company.market,
1763
+ manifestPath: snapshot.manifestPath,
1764
+ commitSha: previousCommitSha,
1765
+ previousCommitSha,
1766
+ treeHash: snapshot.treeHash,
1767
+ branch,
1768
+ pushed: false,
1769
+ remoteUrl: input.remoteUrl,
1770
+ generatedAt
1771
+ };
1772
+ }
1773
+ await commit({
1774
+ ...gitOptions,
1775
+ message: `Mirror ${ticker} workspace snapshot`
1776
+ });
1777
+ const commitSha = await gitRevParseHead(gitOptions);
1778
+ const shouldPush = input.push ?? Boolean(input.remoteUrl);
1779
+ if (shouldPush && !input.remoteUrl) {
1780
+ throw validationError(
1781
+ "Git mirror push requires a remote URL",
1782
+ "git_mirror.git.push"
1783
+ );
1784
+ }
1785
+ if (shouldPush) {
1786
+ await push({ ...gitOptions, branch });
1787
+ }
1788
+ return {
1789
+ status: "published",
1790
+ ticker,
1791
+ market: input.company.market,
1792
+ manifestPath: snapshot.manifestPath,
1793
+ commitSha,
1794
+ previousCommitSha,
1795
+ treeHash: snapshot.treeHash,
1796
+ branch,
1797
+ pushed: shouldPush,
1798
+ remoteUrl: input.remoteUrl,
1799
+ generatedAt
1800
+ };
1801
+ }
1802
+ var GITHUB_APP_TOKEN_TTL_SECONDS = 9 * 60;
1803
+ var GITHUB_APP_TOKEN_CACHE_MS = 50 * 60 * 1e3;
1804
+ var GITHUB_MANIFEST_CACHE_MS = 60 * 1e3;
503
1805
 
504
1806
  // src/local-config.ts
505
- import { chmod, mkdir, readFile, writeFile } from "fs/promises";
1807
+ import { chmod, mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
506
1808
  import os from "os";
507
- import path from "path";
508
- import { z } from "zod";
509
- import { DOSSIERX_CONFIG_DIR } from "@xdsjs/dossierx-workspace";
510
- var DaemonLocalConfigSchema = z.object({
511
- machineId: z.string().uuid().optional(),
512
- machineKey: z.string().startsWith("dx_machine_"),
513
- serverUrl: z.string().min(1),
514
- supabaseUrl: z.string().min(1),
515
- supabaseAnonKey: z.string().min(1),
516
- workspacePath: z.string().min(1),
517
- investWikiMode: z.string().optional(),
518
- investWikiLocalRepo: z.string().optional(),
519
- investWikiCommand: z.string().optional(),
520
- codexCommand: z.string().optional(),
521
- codexModel: z.string().optional(),
522
- codexSandbox: z.string().optional(),
523
- gitMirrorRoot: z.string().optional(),
524
- gitMirrorRemote: z.string().optional(),
525
- gitMirrorBranch: z.string().optional(),
526
- gitCommand: z.string().optional(),
527
- notebookLmPythonCommand: z.string().optional(),
528
- notebookLmProfile: z.string().optional(),
529
- notebookLmHome: z.string().optional(),
530
- notebookLmStoragePath: z.string().optional(),
531
- localApiPort: z.number().int().positive().optional()
1809
+ import path5 from "path";
1810
+ import { z as z12 } from "zod";
1811
+ var DaemonLocalConfigSchema = z12.object({
1812
+ machineId: z12.string().uuid().optional(),
1813
+ machineKey: z12.string().startsWith("dx_machine_"),
1814
+ serverUrl: z12.string().min(1),
1815
+ supabaseUrl: z12.string().min(1),
1816
+ supabaseAnonKey: z12.string().min(1),
1817
+ workspacePath: z12.string().min(1),
1818
+ investWikiMode: z12.string().optional(),
1819
+ investWikiLocalRepo: z12.string().optional(),
1820
+ investWikiCommand: z12.string().optional(),
1821
+ codexCommand: z12.string().optional(),
1822
+ codexModel: z12.string().optional(),
1823
+ codexSandbox: z12.string().optional(),
1824
+ gitMirrorRoot: z12.string().optional(),
1825
+ gitMirrorRemote: z12.string().optional(),
1826
+ gitMirrorBranch: z12.string().optional(),
1827
+ gitCommand: z12.string().optional(),
1828
+ notebookLmPythonCommand: z12.string().optional(),
1829
+ notebookLmProfile: z12.string().optional(),
1830
+ notebookLmHome: z12.string().optional(),
1831
+ notebookLmStoragePath: z12.string().optional(),
1832
+ localApiPort: z12.number().int().positive().optional()
532
1833
  });
533
1834
  function expandHomePath(input) {
534
1835
  if (input === "~") {
535
1836
  return os.homedir();
536
1837
  }
537
1838
  if (input.startsWith("~/")) {
538
- return path.join(os.homedir(), input.slice(2));
1839
+ return path5.join(os.homedir(), input.slice(2));
539
1840
  }
540
1841
  return input;
541
1842
  }
542
1843
  function getDaemonConfigDir(env = process.env) {
543
- return path.resolve(
1844
+ return path5.resolve(
544
1845
  expandHomePath(env.DOSSIERX_CONFIG_DIR ?? DOSSIERX_CONFIG_DIR)
545
1846
  );
546
1847
  }
547
1848
  function daemonConfigPath(configDir = getDaemonConfigDir()) {
548
- return path.join(configDir, "config.json");
1849
+ return path5.join(configDir, "config.json");
549
1850
  }
550
1851
  async function readDaemonLocalConfig(configDir = getDaemonConfigDir()) {
551
1852
  try {
552
1853
  return DaemonLocalConfigSchema.parse(
553
- JSON.parse(await readFile(daemonConfigPath(configDir), "utf8"))
1854
+ JSON.parse(await readFile4(daemonConfigPath(configDir), "utf8"))
554
1855
  );
555
1856
  } catch (error) {
556
1857
  if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
@@ -561,9 +1862,9 @@ async function readDaemonLocalConfig(configDir = getDaemonConfigDir()) {
561
1862
  }
562
1863
  async function writeDaemonLocalConfig(config, configDir = getDaemonConfigDir()) {
563
1864
  const parsed = DaemonLocalConfigSchema.parse(config);
564
- await mkdir(configDir, { recursive: true, mode: 448 });
1865
+ await mkdir3(configDir, { recursive: true, mode: 448 });
565
1866
  const target = daemonConfigPath(configDir);
566
- await writeFile(target, `${JSON.stringify(parsed, null, 2)}
1867
+ await writeFile3(target, `${JSON.stringify(parsed, null, 2)}
567
1868
  `, {
568
1869
  mode: 384
569
1870
  });
@@ -575,9 +1876,9 @@ function createGitMirrorFromOptions(options) {
575
1876
  if (!options.gitMirrorRoot && !options.gitMirrorRemote) {
576
1877
  return null;
577
1878
  }
578
- const mirrorRoot = path2.resolve(
1879
+ const mirrorRoot = path6.resolve(
579
1880
  expandHomePath(
580
- options.gitMirrorRoot ?? path2.join(getDaemonConfigDir(), "git-mirror")
1881
+ options.gitMirrorRoot ?? path6.join(getDaemonConfigDir(), "git-mirror")
581
1882
  )
582
1883
  );
583
1884
  return {
@@ -595,8 +1896,8 @@ function createGitMirrorFromOptions(options) {
595
1896
 
596
1897
  // src/invest-wiki/runner.ts
597
1898
  import { access } from "fs/promises";
598
- import path3 from "path";
599
- import { execa as execa2 } from "execa";
1899
+ import path7 from "path";
1900
+ import { execa as execa3 } from "execa";
600
1901
 
601
1902
  // src/invest-wiki/config.ts
602
1903
  function resolveInvestWikiConfig(options, env = process.env) {
@@ -676,7 +1977,7 @@ function commandFailureMessage2(error) {
676
1977
  }
677
1978
  async function runInvestWikiCommand(command, args, options) {
678
1979
  try {
679
- return await execa2(command, args, options);
1980
+ return await execa3(command, args, options);
680
1981
  } catch (error) {
681
1982
  throw new InvestWikiRuntimeError(
682
1983
  "COMMAND_FAILED",
@@ -689,7 +1990,7 @@ function createLocalRepoRunner(config) {
689
1990
  return {
690
1991
  kind: "local-repo",
691
1992
  async run(args, options) {
692
- const cliPath = path3.join(config.localRepo, "dist", "cli.js");
1993
+ const cliPath = path7.join(config.localRepo, "dist", "cli.js");
693
1994
  await assertFileExists(cliPath);
694
1995
  const result = await runInvestWikiCommand(
695
1996
  process.execPath,
@@ -737,8 +2038,7 @@ function createInvestWikiRunnerFromOptions(options, env = process.env) {
737
2038
  }
738
2039
 
739
2040
  // src/notebooklm/pythonClient.ts
740
- import { execa as execa3 } from "execa";
741
- import { resolveInsideWorkspace } from "@xdsjs/dossierx-workspace";
2041
+ import { execa as execa4 } from "execa";
742
2042
  var DEFAULT_PYTHON_COMMAND = "python3";
743
2043
  var DEFAULT_TIMEOUT_MS = 15 * 60 * 1e3;
744
2044
  var DEFAULT_SOURCE_WAIT_TIMEOUT_SECONDS = 10 * 60;
@@ -858,7 +2158,7 @@ async function runBridge(options, action, input) {
858
2158
  if (options.home) {
859
2159
  env.NOTEBOOKLM_HOME = options.home;
860
2160
  }
861
- const result = await execa3(
2161
+ const result = await execa4(
862
2162
  options.pythonCommand ?? DEFAULT_PYTHON_COMMAND,
863
2163
  ["-c", NOTEBOOKLM_PY_BRIDGE],
864
2164
  {
@@ -910,20 +2210,14 @@ function createNotebookLmPythonClient(options) {
910
2210
 
911
2211
  // src/local-api/server.ts
912
2212
  import { createServer } from "http";
913
- import { readFile as readFile3, realpath, stat } from "fs/promises";
914
- import path5 from "path";
915
- import { execa as execa4 } from "execa";
916
- import {
917
- readCoverageContractBundle,
918
- resolveInsideWorkspace as resolveInsideWorkspace3,
919
- scanCompanyManifest
920
- } from "@xdsjs/dossierx-workspace";
2213
+ import { readFile as readFile6, realpath, stat as stat2 } from "fs/promises";
2214
+ import path9 from "path";
2215
+ import { execa as execa5 } from "execa";
921
2216
 
922
2217
  // src/task-archive.ts
923
2218
  import { randomUUID } from "crypto";
924
- import { appendFile, mkdir as mkdir2, readFile as readFile2 } from "fs/promises";
925
- import path4 from "path";
926
- import { resolveInsideWorkspace as resolveInsideWorkspace2 } from "@xdsjs/dossierx-workspace";
2219
+ import { appendFile, mkdir as mkdir4, readFile as readFile5 } from "fs/promises";
2220
+ import path8 from "path";
927
2221
  var TASK_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
928
2222
  function assertTaskId(taskId) {
929
2223
  if (!TASK_ID_PATTERN.test(taskId)) {
@@ -932,14 +2226,14 @@ function assertTaskId(taskId) {
932
2226
  }
933
2227
  function taskDirectory(workspaceRoot, taskId) {
934
2228
  assertTaskId(taskId);
935
- return resolveInsideWorkspace2(
2229
+ return resolveInsideWorkspace(
936
2230
  workspaceRoot,
937
- path4.posix.join(".dossierx", "tasks", taskId)
2231
+ path8.posix.join(".dossierx", "tasks", taskId)
938
2232
  );
939
2233
  }
940
2234
  async function ensureTaskDirectory(workspaceRoot, taskId) {
941
2235
  const directory = taskDirectory(workspaceRoot, taskId);
942
- await mkdir2(directory, { recursive: true });
2236
+ await mkdir4(directory, { recursive: true });
943
2237
  return directory;
944
2238
  }
945
2239
  function parseEventLine(line) {
@@ -967,7 +2261,7 @@ function createTaskArchive(options) {
967
2261
  created_at: now().toISOString()
968
2262
  };
969
2263
  await appendFile(
970
- path4.join(directory, "events.jsonl"),
2264
+ path8.join(directory, "events.jsonl"),
971
2265
  `${JSON.stringify(archivedEvent)}
972
2266
  `,
973
2267
  "utf8"
@@ -976,13 +2270,13 @@ function createTaskArchive(options) {
976
2270
  },
977
2271
  async appendRawOutput(taskId, stream, chunk) {
978
2272
  const directory = await ensureTaskDirectory(options.workspaceRoot, taskId);
979
- await appendFile(path4.join(directory, `${stream}.log`), chunk, "utf8");
2273
+ await appendFile(path8.join(directory, `${stream}.log`), chunk, "utf8");
980
2274
  },
981
2275
  async listEvents(taskId) {
982
2276
  const directory = taskDirectory(options.workspaceRoot, taskId);
983
2277
  let content = "";
984
2278
  try {
985
- content = await readFile2(path4.join(directory, "events.jsonl"), "utf8");
2279
+ content = await readFile5(path8.join(directory, "events.jsonl"), "utf8");
986
2280
  } catch (error) {
987
2281
  if (error.code === "ENOENT") {
988
2282
  return [];
@@ -996,7 +2290,7 @@ function createTaskArchive(options) {
996
2290
 
997
2291
  // src/version.ts
998
2292
  var DAEMON_PACKAGE_NAME = "@xdsjs/dossierx-daemon";
999
- var DAEMON_VERSION = "0.1.13";
2293
+ var DAEMON_VERSION = "0.1.15";
1000
2294
 
1001
2295
  // src/local-api/server.ts
1002
2296
  var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
@@ -1023,15 +2317,15 @@ function requestUrl(request) {
1023
2317
  return new URL(request.url ?? "/", "http://127.0.0.1");
1024
2318
  }
1025
2319
  async function readWorkspaceFile(options) {
1026
- const extension = path5.extname(options.relativePath).toLowerCase();
2320
+ const extension = path9.extname(options.relativePath).toLowerCase();
1027
2321
  if (!ALLOWED_EXTENSIONS.has(extension)) {
1028
2322
  throw new Error("Only markdown, text, and json files can be previewed");
1029
2323
  }
1030
- const absolutePath = resolveInsideWorkspace3(
2324
+ const absolutePath = resolveInsideWorkspace(
1031
2325
  options.workspaceRoot,
1032
2326
  options.relativePath
1033
2327
  );
1034
- const stats = await stat(absolutePath);
2328
+ const stats = await stat2(absolutePath);
1035
2329
  if (!stats.isFile()) {
1036
2330
  throw new Error("Path is not a file");
1037
2331
  }
@@ -1040,7 +2334,7 @@ async function readWorkspaceFile(options) {
1040
2334
  }
1041
2335
  return {
1042
2336
  path: options.relativePath,
1043
- content: await readFile3(absolutePath, "utf8"),
2337
+ content: await readFile6(absolutePath, "utf8"),
1044
2338
  size: stats.size,
1045
2339
  updatedAt: stats.mtime.toISOString()
1046
2340
  };
@@ -1075,10 +2369,10 @@ function uniqueProbes(probes) {
1075
2369
  }
1076
2370
  async function resolveCommand(command) {
1077
2371
  const normalizedCommand = command.trim();
1078
- if (path5.isAbsolute(normalizedCommand)) {
2372
+ if (path9.isAbsolute(normalizedCommand)) {
1079
2373
  return realpath(normalizedCommand).catch(() => normalizedCommand);
1080
2374
  }
1081
- const result = await execa4("which", [normalizedCommand], {
2375
+ const result = await execa5("which", [normalizedCommand], {
1082
2376
  stdin: "ignore",
1083
2377
  reject: false,
1084
2378
  timeout: 3e3
@@ -1095,7 +2389,7 @@ async function detectCodexCommand(probe) {
1095
2389
  return null;
1096
2390
  }
1097
2391
  try {
1098
- const result = await execa4(command, ["--version"], {
2392
+ const result = await execa5(command, ["--version"], {
1099
2393
  stdin: "ignore",
1100
2394
  timeout: 5e3,
1101
2395
  reject: false
@@ -1192,7 +2486,7 @@ function isNewerVersion(candidate, current) {
1192
2486
  return false;
1193
2487
  }
1194
2488
  async function defaultLatestDaemonVersion(packageName) {
1195
- const result = await execa4("npm", ["view", packageName, "version"], {
2489
+ const result = await execa5("npm", ["view", packageName, "version"], {
1196
2490
  stdin: "ignore",
1197
2491
  timeout: 8e3,
1198
2492
  reject: false
@@ -1204,11 +2498,11 @@ async function defaultLatestDaemonVersion(packageName) {
1204
2498
  }
1205
2499
  async function defaultUpdateDaemonPackage(input) {
1206
2500
  const customCommand = process.env.DOSSIERX_DAEMON_UPDATE_COMMAND?.trim();
1207
- const result = customCommand ? await execa4("/bin/zsh", ["-lc", customCommand], {
2501
+ const result = customCommand ? await execa5("/bin/zsh", ["-lc", customCommand], {
1208
2502
  stdin: "ignore",
1209
2503
  timeout: 12e4,
1210
2504
  reject: false
1211
- }) : await execa4("npm", ["install", "-g", `${input.packageName}@latest`], {
2505
+ }) : await execa5("npm", ["install", "-g", `${input.packageName}@latest`], {
1212
2506
  stdin: "ignore",
1213
2507
  timeout: 12e4,
1214
2508
  reject: false
@@ -1446,12 +2740,7 @@ async function startWorkspaceReadServer(options) {
1446
2740
  }
1447
2741
 
1448
2742
  // src/loop.ts
1449
- import { z as z2 } from "zod";
1450
- import {
1451
- TaskEventInputSchema,
1452
- TaskSchema
1453
- } from "@xdsjs/dossierx-shared";
1454
- import { GitMirrorError } from "@xdsjs/dossierx-git-mirror";
2743
+ import { z as z13 } from "zod";
1455
2744
 
1456
2745
  // src/errors.ts
1457
2746
  function failTaskError(error, code = "UNKNOWN", step) {
@@ -1466,13 +2755,7 @@ function failTaskError(error, code = "UNKNOWN", step) {
1466
2755
  }
1467
2756
 
1468
2757
  // src/executors/codex.ts
1469
- import { readdir, stat as stat2 } from "fs/promises";
1470
- import {
1471
- buildCompanyManifest,
1472
- companyManifestPath,
1473
- investWikiRoot,
1474
- resolveInsideWorkspace as resolveInsideWorkspace4
1475
- } from "@xdsjs/dossierx-workspace";
2758
+ import { readdir as readdir3, stat as stat3 } from "fs/promises";
1476
2759
  function isWorkspaceGuardError(error) {
1477
2760
  if (!(error instanceof Error)) {
1478
2761
  return false;
@@ -1485,7 +2768,7 @@ function isWorkspaceGuardError(error) {
1485
2768
  }
1486
2769
  function workspacePath(workspaceRoot, relativePath, step) {
1487
2770
  try {
1488
- return resolveInsideWorkspace4(workspaceRoot, relativePath);
2771
+ return resolveInsideWorkspace(workspaceRoot, relativePath);
1489
2772
  } catch (error) {
1490
2773
  if (isWorkspaceGuardError(error)) {
1491
2774
  throw new CodexRuntimeError(
@@ -1509,7 +2792,7 @@ function requireRunner(context) {
1509
2792
  }
1510
2793
  async function requireFile(filePath, step) {
1511
2794
  try {
1512
- const fileStat = await stat2(filePath);
2795
+ const fileStat = await stat3(filePath);
1513
2796
  if (fileStat.isFile()) {
1514
2797
  return;
1515
2798
  }
@@ -1527,7 +2810,7 @@ async function requireFile(filePath, step) {
1527
2810
  async function requireInitializedVault(workspaceRoot, ticker, step) {
1528
2811
  const vaultRoot = workspacePath(workspaceRoot, investWikiRoot(ticker), step);
1529
2812
  try {
1530
- const vaultStat = await stat2(vaultRoot);
2813
+ const vaultStat = await stat3(vaultRoot);
1531
2814
  if (!vaultStat.isDirectory()) {
1532
2815
  throw new CodexRuntimeError(
1533
2816
  "WORKSPACE_NOT_FOUND",
@@ -1593,10 +2876,10 @@ async function appendOutputEvent(context, message, output) {
1593
2876
  });
1594
2877
  }
1595
2878
  async function directoryHasFiles(root, relativePath) {
1596
- const directory = resolveInsideWorkspace4(root, relativePath);
2879
+ const directory = resolveInsideWorkspace(root, relativePath);
1597
2880
  let entries;
1598
2881
  try {
1599
- entries = await readdir(directory, { withFileTypes: true });
2882
+ entries = await readdir3(directory, { withFileTypes: true });
1600
2883
  } catch (error) {
1601
2884
  if (error.code === "ENOENT") {
1602
2885
  return false;
@@ -1672,9 +2955,9 @@ async function runCodexTask(task, context) {
1672
2955
  }
1673
2956
 
1674
2957
  // src/executors/financialReports.ts
1675
- import { createHash } from "crypto";
1676
- import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
1677
- import path6 from "path";
2958
+ import { createHash as createHash3 } from "crypto";
2959
+ import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
2960
+ import path10 from "path";
1678
2961
  import {
1679
2962
  FinancialReportManifestSchema,
1680
2963
  assessReportCoverage,
@@ -1685,12 +2968,6 @@ import {
1685
2968
  renderSecHtmlToPdf,
1686
2969
  runNotebookLmFinancialReportsIngest
1687
2970
  } from "@xdsjs/dossier-financial-reports";
1688
- import {
1689
- buildCompanyManifest as buildCompanyManifest2,
1690
- companyManifestPath as companyManifestPath2,
1691
- financialReportsIndexPath,
1692
- resolveInsideWorkspace as resolveInsideWorkspace5
1693
- } from "@xdsjs/dossierx-workspace";
1694
2971
  var FinancialReportsRuntimeError = class extends Error {
1695
2972
  code;
1696
2973
  step;
@@ -1728,7 +3005,7 @@ function marketToAppMarket(market) {
1728
3005
  return "cn";
1729
3006
  }
1730
3007
  function sha256Json(value) {
1731
- return `sha256:${createHash("sha256").update(JSON.stringify(value)).digest("hex")}`;
3008
+ return `sha256:${createHash3("sha256").update(JSON.stringify(value)).digest("hex")}`;
1732
3009
  }
1733
3010
  function writeWorkspaceJson(context, relativePath, value) {
1734
3011
  return writeWorkspaceBytes(
@@ -1747,10 +3024,10 @@ function writeWorkspaceText(context, relativePath, value) {
1747
3024
  );
1748
3025
  }
1749
3026
  async function writeWorkspaceBytes(context, relativePath, bytes) {
1750
- const absolutePath = resolveInsideWorkspace5(context.workspaceRoot, relativePath);
1751
- await mkdir3(path6.dirname(absolutePath), { recursive: true });
3027
+ const absolutePath = resolveInsideWorkspace(context.workspaceRoot, relativePath);
3028
+ await mkdir5(path10.dirname(absolutePath), { recursive: true });
1752
3029
  if (!context.dryRun) {
1753
- await writeFile2(absolutePath, bytes);
3030
+ await writeFile4(absolutePath, bytes);
1754
3031
  }
1755
3032
  }
1756
3033
  function createWorkspaceStorage(context) {
@@ -1761,8 +3038,8 @@ function createWorkspaceStorage(context) {
1761
3038
  };
1762
3039
  }
1763
3040
  function readWorkspaceJson(context, relativePath) {
1764
- const absolutePath = resolveInsideWorkspace5(context.workspaceRoot, relativePath);
1765
- return readFile4(absolutePath, "utf8").then((content) => JSON.parse(content));
3041
+ const absolutePath = resolveInsideWorkspace(context.workspaceRoot, relativePath);
3042
+ return readFile7(absolutePath, "utf8").then((content) => JSON.parse(content));
1766
3043
  }
1767
3044
  function parseReportManifest(payload) {
1768
3045
  const maybeRecord = typeof payload === "object" && payload !== null ? payload : {};
@@ -1771,6 +3048,31 @@ function parseReportManifest(payload) {
1771
3048
  }
1772
3049
  return FinancialReportManifestSchema.parse(maybeRecord.manifest);
1773
3050
  }
3051
+ function parseExistingNotebook(payload) {
3052
+ const record = typeof payload === "object" && payload !== null ? payload : {};
3053
+ const notebooklm = typeof record.notebooklm === "object" && record.notebooklm !== null ? record.notebooklm : {};
3054
+ const notebookId = typeof notebooklm.notebookId === "string" ? notebooklm.notebookId.trim() : "";
3055
+ if (!notebookId) {
3056
+ return void 0;
3057
+ }
3058
+ const sourceIds = Array.isArray(record.sourceIds) ? record.sourceIds.flatMap((source) => {
3059
+ const sourceRecord = typeof source === "object" && source !== null ? source : {};
3060
+ const reportId = typeof sourceRecord.reportId === "string" ? sourceRecord.reportId.trim() : "";
3061
+ const sourceId = typeof sourceRecord.sourceId === "string" ? sourceRecord.sourceId.trim() : "";
3062
+ return reportId && sourceId ? [{ reportId, sourceId }] : [];
3063
+ }) : [];
3064
+ return { notebookId, sourceIds };
3065
+ }
3066
+ async function readExistingNotebook(context, notebookPath) {
3067
+ try {
3068
+ return parseExistingNotebook(await readWorkspaceJson(context, notebookPath));
3069
+ } catch (error) {
3070
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
3071
+ return void 0;
3072
+ }
3073
+ throw error;
3074
+ }
3075
+ }
1774
3076
  async function readReportManifest(context, manifestPath) {
1775
3077
  try {
1776
3078
  return parseReportManifest(await readWorkspaceJson(context, manifestPath));
@@ -1930,7 +3232,7 @@ async function runSyncReports(task, context) {
1930
3232
  missingReports: result.missingReports
1931
3233
  };
1932
3234
  await writeWorkspaceJson(context, reportIndexPath, reportIndex);
1933
- const companyManifest = context.dryRun ? void 0 : await buildCompanyManifest2({
3235
+ const companyManifest = context.dryRun ? void 0 : await buildCompanyManifest({
1934
3236
  workspaceRoot: context.workspaceRoot,
1935
3237
  ticker,
1936
3238
  market: marketToAppMarket(market)
@@ -1949,9 +3251,9 @@ async function runSyncReports(task, context) {
1949
3251
  generatedFiles: [
1950
3252
  ...result.manifest.reports.map((report) => report.localPath),
1951
3253
  reportIndexPath,
1952
- companyManifestPath2(ticker)
3254
+ companyManifestPath(ticker)
1953
3255
  ],
1954
- manifestPath: companyManifestPath2(ticker),
3256
+ manifestPath: companyManifestPath(ticker),
1955
3257
  manifest: companyManifest,
1956
3258
  blockingReasons: [],
1957
3259
  financialReports: financialTaskResult({
@@ -1968,6 +3270,8 @@ async function runNotebookIngest(task, context) {
1968
3270
  const ticker = primaryTicker(manifest.issuer);
1969
3271
  const manifestHash = sha256Json(manifest);
1970
3272
  const factsAsOf = task.payload.factsAsOf ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3273
+ const notebookPath = `companies/${ticker}/financial-reports/notebooklm/notebook.json`;
3274
+ const existingNotebook = await readExistingNotebook(context, notebookPath);
1971
3275
  await context.appendEvent({
1972
3276
  level: "info",
1973
3277
  message: "Starting NotebookLM financial reports ingest",
@@ -1979,9 +3283,9 @@ async function runNotebookIngest(task, context) {
1979
3283
  manifestHash,
1980
3284
  factsAsOf,
1981
3285
  generatedAt: context.financialReports?.now?.(),
1982
- notebookTitle: task.payload.notebookTitle
3286
+ notebookTitle: task.payload.notebookTitle,
3287
+ existingNotebook
1983
3288
  });
1984
- const notebookPath = `companies/${ticker}/financial-reports/notebooklm/notebook.json`;
1985
3289
  const factsBundlePath = `companies/${ticker}/financial-reports/ingest/facts-bundle.json`;
1986
3290
  const wikiPath = `companies/${ticker}/financial-reports/wiki/financial-report-analysis.md`;
1987
3291
  await writeWorkspaceJson(context, notebookPath, {
@@ -1997,7 +3301,7 @@ async function runNotebookIngest(task, context) {
1997
3301
  wikiPath,
1998
3302
  renderFinancialFactsWiki(ingest.factsBundle)
1999
3303
  );
2000
- const companyManifest = context.dryRun ? void 0 : await buildCompanyManifest2({
3304
+ const companyManifest = context.dryRun ? void 0 : await buildCompanyManifest({
2001
3305
  workspaceRoot: context.workspaceRoot,
2002
3306
  ticker,
2003
3307
  market: marketToAppMarket(primaryMarket(manifest.issuer))
@@ -2017,9 +3321,9 @@ async function runNotebookIngest(task, context) {
2017
3321
  notebookPath,
2018
3322
  factsBundlePath,
2019
3323
  wikiPath,
2020
- companyManifestPath2(ticker)
3324
+ companyManifestPath(ticker)
2021
3325
  ],
2022
- manifestPath: companyManifestPath2(ticker),
3326
+ manifestPath: companyManifestPath(ticker),
2023
3327
  manifest: companyManifest,
2024
3328
  blockingReasons: [],
2025
3329
  financialReports: financialTaskResult({
@@ -2091,15 +3395,8 @@ async function runFinancialReportsTask(task, context) {
2091
3395
  }
2092
3396
 
2093
3397
  // src/executors/investWiki.ts
2094
- import { access as access2, mkdir as mkdir4, readFile as readFile5, stat as stat3, writeFile as writeFile3 } from "fs/promises";
2095
- import path7 from "path";
2096
- import {
2097
- buildCompanyManifest as buildCompanyManifest3,
2098
- companyManifestPath as companyManifestPath3,
2099
- investWikiConfigPath,
2100
- investWikiRoot as investWikiRoot2,
2101
- resolveInsideWorkspace as resolveInsideWorkspace6
2102
- } from "@xdsjs/dossierx-workspace";
3398
+ import { access as access2, mkdir as mkdir6, readFile as readFile8, stat as stat4, writeFile as writeFile5 } from "fs/promises";
3399
+ import path11 from "path";
2103
3400
  async function exists(absolutePath) {
2104
3401
  try {
2105
3402
  await access2(absolutePath);
@@ -2123,7 +3420,7 @@ function isWorkspaceGuardError2(error) {
2123
3420
  }
2124
3421
  function workspacePath2(workspaceRoot, relativePath, step) {
2125
3422
  try {
2126
- return resolveInsideWorkspace6(workspaceRoot, relativePath);
3423
+ return resolveInsideWorkspace(workspaceRoot, relativePath);
2127
3424
  } catch (error) {
2128
3425
  if (isWorkspaceGuardError2(error)) {
2129
3426
  throw new InvestWikiRuntimeError(
@@ -2146,9 +3443,9 @@ function requireRunner2(context) {
2146
3443
  return context.investWiki;
2147
3444
  }
2148
3445
  async function requireVaultRoot(workspaceRoot, ticker, step) {
2149
- const vaultRoot = workspacePath2(workspaceRoot, investWikiRoot2(ticker), step);
3446
+ const vaultRoot = workspacePath2(workspaceRoot, investWikiRoot(ticker), step);
2150
3447
  try {
2151
- const vaultStat = await stat3(vaultRoot);
3448
+ const vaultStat = await stat4(vaultRoot);
2152
3449
  if (vaultStat.isDirectory()) {
2153
3450
  return vaultRoot;
2154
3451
  }
@@ -2204,11 +3501,11 @@ function isMarket(value) {
2204
3501
  async function readManifestMarket(workspaceRoot, ticker) {
2205
3502
  const manifestPath = workspacePath2(
2206
3503
  workspaceRoot,
2207
- companyManifestPath3(ticker),
3504
+ companyManifestPath(ticker),
2208
3505
  "invest_wiki.sync"
2209
3506
  );
2210
3507
  try {
2211
- const manifest = JSON.parse(await readFile5(manifestPath, "utf8"));
3508
+ const manifest = JSON.parse(await readFile8(manifestPath, "utf8"));
2212
3509
  if (!isMarket(manifest.market)) {
2213
3510
  throw new InvestWikiRuntimeError(
2214
3511
  "VALIDATION_ERROR",
@@ -2234,7 +3531,7 @@ async function readManifestMarket(workspaceRoot, ticker) {
2234
3531
  async function runInitCompanyVault(task, context) {
2235
3532
  const runner = requireRunner2(context);
2236
3533
  const ticker = task.payload.ticker;
2237
- const vaultRelativePath = investWikiRoot2(ticker);
3534
+ const vaultRelativePath = investWikiRoot(ticker);
2238
3535
  const vaultRoot = workspacePath2(
2239
3536
  context.workspaceRoot,
2240
3537
  vaultRelativePath,
@@ -2251,7 +3548,7 @@ async function runInitCompanyVault(task, context) {
2251
3548
  `${vaultRelativePath}/.llm-wiki-invest/dossier-state.json`,
2252
3549
  "invest_wiki.init_company_vault"
2253
3550
  );
2254
- await mkdir4(vaultRoot, { recursive: true });
3551
+ await mkdir6(vaultRoot, { recursive: true });
2255
3552
  await context.appendEvent({
2256
3553
  level: "info",
2257
3554
  message: "Initializing invest-wiki vault",
@@ -2270,10 +3567,10 @@ async function runInitCompanyVault(task, context) {
2270
3567
  const statusOutput = await runner.run(["dossier", "status"], { cwd: vaultRoot });
2271
3568
  await appendOutputEvent2(context, "Invest wiki dossier status completed", statusOutput);
2272
3569
  if (!await exists(markerPath)) {
2273
- await mkdir4(path7.dirname(markerPath), { recursive: true });
2274
- await writeFile3(markerPath, "# Created by dossierx-daemon\n");
3570
+ await mkdir6(path11.dirname(markerPath), { recursive: true });
3571
+ await writeFile5(markerPath, "# Created by dossierx-daemon\n");
2275
3572
  }
2276
- const manifest = await buildCompanyManifest3({
3573
+ const manifest = await buildCompanyManifest({
2277
3574
  workspaceRoot: context.workspaceRoot,
2278
3575
  ticker,
2279
3576
  market: task.payload.market
@@ -2287,10 +3584,10 @@ async function runInitCompanyVault(task, context) {
2287
3584
  generatedFiles: [
2288
3585
  vaultRelativePath,
2289
3586
  markerRelativePath,
2290
- companyManifestPath3(ticker)
3587
+ companyManifestPath(ticker)
2291
3588
  ],
2292
3589
  blockingReasons: [],
2293
- manifestPath: companyManifestPath3(ticker),
3590
+ manifestPath: companyManifestPath(ticker),
2294
3591
  manifest
2295
3592
  };
2296
3593
  }
@@ -2315,7 +3612,7 @@ async function runStatus(task, context) {
2315
3612
  return {
2316
3613
  generatedFiles: [],
2317
3614
  blockingReasons: [],
2318
- manifestPath: companyManifestPath3(ticker)
3615
+ manifestPath: companyManifestPath(ticker)
2319
3616
  };
2320
3617
  }
2321
3618
  async function runSync(task, context) {
@@ -2330,7 +3627,7 @@ async function runSync(task, context) {
2330
3627
  const args = task.payload.dryRun ? ["sync", "--dry-run"] : ["sync"];
2331
3628
  const output = await runner.run(args, { cwd: vaultRoot });
2332
3629
  await appendOutputEvent2(context, "Invest wiki sync completed", output);
2333
- const manifest = await buildCompanyManifest3({
3630
+ const manifest = await buildCompanyManifest({
2334
3631
  workspaceRoot: context.workspaceRoot,
2335
3632
  ticker,
2336
3633
  market
@@ -2338,7 +3635,7 @@ async function runSync(task, context) {
2338
3635
  return {
2339
3636
  generatedFiles: [],
2340
3637
  blockingReasons: [],
2341
- manifestPath: companyManifestPath3(ticker),
3638
+ manifestPath: companyManifestPath(ticker),
2342
3639
  manifest
2343
3640
  };
2344
3641
  }
@@ -2360,17 +3657,8 @@ async function runInvestWikiTask(task, context) {
2360
3657
  }
2361
3658
 
2362
3659
  // src/executors/mockWriteCompanyReport.ts
2363
- import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
2364
- import path8 from "path";
2365
- import {
2366
- buildCompanyManifest as buildCompanyManifest4,
2367
- companyManifestPath as companyManifestPath4,
2368
- companyRoot,
2369
- resolveInsideWorkspace as resolveInsideWorkspace7,
2370
- rightBusinessPath,
2371
- rightPeoplePath,
2372
- rightPricePath
2373
- } from "@xdsjs/dossierx-workspace";
3660
+ import { mkdir as mkdir7, writeFile as writeFile6 } from "fs/promises";
3661
+ import path12 from "path";
2374
3662
  var rightBusiness = (ticker) => `# Right Business - ${ticker}
2375
3663
 
2376
3664
  > Mock output generated by dossierx-daemon.
@@ -2400,10 +3688,10 @@ var rightPrice = (ticker) => `# Right Price - ${ticker}
2400
3688
  This is a placeholder right-price analysis for ${ticker}.
2401
3689
  `;
2402
3690
  async function writeWorkspaceFile(context, relativePath, content) {
2403
- const absolutePath = resolveInsideWorkspace7(context.workspaceRoot, relativePath);
2404
- await mkdir5(path8.dirname(absolutePath), { recursive: true });
3691
+ const absolutePath = resolveInsideWorkspace(context.workspaceRoot, relativePath);
3692
+ await mkdir7(path12.dirname(absolutePath), { recursive: true });
2405
3693
  if (!context.dryRun) {
2406
- await writeFile4(absolutePath, content);
3694
+ await writeFile6(absolutePath, content);
2407
3695
  }
2408
3696
  }
2409
3697
  async function runMockWriteCompanyReport(task, context) {
@@ -2418,7 +3706,7 @@ async function runMockWriteCompanyReport(task, context) {
2418
3706
  message: "Creating company directory",
2419
3707
  data: { ticker }
2420
3708
  });
2421
- await mkdir5(resolveInsideWorkspace7(context.workspaceRoot, companyRoot(ticker)), {
3709
+ await mkdir7(resolveInsideWorkspace(context.workspaceRoot, companyRoot(ticker)), {
2422
3710
  recursive: true
2423
3711
  });
2424
3712
  await context.appendEvent({
@@ -2442,11 +3730,11 @@ async function runMockWriteCompanyReport(task, context) {
2442
3730
  await context.appendEvent({
2443
3731
  level: "info",
2444
3732
  message: "Generating manifest.json",
2445
- data: { path: companyManifestPath4(ticker) }
3733
+ data: { path: companyManifestPath(ticker) }
2446
3734
  });
2447
3735
  let manifest;
2448
3736
  if (!context.dryRun) {
2449
- manifest = await buildCompanyManifest4({
3737
+ manifest = await buildCompanyManifest({
2450
3738
  workspaceRoot: context.workspaceRoot,
2451
3739
  ticker,
2452
3740
  market: task.payload.market
@@ -2458,9 +3746,9 @@ async function runMockWriteCompanyReport(task, context) {
2458
3746
  data: { ticker }
2459
3747
  });
2460
3748
  return {
2461
- generatedFiles: [...generatedFiles, companyManifestPath4(ticker)],
3749
+ generatedFiles: [...generatedFiles, companyManifestPath(ticker)],
2462
3750
  blockingReasons: [],
2463
- manifestPath: companyManifestPath4(ticker),
3751
+ manifestPath: companyManifestPath(ticker),
2464
3752
  manifest
2465
3753
  };
2466
3754
  }
@@ -2487,7 +3775,7 @@ function taskIdFromUnknown(value) {
2487
3775
  if (!value || typeof value !== "object" || !("id" in value)) {
2488
3776
  return null;
2489
3777
  }
2490
- const parsed = z2.string().uuid().safeParse(value.id);
3778
+ const parsed = z13.string().uuid().safeParse(value.id);
2491
3779
  return parsed.success ? parsed.data : null;
2492
3780
  }
2493
3781
  async function appendEvent(ctx, taskId, message) {
@@ -2722,10 +4010,10 @@ function createLogger(level = "info", stream) {
2722
4010
  }
2723
4011
 
2724
4012
  // src/runtime/detect.ts
2725
- import { execa as execa5 } from "execa";
4013
+ import { execa as execa6 } from "execa";
2726
4014
  async function commandResponds(command, args = ["--version"]) {
2727
4015
  try {
2728
- await execa5(command, args, {
4016
+ await execa6(command, args, {
2729
4017
  reject: true,
2730
4018
  timeout: 2e3,
2731
4019
  stdout: "ignore",
@@ -2737,7 +4025,7 @@ async function commandResponds(command, args = ["--version"]) {
2737
4025
  }
2738
4026
  }
2739
4027
  async function detectCapabilities(options = {}) {
2740
- const [git, python3, python, investWikiRuntime, codex, claude, notebookLm] = await Promise.all([
4028
+ const [git2, python3, python, investWikiRuntime, codex, claude, notebookLm] = await Promise.all([
2741
4029
  commandResponds("git"),
2742
4030
  commandResponds("python3"),
2743
4031
  commandResponds("python"),
@@ -2747,7 +4035,7 @@ async function detectCapabilities(options = {}) {
2747
4035
  probeNotebookLmPythonClient(options.notebookLm)
2748
4036
  ]);
2749
4037
  return {
2750
- git,
4038
+ git: git2,
2751
4039
  node: true,
2752
4040
  python: python3 || python,
2753
4041
  financialReports: true,
@@ -2761,9 +4049,6 @@ async function detectCapabilities(options = {}) {
2761
4049
 
2762
4050
  // src/realtime/client.ts
2763
4051
  import { createClient } from "@supabase/supabase-js";
2764
- import {
2765
- RealtimeEventSchema
2766
- } from "@xdsjs/dossierx-shared";
2767
4052
  function normalizeBroadcast(message) {
2768
4053
  const value = message;
2769
4054
  if (value.payload && typeof value.payload === "object" && "event" in value.payload) {
@@ -2829,9 +4114,9 @@ async function subscribeToTaskAvailable(options, onEvent, onInvalidEvent) {
2829
4114
  }
2830
4115
 
2831
4116
  // src/service.ts
2832
- import { mkdir as mkdir6, unlink, writeFile as writeFile5 } from "fs/promises";
4117
+ import { mkdir as mkdir8, unlink, writeFile as writeFile7 } from "fs/promises";
2833
4118
  import os2 from "os";
2834
- import path9 from "path";
4119
+ import path13 from "path";
2835
4120
  var LAUNCH_AGENT_LABEL = "com.xdsjs.dossierx-daemon";
2836
4121
  function xmlEscape(value) {
2837
4122
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -2840,10 +4125,10 @@ function shellQuote(value) {
2840
4125
  return `'${value.replaceAll("'", "'\\''")}'`;
2841
4126
  }
2842
4127
  function launchAgentsDir() {
2843
- return path9.join(os2.homedir(), "Library", "LaunchAgents");
4128
+ return path13.join(os2.homedir(), "Library", "LaunchAgents");
2844
4129
  }
2845
4130
  function launchAgentPlistPath(label = LAUNCH_AGENT_LABEL, dir = launchAgentsDir()) {
2846
- return path9.join(dir, `${label}.plist`);
4131
+ return path13.join(dir, `${label}.plist`);
2847
4132
  }
2848
4133
  function resolveDaemonProgramArguments(input) {
2849
4134
  if (input.daemonCommand?.trim()) {
@@ -2854,14 +4139,14 @@ function resolveDaemonProgramArguments(input) {
2854
4139
  if (!entry) {
2855
4140
  throw new Error("Unable to resolve daemon entrypoint for LaunchAgent");
2856
4141
  }
2857
- if (path9.extname(entry) === ".ts") {
4142
+ if (path13.extname(entry) === ".ts") {
2858
4143
  throw new Error(
2859
4144
  "LaunchAgent cannot run a TypeScript daemon entrypoint directly; pass --daemon-command when installing from source"
2860
4145
  );
2861
4146
  }
2862
4147
  return [
2863
4148
  input.execPath ?? process.execPath,
2864
- path9.resolve(entry),
4149
+ path13.resolve(entry),
2865
4150
  "--log-level",
2866
4151
  input.logLevel ?? "info"
2867
4152
  ];
@@ -2924,7 +4209,7 @@ async function installLaunchAgent(options = {}) {
2924
4209
  throw new Error("DossierX LaunchAgent service is only supported on macOS");
2925
4210
  }
2926
4211
  const label = options.label ?? LAUNCH_AGENT_LABEL;
2927
- const configDir = path9.resolve(
4212
+ const configDir = path13.resolve(
2928
4213
  expandHomePath(options.configDir ?? getDaemonConfigDir())
2929
4214
  );
2930
4215
  const config = await readDaemonLocalConfig(configDir);
@@ -2944,8 +4229,8 @@ async function installLaunchAgent(options = {}) {
2944
4229
  );
2945
4230
  }
2946
4231
  const plistPath = launchAgentPlistPath(label, options.launchAgentsDir);
2947
- const stdoutPath = path9.join(configDir, "daemon.out.log");
2948
- const stderrPath = path9.join(configDir, "daemon.err.log");
4232
+ const stdoutPath = path13.join(configDir, "daemon.out.log");
4233
+ const stderrPath = path13.join(configDir, "daemon.err.log");
2949
4234
  const uid = typeof process.getuid === "function" ? process.getuid() : "<uid>";
2950
4235
  const programArguments = resolveDaemonProgramArguments({
2951
4236
  daemonCommand: options.daemonCommand,
@@ -2953,9 +4238,9 @@ async function installLaunchAgent(options = {}) {
2953
4238
  argv: options.argv,
2954
4239
  execPath: options.execPath
2955
4240
  });
2956
- await mkdir6(path9.dirname(plistPath), { recursive: true });
2957
- await mkdir6(configDir, { recursive: true, mode: 448 });
2958
- await writeFile5(
4241
+ await mkdir8(path13.dirname(plistPath), { recursive: true });
4242
+ await mkdir8(configDir, { recursive: true, mode: 448 });
4243
+ await writeFile7(
2959
4244
  plistPath,
2960
4245
  buildLaunchAgentPlist({
2961
4246
  label,
@@ -2996,14 +4281,14 @@ async function uninstallLaunchAgent(options = {}) {
2996
4281
 
2997
4282
  // src/cli.ts
2998
4283
  async function ensureWorkspaceDirectory(workspace) {
2999
- await mkdir7(workspace, { recursive: true }).catch(async (error) => {
3000
- const stats2 = await stat4(workspace).catch(() => null);
4284
+ await mkdir9(workspace, { recursive: true }).catch(async (error) => {
4285
+ const stats2 = await stat5(workspace).catch(() => null);
3001
4286
  if (!stats2?.isDirectory()) {
3002
4287
  throw new Error("Workspace path is not a directory");
3003
4288
  }
3004
4289
  throw error;
3005
4290
  });
3006
- const stats = await stat4(workspace);
4291
+ const stats = await stat5(workspace);
3007
4292
  if (!stats.isDirectory()) {
3008
4293
  throw new Error("Workspace path is not a directory");
3009
4294
  }
@@ -3109,7 +4394,7 @@ async function runDaemon(options) {
3109
4394
  "Missing daemon connection config. Run the generated daemon command from DossierX first."
3110
4395
  );
3111
4396
  }
3112
- const workspaceRoot = path10.resolve(expandHomePath(workspacePath3));
4397
+ const workspaceRoot = path14.resolve(expandHomePath(workspacePath3));
3113
4398
  await ensureWorkspaceDirectory(workspaceRoot);
3114
4399
  const notebookLmOptions = {
3115
4400
  pythonCommand: runtimeOptions.notebookLmPythonCommand,