@xdsjs/dossierx-daemon 0.1.12 → 0.1.14

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 +1538 -199
  2. package/package.json +3 -3
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.12";
2293
+ var DAEMON_VERSION = "0.1.14";
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(
@@ -1738,11 +3015,19 @@ function writeWorkspaceJson(context, relativePath, value) {
1738
3015
  `)
1739
3016
  );
1740
3017
  }
3018
+ function writeWorkspaceText(context, relativePath, value) {
3019
+ return writeWorkspaceBytes(
3020
+ context,
3021
+ relativePath,
3022
+ new TextEncoder().encode(value.endsWith("\n") ? value : `${value}
3023
+ `)
3024
+ );
3025
+ }
1741
3026
  async function writeWorkspaceBytes(context, relativePath, bytes) {
1742
- const absolutePath = resolveInsideWorkspace5(context.workspaceRoot, relativePath);
1743
- await mkdir3(path6.dirname(absolutePath), { recursive: true });
3027
+ const absolutePath = resolveInsideWorkspace(context.workspaceRoot, relativePath);
3028
+ await mkdir5(path10.dirname(absolutePath), { recursive: true });
1744
3029
  if (!context.dryRun) {
1745
- await writeFile2(absolutePath, bytes);
3030
+ await writeFile4(absolutePath, bytes);
1746
3031
  }
1747
3032
  }
1748
3033
  function createWorkspaceStorage(context) {
@@ -1753,8 +3038,8 @@ function createWorkspaceStorage(context) {
1753
3038
  };
1754
3039
  }
1755
3040
  function readWorkspaceJson(context, relativePath) {
1756
- const absolutePath = resolveInsideWorkspace5(context.workspaceRoot, relativePath);
1757
- 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));
1758
3043
  }
1759
3044
  function parseReportManifest(payload) {
1760
3045
  const maybeRecord = typeof payload === "object" && payload !== null ? payload : {};
@@ -1811,11 +3096,71 @@ function financialTaskResult(input) {
1811
3096
  manifestHash: input.manifestHash,
1812
3097
  notebookPath: input.notebookPath,
1813
3098
  factsBundlePath: input.factsBundlePath,
3099
+ wikiPath: input.wikiPath,
1814
3100
  reportCount: input.manifest.reports.length,
1815
3101
  coverageStatus: coverage.status,
1816
3102
  blockingReasons: coverage.knownGaps
1817
3103
  };
1818
3104
  }
3105
+ var financialFactsSectionLabels = {
3106
+ business: "\u4E1A\u52A1",
3107
+ revenueAndMargins: "\u6536\u5165\u548C\u6BDB\u5229",
3108
+ cashFlowAndBalanceSheet: "\u73B0\u91D1\u6D41\u548C\u8D44\u4EA7\u8D1F\u503A",
3109
+ growthDrivers: "\u589E\u957F\u9A71\u52A8",
3110
+ risksAndRedFlags: "\u98CE\u9669\u7EA2\u65D7",
3111
+ managementAndCapitalAllocation: "\u7BA1\u7406\u5C42\u548C\u8D44\u672C\u914D\u7F6E"
3112
+ };
3113
+ function renderFinancialFactsWiki(bundle) {
3114
+ const evidenceById = new Map(
3115
+ bundle.evidenceRefs.map((evidence) => [evidence.evidenceId, evidence])
3116
+ );
3117
+ const lines = [
3118
+ `# ${bundle.ticker} \u8D22\u62A5\u89E3\u8BFB`,
3119
+ "",
3120
+ `- factsAsOf: ${bundle.factsAsOf}`,
3121
+ `- manifestHash: ${bundle.manifestHash}`,
3122
+ `- sourceReports: ${bundle.sourceReportIds.length}`,
3123
+ `- coverage: ${bundle.sourceCoverage.status}`,
3124
+ ""
3125
+ ];
3126
+ for (const [sectionName, section] of Object.entries(bundle.sections)) {
3127
+ lines.push(`## ${financialFactsSectionLabels[sectionName]}`);
3128
+ lines.push("");
3129
+ lines.push(section.summary);
3130
+ lines.push("");
3131
+ for (const evidenceId of section.evidenceIds) {
3132
+ const evidence = evidenceById.get(evidenceId);
3133
+ if (!evidence) {
3134
+ continue;
3135
+ }
3136
+ lines.push(
3137
+ `- evidence: ${evidence.evidenceId} (${evidence.polarity}, ${evidence.sourceType}) - ${evidence.summary}`
3138
+ );
3139
+ lines.push(` - source: ${evidence.sourceUrlOrPath}`);
3140
+ lines.push(` - citation: ${formatCitation(evidence.citation)}`);
3141
+ }
3142
+ lines.push("");
3143
+ }
3144
+ if (bundle.blockingReasons.length > 0) {
3145
+ lines.push("## \u963B\u585E / \u7F3A\u53E3");
3146
+ lines.push("");
3147
+ for (const reason of bundle.blockingReasons) {
3148
+ lines.push(`- ${reason}`);
3149
+ }
3150
+ lines.push("");
3151
+ }
3152
+ return lines.join("\n");
3153
+ }
3154
+ function formatCitation(citation) {
3155
+ const locators = [
3156
+ citation.page === void 0 ? void 0 : `page ${citation.page}`,
3157
+ citation.pageRange ? `pages ${citation.pageRange}` : void 0,
3158
+ citation.sectionTitle,
3159
+ citation.notebooklmSourceId ? `NotebookLM ${citation.notebooklmSourceId}` : void 0,
3160
+ citation.quotedText ? `"${citation.quotedText}"` : void 0
3161
+ ].filter(Boolean);
3162
+ return locators.join("; ") || "citation locator unavailable";
3163
+ }
1819
3164
  async function runSyncReports(task, context) {
1820
3165
  const issuer = task.payload.issuer;
1821
3166
  const market = primaryMarket(issuer);
@@ -1862,7 +3207,7 @@ async function runSyncReports(task, context) {
1862
3207
  missingReports: result.missingReports
1863
3208
  };
1864
3209
  await writeWorkspaceJson(context, reportIndexPath, reportIndex);
1865
- const companyManifest = context.dryRun ? void 0 : await buildCompanyManifest2({
3210
+ const companyManifest = context.dryRun ? void 0 : await buildCompanyManifest({
1866
3211
  workspaceRoot: context.workspaceRoot,
1867
3212
  ticker,
1868
3213
  market: marketToAppMarket(market)
@@ -1881,9 +3226,9 @@ async function runSyncReports(task, context) {
1881
3226
  generatedFiles: [
1882
3227
  ...result.manifest.reports.map((report) => report.localPath),
1883
3228
  reportIndexPath,
1884
- companyManifestPath2(ticker)
3229
+ companyManifestPath(ticker)
1885
3230
  ],
1886
- manifestPath: companyManifestPath2(ticker),
3231
+ manifestPath: companyManifestPath(ticker),
1887
3232
  manifest: companyManifest,
1888
3233
  blockingReasons: [],
1889
3234
  financialReports: financialTaskResult({
@@ -1915,6 +3260,7 @@ async function runNotebookIngest(task, context) {
1915
3260
  });
1916
3261
  const notebookPath = `companies/${ticker}/financial-reports/notebooklm/notebook.json`;
1917
3262
  const factsBundlePath = `companies/${ticker}/financial-reports/ingest/facts-bundle.json`;
3263
+ const wikiPath = `companies/${ticker}/financial-reports/wiki/financial-report-analysis.md`;
1918
3264
  await writeWorkspaceJson(context, notebookPath, {
1919
3265
  schemaVersion: "financial-reports/notebooklm-run/v1",
1920
3266
  generatedAt: ingest.factsBundle.generatedAt,
@@ -1923,7 +3269,12 @@ async function runNotebookIngest(task, context) {
1923
3269
  sourceIds: ingest.sourceIds
1924
3270
  });
1925
3271
  await writeWorkspaceJson(context, factsBundlePath, ingest.factsBundle);
1926
- const companyManifest = context.dryRun ? void 0 : await buildCompanyManifest2({
3272
+ await writeWorkspaceText(
3273
+ context,
3274
+ wikiPath,
3275
+ renderFinancialFactsWiki(ingest.factsBundle)
3276
+ );
3277
+ const companyManifest = context.dryRun ? void 0 : await buildCompanyManifest({
1927
3278
  workspaceRoot: context.workspaceRoot,
1928
3279
  ticker,
1929
3280
  market: marketToAppMarket(primaryMarket(manifest.issuer))
@@ -1934,12 +3285,18 @@ async function runNotebookIngest(task, context) {
1934
3285
  data: {
1935
3286
  issuerId: manifest.issuer.issuerId,
1936
3287
  notebookPath,
1937
- factsBundlePath
3288
+ factsBundlePath,
3289
+ wikiPath
1938
3290
  }
1939
3291
  });
1940
3292
  return {
1941
- generatedFiles: [notebookPath, factsBundlePath, companyManifestPath2(ticker)],
1942
- manifestPath: companyManifestPath2(ticker),
3293
+ generatedFiles: [
3294
+ notebookPath,
3295
+ factsBundlePath,
3296
+ wikiPath,
3297
+ companyManifestPath(ticker)
3298
+ ],
3299
+ manifestPath: companyManifestPath(ticker),
1943
3300
  manifest: companyManifest,
1944
3301
  blockingReasons: [],
1945
3302
  financialReports: financialTaskResult({
@@ -1947,7 +3304,8 @@ async function runNotebookIngest(task, context) {
1947
3304
  manifestPath: task.payload.manifestPath,
1948
3305
  manifestHash,
1949
3306
  notebookPath,
1950
- factsBundlePath
3307
+ factsBundlePath,
3308
+ wikiPath
1951
3309
  })
1952
3310
  };
1953
3311
  }
@@ -2010,15 +3368,8 @@ async function runFinancialReportsTask(task, context) {
2010
3368
  }
2011
3369
 
2012
3370
  // src/executors/investWiki.ts
2013
- import { access as access2, mkdir as mkdir4, readFile as readFile5, stat as stat3, writeFile as writeFile3 } from "fs/promises";
2014
- import path7 from "path";
2015
- import {
2016
- buildCompanyManifest as buildCompanyManifest3,
2017
- companyManifestPath as companyManifestPath3,
2018
- investWikiConfigPath,
2019
- investWikiRoot as investWikiRoot2,
2020
- resolveInsideWorkspace as resolveInsideWorkspace6
2021
- } from "@xdsjs/dossierx-workspace";
3371
+ import { access as access2, mkdir as mkdir6, readFile as readFile8, stat as stat4, writeFile as writeFile5 } from "fs/promises";
3372
+ import path11 from "path";
2022
3373
  async function exists(absolutePath) {
2023
3374
  try {
2024
3375
  await access2(absolutePath);
@@ -2042,7 +3393,7 @@ function isWorkspaceGuardError2(error) {
2042
3393
  }
2043
3394
  function workspacePath2(workspaceRoot, relativePath, step) {
2044
3395
  try {
2045
- return resolveInsideWorkspace6(workspaceRoot, relativePath);
3396
+ return resolveInsideWorkspace(workspaceRoot, relativePath);
2046
3397
  } catch (error) {
2047
3398
  if (isWorkspaceGuardError2(error)) {
2048
3399
  throw new InvestWikiRuntimeError(
@@ -2065,9 +3416,9 @@ function requireRunner2(context) {
2065
3416
  return context.investWiki;
2066
3417
  }
2067
3418
  async function requireVaultRoot(workspaceRoot, ticker, step) {
2068
- const vaultRoot = workspacePath2(workspaceRoot, investWikiRoot2(ticker), step);
3419
+ const vaultRoot = workspacePath2(workspaceRoot, investWikiRoot(ticker), step);
2069
3420
  try {
2070
- const vaultStat = await stat3(vaultRoot);
3421
+ const vaultStat = await stat4(vaultRoot);
2071
3422
  if (vaultStat.isDirectory()) {
2072
3423
  return vaultRoot;
2073
3424
  }
@@ -2123,11 +3474,11 @@ function isMarket(value) {
2123
3474
  async function readManifestMarket(workspaceRoot, ticker) {
2124
3475
  const manifestPath = workspacePath2(
2125
3476
  workspaceRoot,
2126
- companyManifestPath3(ticker),
3477
+ companyManifestPath(ticker),
2127
3478
  "invest_wiki.sync"
2128
3479
  );
2129
3480
  try {
2130
- const manifest = JSON.parse(await readFile5(manifestPath, "utf8"));
3481
+ const manifest = JSON.parse(await readFile8(manifestPath, "utf8"));
2131
3482
  if (!isMarket(manifest.market)) {
2132
3483
  throw new InvestWikiRuntimeError(
2133
3484
  "VALIDATION_ERROR",
@@ -2153,7 +3504,7 @@ async function readManifestMarket(workspaceRoot, ticker) {
2153
3504
  async function runInitCompanyVault(task, context) {
2154
3505
  const runner = requireRunner2(context);
2155
3506
  const ticker = task.payload.ticker;
2156
- const vaultRelativePath = investWikiRoot2(ticker);
3507
+ const vaultRelativePath = investWikiRoot(ticker);
2157
3508
  const vaultRoot = workspacePath2(
2158
3509
  context.workspaceRoot,
2159
3510
  vaultRelativePath,
@@ -2170,7 +3521,7 @@ async function runInitCompanyVault(task, context) {
2170
3521
  `${vaultRelativePath}/.llm-wiki-invest/dossier-state.json`,
2171
3522
  "invest_wiki.init_company_vault"
2172
3523
  );
2173
- await mkdir4(vaultRoot, { recursive: true });
3524
+ await mkdir6(vaultRoot, { recursive: true });
2174
3525
  await context.appendEvent({
2175
3526
  level: "info",
2176
3527
  message: "Initializing invest-wiki vault",
@@ -2189,10 +3540,10 @@ async function runInitCompanyVault(task, context) {
2189
3540
  const statusOutput = await runner.run(["dossier", "status"], { cwd: vaultRoot });
2190
3541
  await appendOutputEvent2(context, "Invest wiki dossier status completed", statusOutput);
2191
3542
  if (!await exists(markerPath)) {
2192
- await mkdir4(path7.dirname(markerPath), { recursive: true });
2193
- await writeFile3(markerPath, "# Created by dossierx-daemon\n");
3543
+ await mkdir6(path11.dirname(markerPath), { recursive: true });
3544
+ await writeFile5(markerPath, "# Created by dossierx-daemon\n");
2194
3545
  }
2195
- const manifest = await buildCompanyManifest3({
3546
+ const manifest = await buildCompanyManifest({
2196
3547
  workspaceRoot: context.workspaceRoot,
2197
3548
  ticker,
2198
3549
  market: task.payload.market
@@ -2206,10 +3557,10 @@ async function runInitCompanyVault(task, context) {
2206
3557
  generatedFiles: [
2207
3558
  vaultRelativePath,
2208
3559
  markerRelativePath,
2209
- companyManifestPath3(ticker)
3560
+ companyManifestPath(ticker)
2210
3561
  ],
2211
3562
  blockingReasons: [],
2212
- manifestPath: companyManifestPath3(ticker),
3563
+ manifestPath: companyManifestPath(ticker),
2213
3564
  manifest
2214
3565
  };
2215
3566
  }
@@ -2234,7 +3585,7 @@ async function runStatus(task, context) {
2234
3585
  return {
2235
3586
  generatedFiles: [],
2236
3587
  blockingReasons: [],
2237
- manifestPath: companyManifestPath3(ticker)
3588
+ manifestPath: companyManifestPath(ticker)
2238
3589
  };
2239
3590
  }
2240
3591
  async function runSync(task, context) {
@@ -2249,7 +3600,7 @@ async function runSync(task, context) {
2249
3600
  const args = task.payload.dryRun ? ["sync", "--dry-run"] : ["sync"];
2250
3601
  const output = await runner.run(args, { cwd: vaultRoot });
2251
3602
  await appendOutputEvent2(context, "Invest wiki sync completed", output);
2252
- const manifest = await buildCompanyManifest3({
3603
+ const manifest = await buildCompanyManifest({
2253
3604
  workspaceRoot: context.workspaceRoot,
2254
3605
  ticker,
2255
3606
  market
@@ -2257,7 +3608,7 @@ async function runSync(task, context) {
2257
3608
  return {
2258
3609
  generatedFiles: [],
2259
3610
  blockingReasons: [],
2260
- manifestPath: companyManifestPath3(ticker),
3611
+ manifestPath: companyManifestPath(ticker),
2261
3612
  manifest
2262
3613
  };
2263
3614
  }
@@ -2279,17 +3630,8 @@ async function runInvestWikiTask(task, context) {
2279
3630
  }
2280
3631
 
2281
3632
  // src/executors/mockWriteCompanyReport.ts
2282
- import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
2283
- import path8 from "path";
2284
- import {
2285
- buildCompanyManifest as buildCompanyManifest4,
2286
- companyManifestPath as companyManifestPath4,
2287
- companyRoot,
2288
- resolveInsideWorkspace as resolveInsideWorkspace7,
2289
- rightBusinessPath,
2290
- rightPeoplePath,
2291
- rightPricePath
2292
- } from "@xdsjs/dossierx-workspace";
3633
+ import { mkdir as mkdir7, writeFile as writeFile6 } from "fs/promises";
3634
+ import path12 from "path";
2293
3635
  var rightBusiness = (ticker) => `# Right Business - ${ticker}
2294
3636
 
2295
3637
  > Mock output generated by dossierx-daemon.
@@ -2319,10 +3661,10 @@ var rightPrice = (ticker) => `# Right Price - ${ticker}
2319
3661
  This is a placeholder right-price analysis for ${ticker}.
2320
3662
  `;
2321
3663
  async function writeWorkspaceFile(context, relativePath, content) {
2322
- const absolutePath = resolveInsideWorkspace7(context.workspaceRoot, relativePath);
2323
- await mkdir5(path8.dirname(absolutePath), { recursive: true });
3664
+ const absolutePath = resolveInsideWorkspace(context.workspaceRoot, relativePath);
3665
+ await mkdir7(path12.dirname(absolutePath), { recursive: true });
2324
3666
  if (!context.dryRun) {
2325
- await writeFile4(absolutePath, content);
3667
+ await writeFile6(absolutePath, content);
2326
3668
  }
2327
3669
  }
2328
3670
  async function runMockWriteCompanyReport(task, context) {
@@ -2337,7 +3679,7 @@ async function runMockWriteCompanyReport(task, context) {
2337
3679
  message: "Creating company directory",
2338
3680
  data: { ticker }
2339
3681
  });
2340
- await mkdir5(resolveInsideWorkspace7(context.workspaceRoot, companyRoot(ticker)), {
3682
+ await mkdir7(resolveInsideWorkspace(context.workspaceRoot, companyRoot(ticker)), {
2341
3683
  recursive: true
2342
3684
  });
2343
3685
  await context.appendEvent({
@@ -2361,11 +3703,11 @@ async function runMockWriteCompanyReport(task, context) {
2361
3703
  await context.appendEvent({
2362
3704
  level: "info",
2363
3705
  message: "Generating manifest.json",
2364
- data: { path: companyManifestPath4(ticker) }
3706
+ data: { path: companyManifestPath(ticker) }
2365
3707
  });
2366
3708
  let manifest;
2367
3709
  if (!context.dryRun) {
2368
- manifest = await buildCompanyManifest4({
3710
+ manifest = await buildCompanyManifest({
2369
3711
  workspaceRoot: context.workspaceRoot,
2370
3712
  ticker,
2371
3713
  market: task.payload.market
@@ -2377,9 +3719,9 @@ async function runMockWriteCompanyReport(task, context) {
2377
3719
  data: { ticker }
2378
3720
  });
2379
3721
  return {
2380
- generatedFiles: [...generatedFiles, companyManifestPath4(ticker)],
3722
+ generatedFiles: [...generatedFiles, companyManifestPath(ticker)],
2381
3723
  blockingReasons: [],
2382
- manifestPath: companyManifestPath4(ticker),
3724
+ manifestPath: companyManifestPath(ticker),
2383
3725
  manifest
2384
3726
  };
2385
3727
  }
@@ -2406,7 +3748,7 @@ function taskIdFromUnknown(value) {
2406
3748
  if (!value || typeof value !== "object" || !("id" in value)) {
2407
3749
  return null;
2408
3750
  }
2409
- const parsed = z2.string().uuid().safeParse(value.id);
3751
+ const parsed = z13.string().uuid().safeParse(value.id);
2410
3752
  return parsed.success ? parsed.data : null;
2411
3753
  }
2412
3754
  async function appendEvent(ctx, taskId, message) {
@@ -2641,10 +3983,10 @@ function createLogger(level = "info", stream) {
2641
3983
  }
2642
3984
 
2643
3985
  // src/runtime/detect.ts
2644
- import { execa as execa5 } from "execa";
3986
+ import { execa as execa6 } from "execa";
2645
3987
  async function commandResponds(command, args = ["--version"]) {
2646
3988
  try {
2647
- await execa5(command, args, {
3989
+ await execa6(command, args, {
2648
3990
  reject: true,
2649
3991
  timeout: 2e3,
2650
3992
  stdout: "ignore",
@@ -2656,7 +3998,7 @@ async function commandResponds(command, args = ["--version"]) {
2656
3998
  }
2657
3999
  }
2658
4000
  async function detectCapabilities(options = {}) {
2659
- const [git, python3, python, investWikiRuntime, codex, claude, notebookLm] = await Promise.all([
4001
+ const [git2, python3, python, investWikiRuntime, codex, claude, notebookLm] = await Promise.all([
2660
4002
  commandResponds("git"),
2661
4003
  commandResponds("python3"),
2662
4004
  commandResponds("python"),
@@ -2666,7 +4008,7 @@ async function detectCapabilities(options = {}) {
2666
4008
  probeNotebookLmPythonClient(options.notebookLm)
2667
4009
  ]);
2668
4010
  return {
2669
- git,
4011
+ git: git2,
2670
4012
  node: true,
2671
4013
  python: python3 || python,
2672
4014
  financialReports: true,
@@ -2680,9 +4022,6 @@ async function detectCapabilities(options = {}) {
2680
4022
 
2681
4023
  // src/realtime/client.ts
2682
4024
  import { createClient } from "@supabase/supabase-js";
2683
- import {
2684
- RealtimeEventSchema
2685
- } from "@xdsjs/dossierx-shared";
2686
4025
  function normalizeBroadcast(message) {
2687
4026
  const value = message;
2688
4027
  if (value.payload && typeof value.payload === "object" && "event" in value.payload) {
@@ -2748,9 +4087,9 @@ async function subscribeToTaskAvailable(options, onEvent, onInvalidEvent) {
2748
4087
  }
2749
4088
 
2750
4089
  // src/service.ts
2751
- import { mkdir as mkdir6, unlink, writeFile as writeFile5 } from "fs/promises";
4090
+ import { mkdir as mkdir8, unlink, writeFile as writeFile7 } from "fs/promises";
2752
4091
  import os2 from "os";
2753
- import path9 from "path";
4092
+ import path13 from "path";
2754
4093
  var LAUNCH_AGENT_LABEL = "com.xdsjs.dossierx-daemon";
2755
4094
  function xmlEscape(value) {
2756
4095
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
@@ -2759,10 +4098,10 @@ function shellQuote(value) {
2759
4098
  return `'${value.replaceAll("'", "'\\''")}'`;
2760
4099
  }
2761
4100
  function launchAgentsDir() {
2762
- return path9.join(os2.homedir(), "Library", "LaunchAgents");
4101
+ return path13.join(os2.homedir(), "Library", "LaunchAgents");
2763
4102
  }
2764
4103
  function launchAgentPlistPath(label = LAUNCH_AGENT_LABEL, dir = launchAgentsDir()) {
2765
- return path9.join(dir, `${label}.plist`);
4104
+ return path13.join(dir, `${label}.plist`);
2766
4105
  }
2767
4106
  function resolveDaemonProgramArguments(input) {
2768
4107
  if (input.daemonCommand?.trim()) {
@@ -2773,14 +4112,14 @@ function resolveDaemonProgramArguments(input) {
2773
4112
  if (!entry) {
2774
4113
  throw new Error("Unable to resolve daemon entrypoint for LaunchAgent");
2775
4114
  }
2776
- if (path9.extname(entry) === ".ts") {
4115
+ if (path13.extname(entry) === ".ts") {
2777
4116
  throw new Error(
2778
4117
  "LaunchAgent cannot run a TypeScript daemon entrypoint directly; pass --daemon-command when installing from source"
2779
4118
  );
2780
4119
  }
2781
4120
  return [
2782
4121
  input.execPath ?? process.execPath,
2783
- path9.resolve(entry),
4122
+ path13.resolve(entry),
2784
4123
  "--log-level",
2785
4124
  input.logLevel ?? "info"
2786
4125
  ];
@@ -2843,7 +4182,7 @@ async function installLaunchAgent(options = {}) {
2843
4182
  throw new Error("DossierX LaunchAgent service is only supported on macOS");
2844
4183
  }
2845
4184
  const label = options.label ?? LAUNCH_AGENT_LABEL;
2846
- const configDir = path9.resolve(
4185
+ const configDir = path13.resolve(
2847
4186
  expandHomePath(options.configDir ?? getDaemonConfigDir())
2848
4187
  );
2849
4188
  const config = await readDaemonLocalConfig(configDir);
@@ -2863,8 +4202,8 @@ async function installLaunchAgent(options = {}) {
2863
4202
  );
2864
4203
  }
2865
4204
  const plistPath = launchAgentPlistPath(label, options.launchAgentsDir);
2866
- const stdoutPath = path9.join(configDir, "daemon.out.log");
2867
- const stderrPath = path9.join(configDir, "daemon.err.log");
4205
+ const stdoutPath = path13.join(configDir, "daemon.out.log");
4206
+ const stderrPath = path13.join(configDir, "daemon.err.log");
2868
4207
  const uid = typeof process.getuid === "function" ? process.getuid() : "<uid>";
2869
4208
  const programArguments = resolveDaemonProgramArguments({
2870
4209
  daemonCommand: options.daemonCommand,
@@ -2872,9 +4211,9 @@ async function installLaunchAgent(options = {}) {
2872
4211
  argv: options.argv,
2873
4212
  execPath: options.execPath
2874
4213
  });
2875
- await mkdir6(path9.dirname(plistPath), { recursive: true });
2876
- await mkdir6(configDir, { recursive: true, mode: 448 });
2877
- await writeFile5(
4214
+ await mkdir8(path13.dirname(plistPath), { recursive: true });
4215
+ await mkdir8(configDir, { recursive: true, mode: 448 });
4216
+ await writeFile7(
2878
4217
  plistPath,
2879
4218
  buildLaunchAgentPlist({
2880
4219
  label,
@@ -2915,14 +4254,14 @@ async function uninstallLaunchAgent(options = {}) {
2915
4254
 
2916
4255
  // src/cli.ts
2917
4256
  async function ensureWorkspaceDirectory(workspace) {
2918
- await mkdir7(workspace, { recursive: true }).catch(async (error) => {
2919
- const stats2 = await stat4(workspace).catch(() => null);
4257
+ await mkdir9(workspace, { recursive: true }).catch(async (error) => {
4258
+ const stats2 = await stat5(workspace).catch(() => null);
2920
4259
  if (!stats2?.isDirectory()) {
2921
4260
  throw new Error("Workspace path is not a directory");
2922
4261
  }
2923
4262
  throw error;
2924
4263
  });
2925
- const stats = await stat4(workspace);
4264
+ const stats = await stat5(workspace);
2926
4265
  if (!stats.isDirectory()) {
2927
4266
  throw new Error("Workspace path is not a directory");
2928
4267
  }
@@ -3028,7 +4367,7 @@ async function runDaemon(options) {
3028
4367
  "Missing daemon connection config. Run the generated daemon command from DossierX first."
3029
4368
  );
3030
4369
  }
3031
- const workspaceRoot = path10.resolve(expandHomePath(workspacePath3));
4370
+ const workspaceRoot = path14.resolve(expandHomePath(workspacePath3));
3032
4371
  await ensureWorkspaceDirectory(workspaceRoot);
3033
4372
  const notebookLmOptions = {
3034
4373
  pythonCommand: runtimeOptions.notebookLmPythonCommand,