@jmanuelcorral/openteam 0.18.1 → 0.20.0

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 (162) hide show
  1. package/.opencode/openteam.example.json +23 -14
  2. package/AGENTS.md +16 -2
  3. package/README.es.md +300 -209
  4. package/README.md +300 -139
  5. package/dist/capabilities/classify.d.ts.map +1 -1
  6. package/dist/capabilities/normalize.d.ts.map +1 -1
  7. package/dist/certificates/graph-release-certificate.json +2 -2
  8. package/dist/certificates/graph-shadow-certificate.json +2 -2
  9. package/dist/cli/consoleServe.d.ts +16 -0
  10. package/dist/cli/consoleServe.d.ts.map +1 -1
  11. package/dist/cli/graphOperator.d.ts +10 -1
  12. package/dist/cli/graphOperator.d.ts.map +1 -1
  13. package/dist/cli/lifecycleHistoryProvider.d.ts +21 -0
  14. package/dist/cli/lifecycleHistoryProvider.d.ts.map +1 -0
  15. package/dist/cli.d.ts +3 -1
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +6841 -1555
  18. package/dist/commands/agents.d.ts +16 -4
  19. package/dist/commands/agents.d.ts.map +1 -1
  20. package/dist/commands/dispatch.d.ts.map +1 -1
  21. package/dist/commands/doctor.d.ts.map +1 -1
  22. package/dist/commands/local.d.ts +4 -5
  23. package/dist/commands/local.d.ts.map +1 -1
  24. package/dist/commands/report.d.ts +6 -6
  25. package/dist/commands/report.d.ts.map +1 -1
  26. package/dist/commands/rolesInit.d.ts +10 -12
  27. package/dist/commands/rolesInit.d.ts.map +1 -1
  28. package/dist/commands/setup.d.ts +5 -13
  29. package/dist/commands/setup.d.ts.map +1 -1
  30. package/dist/commands/yolo.d.ts +2 -4
  31. package/dist/commands/yolo.d.ts.map +1 -1
  32. package/dist/config/errors.d.ts.map +1 -1
  33. package/dist/config/executionPolicyDomains.d.ts +18 -0
  34. package/dist/config/executionPolicyDomains.d.ts.map +1 -0
  35. package/dist/config/migrations.d.ts +9 -2
  36. package/dist/config/migrations.d.ts.map +1 -1
  37. package/dist/config/persist.d.ts.map +1 -1
  38. package/dist/config/runtime.d.ts +2 -0
  39. package/dist/config/runtime.d.ts.map +1 -1
  40. package/dist/config/schema.d.ts +128 -13
  41. package/dist/config/schema.d.ts.map +1 -1
  42. package/dist/console/assets.d.ts +22 -1
  43. package/dist/console/assets.d.ts.map +1 -1
  44. package/dist/console/configView.d.ts +2 -7
  45. package/dist/console/configView.d.ts.map +1 -1
  46. package/dist/console/render.d.ts +12 -0
  47. package/dist/console/render.d.ts.map +1 -1
  48. package/dist/console/types.d.ts +2 -2
  49. package/dist/console/types.d.ts.map +1 -1
  50. package/dist/context/schema.d.ts +13 -7
  51. package/dist/context/schema.d.ts.map +1 -1
  52. package/dist/graph/certificate.d.ts.map +1 -1
  53. package/dist/graph/langgraph/adapter.d.ts +7 -8
  54. package/dist/graph/langgraph/adapter.d.ts.map +1 -1
  55. package/dist/graph/langgraph/certification.d.ts +5 -0
  56. package/dist/graph/langgraph/certification.d.ts.map +1 -1
  57. package/dist/graph/langgraph/checkpointReplay.d.ts.map +1 -1
  58. package/dist/graph/langgraph/engine.d.ts +2 -2
  59. package/dist/graph/langgraph/engine.d.ts.map +1 -1
  60. package/dist/graph/langgraph/types.d.ts +11 -6
  61. package/dist/graph/langgraph/types.d.ts.map +1 -1
  62. package/dist/graph/privacyPolicy.d.ts +6 -30
  63. package/dist/graph/privacyPolicy.d.ts.map +1 -1
  64. package/dist/index.d.ts +1 -9
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +5992 -1390
  67. package/dist/lifecycle/contracts.d.ts +618 -0
  68. package/dist/lifecycle/contracts.d.ts.map +1 -0
  69. package/dist/lifecycle/historyReader.d.ts +11 -0
  70. package/dist/lifecycle/historyReader.d.ts.map +1 -0
  71. package/dist/lifecycle/historySourceError.d.ts +7 -0
  72. package/dist/lifecycle/historySourceError.d.ts.map +1 -0
  73. package/dist/lifecycle/project.d.ts +3 -0
  74. package/dist/lifecycle/project.d.ts.map +1 -0
  75. package/dist/lifecycle/root.d.ts +3 -0
  76. package/dist/lifecycle/root.d.ts.map +1 -0
  77. package/dist/lifecycle/runtimeRecorder.d.ts +6 -0
  78. package/dist/lifecycle/runtimeRecorder.d.ts.map +1 -0
  79. package/dist/lifecycle/schema.d.ts +487 -0
  80. package/dist/lifecycle/schema.d.ts.map +1 -0
  81. package/dist/mcp/teamMemory.d.ts +2 -2
  82. package/dist/mcp/teamMemory.d.ts.map +1 -1
  83. package/dist/messages/commands.d.ts +22 -35
  84. package/dist/messages/commands.d.ts.map +1 -1
  85. package/dist/messages/executionSetup.d.ts +116 -0
  86. package/dist/messages/executionSetup.d.ts.map +1 -0
  87. package/dist/messages/index.d.ts +2 -0
  88. package/dist/messages/index.d.ts.map +1 -1
  89. package/dist/messages/lifecycle.d.ts +95 -0
  90. package/dist/messages/lifecycle.d.ts.map +1 -0
  91. package/dist/messages/lifecycleRuntime.d.ts +4 -0
  92. package/dist/messages/lifecycleRuntime.d.ts.map +1 -0
  93. package/dist/messages/lifecycleStorage.d.ts +4 -0
  94. package/dist/messages/lifecycleStorage.d.ts.map +1 -0
  95. package/dist/messages/memoryTool.d.ts +17 -0
  96. package/dist/messages/memoryTool.d.ts.map +1 -0
  97. package/dist/messages/orchestration.d.ts +16 -0
  98. package/dist/messages/orchestration.d.ts.map +1 -0
  99. package/dist/messages/routing.d.ts +9 -0
  100. package/dist/messages/routing.d.ts.map +1 -0
  101. package/dist/opencodeArtifacts/orchestratorAgent.d.ts +3 -5
  102. package/dist/opencodeArtifacts/orchestratorAgent.d.ts.map +1 -1
  103. package/dist/orchestrator/coordinator.d.ts +30 -13
  104. package/dist/orchestrator/coordinator.d.ts.map +1 -1
  105. package/dist/orchestrator/graphEffects.d.ts +10 -11
  106. package/dist/orchestrator/graphEffects.d.ts.map +1 -1
  107. package/dist/orchestrator/graphIngress.d.ts +5 -0
  108. package/dist/orchestrator/graphIngress.d.ts.map +1 -1
  109. package/dist/orchestrator/graphRuntime.d.ts +13 -1
  110. package/dist/orchestrator/graphRuntime.d.ts.map +1 -1
  111. package/dist/orchestrator/outputContract.d.ts +5 -6
  112. package/dist/orchestrator/outputContract.d.ts.map +1 -1
  113. package/dist/orchestrator/roles.d.ts +25 -2
  114. package/dist/orchestrator/roles.d.ts.map +1 -1
  115. package/dist/orchestrator/runtimeSelection.d.ts.map +1 -1
  116. package/dist/orchestrator/subsessions.d.ts +52 -1
  117. package/dist/orchestrator/subsessions.d.ts.map +1 -1
  118. package/dist/plugin/availability.d.ts +15 -2
  119. package/dist/plugin/availability.d.ts.map +1 -1
  120. package/dist/plugin/diagnostics.d.ts +1 -0
  121. package/dist/plugin/diagnostics.d.ts.map +1 -1
  122. package/dist/plugin/hooks.d.ts +21 -2
  123. package/dist/plugin/hooks.d.ts.map +1 -1
  124. package/dist/plugin/memoryTool.d.ts +3 -3
  125. package/dist/plugin/memoryTool.d.ts.map +1 -1
  126. package/dist/plugin/modelOwnership.d.ts +15 -0
  127. package/dist/plugin/modelOwnership.d.ts.map +1 -0
  128. package/dist/plugin/orchestrateTool.d.ts +53 -3
  129. package/dist/plugin/orchestrateTool.d.ts.map +1 -1
  130. package/dist/router/chooseModel.d.ts.map +1 -1
  131. package/dist/router/cost.d.ts +1 -1
  132. package/dist/router/cost.d.ts.map +1 -1
  133. package/dist/router/executionPolicy.d.ts +44 -0
  134. package/dist/router/executionPolicy.d.ts.map +1 -0
  135. package/dist/router/frontierBaseline.d.ts.map +1 -1
  136. package/dist/router/types.d.ts +10 -4
  137. package/dist/router/types.d.ts.map +1 -1
  138. package/dist/storage/lifecycle/codec.d.ts +19 -0
  139. package/dist/storage/lifecycle/codec.d.ts.map +1 -0
  140. package/dist/storage/lifecycle/fsLifecycleJournal.d.ts +3 -0
  141. package/dist/storage/lifecycle/fsLifecycleJournal.d.ts.map +1 -0
  142. package/dist/storage/lifecycle/fsLifecycleSupport.d.ts +17 -0
  143. package/dist/storage/lifecycle/fsLifecycleSupport.d.ts.map +1 -0
  144. package/dist/storage/lifecycle/fsLifecycleWriterLivenessProbe.d.ts +3 -0
  145. package/dist/storage/lifecycle/fsLifecycleWriterLivenessProbe.d.ts.map +1 -0
  146. package/dist/telemetry/aggregate.d.ts +4 -4
  147. package/dist/telemetry/aggregate.d.ts.map +1 -1
  148. package/dist/telemetry/diagnostics.d.ts.map +1 -1
  149. package/dist/telemetry/events.d.ts +6 -6
  150. package/dist/telemetry/otel.d.ts.map +1 -1
  151. package/dist/telemetry/types.d.ts +3 -3
  152. package/dist/web/configApi.d.ts +3 -1
  153. package/dist/web/configApi.d.ts.map +1 -1
  154. package/dist/web/graphRoute.d.ts +39 -1
  155. package/dist/web/graphRoute.d.ts.map +1 -1
  156. package/dist/web/server.d.ts +19 -0
  157. package/dist/web/server.d.ts.map +1 -1
  158. package/dist/web/start.d.ts +11 -0
  159. package/dist/web/start.d.ts.map +1 -1
  160. package/dist/web/watch.d.ts +17 -2
  161. package/dist/web/watch.d.ts.map +1 -1
  162. package/package.json +1 -1
@@ -10,6 +10,11 @@ export declare const RouterModeSchema: z.ZodEnum<{
10
10
  economy: "economy";
11
11
  quality: "quality";
12
12
  }>;
13
+ export declare const ExecutionModeSchema: z.ZodEnum<{
14
+ frontier: "frontier";
15
+ local: "local";
16
+ mixed: "mixed";
17
+ }>;
13
18
  export declare const PrivacyModeSchema: z.ZodEnum<{
14
19
  consentBeforeFrontier: "consentBeforeFrontier";
15
20
  forceLocalOnSensitive: "forceLocalOnSensitive";
@@ -52,6 +57,18 @@ export declare const GraphEngineSchema: z.ZodEnum<{
52
57
  */
53
58
  export declare const DEFAULT_GRAPH_JOURNAL_ROOT = ".opencode/openteam-local/graph/runs";
54
59
  export declare const DEFAULT_GRAPH_WORKTREES_DIR = ".opencode/openteam-local/graph/worktrees";
60
+ export declare const DEFAULT_LIFECYCLE_ROOT = ".opencode/openteam-local/lifecycle/runs";
61
+ export declare const DEFAULT_LIFECYCLE_MAX_TERMINAL_RUNS = 200;
62
+ export declare const DEFAULT_LIFECYCLE_MAX_AGE_DAYS = 30;
63
+ export declare const DEFAULT_LIFECYCLE_MAX_BYTES = 268435456;
64
+ export declare const LifecycleConfigSchema: z.ZodDefault<z.ZodObject<{
65
+ root: z.ZodDefault<z.ZodString>;
66
+ retention: z.ZodDefault<z.ZodObject<{
67
+ maxTerminalRuns: z.ZodDefault<z.ZodNumber>;
68
+ maxAgeDays: z.ZodDefault<z.ZodNumber>;
69
+ maxBytes: z.ZodDefault<z.ZodNumber>;
70
+ }, z.core.$strict>>;
71
+ }, z.core.$strict>>;
55
72
  export declare const GraphConfigSchema: z.ZodObject<{
56
73
  mode: z.ZodDefault<z.ZodEnum<{
57
74
  active: "active";
@@ -107,6 +124,41 @@ export declare const StorageConfigSchema: z.ZodDefault<z.ZodObject<{
107
124
  path: z.ZodDefault<z.ZodString>;
108
125
  }, z.core.$strict>>;
109
126
  }, z.core.$strict>>;
127
+ export declare const AgentExecutionPolicySchema: z.ZodObject<{
128
+ executionMode: z.ZodOptional<z.ZodEnum<{
129
+ frontier: "frontier";
130
+ local: "local";
131
+ mixed: "mixed";
132
+ }>>;
133
+ model: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
134
+ providerID: z.ZodString;
135
+ modelID: z.ZodString;
136
+ }, z.core.$strict>, z.ZodLiteral<"auto">]>>;
137
+ fallbacks: z.ZodOptional<z.ZodArray<z.ZodObject<{
138
+ providerID: z.ZodString;
139
+ modelID: z.ZodString;
140
+ }, z.core.$strict>>>;
141
+ }, z.core.$strict>;
142
+ declare const OrchestratorConfigSchema: z.ZodObject<{
143
+ roles: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>, z.ZodTransform<Record<string, AgentRoleProfile>, Record<string, unknown>>>;
144
+ primary: z.ZodOptional<z.ZodObject<{
145
+ executionMode: z.ZodOptional<z.ZodEnum<{
146
+ frontier: "frontier";
147
+ local: "local";
148
+ mixed: "mixed";
149
+ }>>;
150
+ model: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
151
+ providerID: z.ZodString;
152
+ modelID: z.ZodString;
153
+ }, z.core.$strict>, z.ZodLiteral<"auto">]>>;
154
+ fallbacks: z.ZodOptional<z.ZodArray<z.ZodObject<{
155
+ providerID: z.ZodString;
156
+ modelID: z.ZodString;
157
+ }, z.core.$strict>>>;
158
+ }, z.core.$strict>>;
159
+ maxRetries: z.ZodOptional<z.ZodNumber>;
160
+ maxModelsPerNode: z.ZodOptional<z.ZodNumber>;
161
+ }, z.core.$strict>;
110
162
  /**
111
163
  * Default per-runtime concurrency cap when a runtime does not declare
112
164
  * `maxConcurrency` (#144). Applied at read time — the field is optional in the
@@ -177,10 +229,10 @@ export declare function effectiveMaxConcurrency(runtime: Pick<LocalRuntime, "max
177
229
  */
178
230
  export declare function effectiveReservedInteractiveSlots(runtime: Pick<LocalRuntime, "maxConcurrency" | "reservedInteractiveSlots">): number;
179
231
  /**
180
- * Bloque de memoria semántica long-term (capa de conocimiento). Opt-in y
181
- * desactivado por defecto (ADR-1..6). Privacy-first: `storeContent=false` guarda
182
- * estructura redactada + `sourceHash`, nunca el prompt crudo. La extracción es
183
- * local-first; frontier solo como fallback opt-in respetando `forceLocalOnSensitive`.
232
+ * Long-term semantic memory is opt-in and disabled by default (ADR-1..6).
233
+ * `storeContent=false` keeps redacted structure and `sourceHash`, never the raw
234
+ * prompt. Extraction is local-first; frontier fallback is explicitly configured,
235
+ * not authorized or blocked by inferred content sensitivity.
184
236
  */
185
237
  export declare const MemoryScopeSchema: z.ZodEnum<{
186
238
  project: "project";
@@ -289,7 +341,7 @@ export declare const MemoryConfigSchema: z.ZodObject<{
289
341
  }, z.core.$strict>>;
290
342
  }, z.core.$strict>;
291
343
  export declare const OpenTeamConfigObjectSchema: z.ZodObject<{
292
- configVersion: z.ZodOptional<z.ZodLiteral<1>>;
344
+ configVersion: z.ZodOptional<z.ZodLiteral<2>>;
293
345
  baseline: z.ZodDefault<z.ZodObject<{
294
346
  mode: z.ZodDefault<z.ZodEnum<{
295
347
  auto: "auto";
@@ -310,14 +362,19 @@ export declare const OpenTeamConfigObjectSchema: z.ZodObject<{
310
362
  economy: "economy";
311
363
  quality: "quality";
312
364
  }>>;
365
+ executionMode: z.ZodOptional<z.ZodEnum<{
366
+ frontier: "frontier";
367
+ local: "local";
368
+ mixed: "mixed";
369
+ }>>;
313
370
  localDefault: z.ZodDefault<z.ZodNullable<z.ZodObject<{
314
371
  providerID: z.ZodString;
315
372
  modelID: z.ZodString;
316
373
  }, z.core.$strict>>>;
317
374
  trivialPromptMaxChars: z.ZodDefault<z.ZodNumber>;
318
375
  frontierPromptMinChars: z.ZodDefault<z.ZodNumber>;
319
- frontierOnly: z.ZodDefault<z.ZodBoolean>;
320
- localOnly: z.ZodDefault<z.ZodBoolean>;
376
+ frontierOnly: z.ZodOptional<z.ZodBoolean>;
377
+ localOnly: z.ZodOptional<z.ZodBoolean>;
321
378
  }, z.core.$strict>>;
322
379
  local: z.ZodDefault<z.ZodObject<{
323
380
  runtimes: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -352,7 +409,7 @@ export declare const OpenTeamConfigObjectSchema: z.ZodObject<{
352
409
  frontierTokensPerSession: z.ZodOptional<z.ZodNumber>;
353
410
  hardStopOnBudgetExhaustion: z.ZodDefault<z.ZodBoolean>;
354
411
  }, z.core.$strict>>;
355
- privacyMode: z.ZodDefault<z.ZodEnum<{
412
+ privacyMode: z.ZodOptional<z.ZodEnum<{
356
413
  consentBeforeFrontier: "consentBeforeFrontier";
357
414
  forceLocalOnSensitive: "forceLocalOnSensitive";
358
415
  off: "off";
@@ -424,6 +481,14 @@ export declare const OpenTeamConfigObjectSchema: z.ZodObject<{
424
481
  }, z.core.$strict>>;
425
482
  }, z.core.$strict>>;
426
483
  }, z.core.$strict>>;
484
+ lifecycle: z.ZodDefault<z.ZodObject<{
485
+ root: z.ZodDefault<z.ZodString>;
486
+ retention: z.ZodDefault<z.ZodObject<{
487
+ maxTerminalRuns: z.ZodDefault<z.ZodNumber>;
488
+ maxAgeDays: z.ZodDefault<z.ZodNumber>;
489
+ maxBytes: z.ZodDefault<z.ZodNumber>;
490
+ }, z.core.$strict>>;
491
+ }, z.core.$strict>>;
427
492
  graph: z.ZodDefault<z.ZodObject<{
428
493
  mode: z.ZodDefault<z.ZodEnum<{
429
494
  active: "active";
@@ -443,12 +508,28 @@ export declare const OpenTeamConfigObjectSchema: z.ZodObject<{
443
508
  }, z.core.$strict>>;
444
509
  orchestrator: z.ZodOptional<z.ZodObject<{
445
510
  roles: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>, z.ZodTransform<Record<string, AgentRoleProfile>, Record<string, unknown>>>;
511
+ primary: z.ZodOptional<z.ZodObject<{
512
+ executionMode: z.ZodOptional<z.ZodEnum<{
513
+ frontier: "frontier";
514
+ local: "local";
515
+ mixed: "mixed";
516
+ }>>;
517
+ model: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
518
+ providerID: z.ZodString;
519
+ modelID: z.ZodString;
520
+ }, z.core.$strict>, z.ZodLiteral<"auto">]>>;
521
+ fallbacks: z.ZodOptional<z.ZodArray<z.ZodObject<{
522
+ providerID: z.ZodString;
523
+ modelID: z.ZodString;
524
+ }, z.core.$strict>>>;
525
+ }, z.core.$strict>>;
446
526
  maxRetries: z.ZodOptional<z.ZodNumber>;
527
+ maxModelsPerNode: z.ZodOptional<z.ZodNumber>;
447
528
  }, z.core.$strict>>;
448
529
  }, z.core.$strict>;
449
530
  /** Esquema público de la config de openteam. */
450
531
  export declare const OpenTeamConfigSchema: z.ZodObject<{
451
- configVersion: z.ZodOptional<z.ZodLiteral<1>>;
532
+ configVersion: z.ZodOptional<z.ZodLiteral<2>>;
452
533
  baseline: z.ZodDefault<z.ZodObject<{
453
534
  mode: z.ZodDefault<z.ZodEnum<{
454
535
  auto: "auto";
@@ -469,14 +550,19 @@ export declare const OpenTeamConfigSchema: z.ZodObject<{
469
550
  economy: "economy";
470
551
  quality: "quality";
471
552
  }>>;
553
+ executionMode: z.ZodOptional<z.ZodEnum<{
554
+ frontier: "frontier";
555
+ local: "local";
556
+ mixed: "mixed";
557
+ }>>;
472
558
  localDefault: z.ZodDefault<z.ZodNullable<z.ZodObject<{
473
559
  providerID: z.ZodString;
474
560
  modelID: z.ZodString;
475
561
  }, z.core.$strict>>>;
476
562
  trivialPromptMaxChars: z.ZodDefault<z.ZodNumber>;
477
563
  frontierPromptMinChars: z.ZodDefault<z.ZodNumber>;
478
- frontierOnly: z.ZodDefault<z.ZodBoolean>;
479
- localOnly: z.ZodDefault<z.ZodBoolean>;
564
+ frontierOnly: z.ZodOptional<z.ZodBoolean>;
565
+ localOnly: z.ZodOptional<z.ZodBoolean>;
480
566
  }, z.core.$strict>>;
481
567
  local: z.ZodDefault<z.ZodObject<{
482
568
  runtimes: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -511,7 +597,7 @@ export declare const OpenTeamConfigSchema: z.ZodObject<{
511
597
  frontierTokensPerSession: z.ZodOptional<z.ZodNumber>;
512
598
  hardStopOnBudgetExhaustion: z.ZodDefault<z.ZodBoolean>;
513
599
  }, z.core.$strict>>;
514
- privacyMode: z.ZodDefault<z.ZodEnum<{
600
+ privacyMode: z.ZodOptional<z.ZodEnum<{
515
601
  consentBeforeFrontier: "consentBeforeFrontier";
516
602
  forceLocalOnSensitive: "forceLocalOnSensitive";
517
603
  off: "off";
@@ -583,6 +669,14 @@ export declare const OpenTeamConfigSchema: z.ZodObject<{
583
669
  }, z.core.$strict>>;
584
670
  }, z.core.$strict>>;
585
671
  }, z.core.$strict>>;
672
+ lifecycle: z.ZodDefault<z.ZodObject<{
673
+ root: z.ZodDefault<z.ZodString>;
674
+ retention: z.ZodDefault<z.ZodObject<{
675
+ maxTerminalRuns: z.ZodDefault<z.ZodNumber>;
676
+ maxAgeDays: z.ZodDefault<z.ZodNumber>;
677
+ maxBytes: z.ZodDefault<z.ZodNumber>;
678
+ }, z.core.$strict>>;
679
+ }, z.core.$strict>>;
586
680
  graph: z.ZodDefault<z.ZodObject<{
587
681
  mode: z.ZodDefault<z.ZodEnum<{
588
682
  active: "active";
@@ -602,27 +696,48 @@ export declare const OpenTeamConfigSchema: z.ZodObject<{
602
696
  }, z.core.$strict>>;
603
697
  orchestrator: z.ZodOptional<z.ZodObject<{
604
698
  roles: z.ZodPipe<z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>, z.ZodTransform<Record<string, AgentRoleProfile>, Record<string, unknown>>>;
699
+ primary: z.ZodOptional<z.ZodObject<{
700
+ executionMode: z.ZodOptional<z.ZodEnum<{
701
+ frontier: "frontier";
702
+ local: "local";
703
+ mixed: "mixed";
704
+ }>>;
705
+ model: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
706
+ providerID: z.ZodString;
707
+ modelID: z.ZodString;
708
+ }, z.core.$strict>, z.ZodLiteral<"auto">]>>;
709
+ fallbacks: z.ZodOptional<z.ZodArray<z.ZodObject<{
710
+ providerID: z.ZodString;
711
+ modelID: z.ZodString;
712
+ }, z.core.$strict>>>;
713
+ }, z.core.$strict>>;
605
714
  maxRetries: z.ZodOptional<z.ZodNumber>;
715
+ maxModelsPerNode: z.ZodOptional<z.ZodNumber>;
606
716
  }, z.core.$strict>>;
607
717
  }, z.core.$strict>;
608
718
  export type ModelRef = z.infer<typeof ModelRefSchema>;
609
719
  export type RouterMode = z.infer<typeof RouterModeSchema>;
720
+ export type ExecutionMode = z.infer<typeof ExecutionModeSchema>;
610
721
  export type PrivacyMode = z.infer<typeof PrivacyModeSchema>;
611
722
  export type GraphMode = z.infer<typeof GraphModeSchema>;
612
723
  export type GraphConfig = z.infer<typeof GraphConfigSchema>;
724
+ export type LifecycleConfig = z.infer<typeof LifecycleConfigSchema>;
613
725
  export type LocalRuntime = z.infer<typeof LocalRuntimeSchema>;
614
726
  type ParsedConsoleConfig = z.infer<typeof ConsoleConfigSchema>;
615
727
  export type ConsoleConfig = Omit<ParsedConsoleConfig, "graphView"> & {
616
728
  readonly graphView?: ParsedConsoleConfig["graphView"];
617
729
  };
618
730
  type ParsedOpenTeamConfig = z.infer<typeof OpenTeamConfigSchema>;
619
- export type OpenTeamConfig = Omit<ParsedOpenTeamConfig, "console" | "graph"> & {
731
+ export type OpenTeamConfig = Omit<ParsedOpenTeamConfig, "console" | "graph" | "lifecycle"> & {
620
732
  readonly console: ConsoleConfig;
621
733
  readonly graph?: ParsedOpenTeamConfig["graph"];
734
+ readonly lifecycle?: ParsedOpenTeamConfig["lifecycle"];
622
735
  };
623
736
  export type StorageConfig = z.infer<typeof StorageConfigSchema>;
624
737
  export type MemoryConfig = z.infer<typeof MemoryConfigSchema>;
625
738
  export type MemorySemanticConfig = z.infer<typeof MemorySemanticSchema>;
739
+ export type OrchestratorConfig = z.infer<typeof OrchestratorConfigSchema>;
740
+ export type ConfiguredAgentExecutionPolicy = z.infer<typeof AgentExecutionPolicySchema>;
626
741
  /**
627
742
  * Resuelve la config de memoria semántica efectiva. Si `memory` está ausente,
628
743
  * devuelve los defaults (memoria desactivada). Fuente única de defaults.
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EACL,KAAK,gBAAgB,EAKtB,MAAM,uBAAuB,CAAC;AAS/B,eAAO,MAAM,cAAc;;;kBAKhB,CAAC;AAEZ,eAAO,MAAM,gBAAgB;;;;EAA6C,CAAC;AAC3E,eAAO,MAAM,mBAAmB;;;;EAAyC,CAAC;AAC1E,eAAO,MAAM,iBAAiB;;;;EAI5B,CAAC;AACH,eAAO,MAAM,kBAAkB;;;EAA6B,CAAC;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,eAAe;;;;EAAsC,CAAC;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;;;EAAmC,CAAC;AAElE;;;GAGG;AAEH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,wCAAwC,CAAC;AAChF,eAAO,MAAM,2BAA2B,6CACI,CAAC;AAC7C,eAAO,MAAM,sBAAsB,4CAA4C,CAAC;AAChF,eAAO,MAAM,mCAAmC,MAAM,CAAC;AACvD,eAAO,MAAM,8BAA8B,KAAK,CAAC;AACjD,eAAO,MAAM,2BAA2B,YAAc,CAAC;AAEvD,eAAO,MAAM,qBAAqB;;;;;;;mBAmC9B,CAAC;AAEL,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;kBA4DnB,CAAC;AAEZ,eAAO,MAAM,iBAAiB;;;EAAqC,CAAC;AAEpE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;mBAiD5B,CAAC;AAEL;;GAEG;AAEH;;;;GAIG;AACH,eAAO,MAAM,iCAAiC,0CACL,CAAC;AAE1C,eAAO,MAAM,mBAAmB;;;;;mBAa5B,CAAC;AAqHL,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;kBAM5B,CAAC;AAEZ,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;kBAoBnB,CAAC;AAQZ;;;;;;;;;;GAUG;AACH,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C,eAAO,MAAM,sBAAsB;;;;;EAKjC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;kBA+F3B,CAAC;AAEL;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,CAAC,GACzC,gBAAgB,CAElB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,gBAAgB,CAAC,GAC5C,MAAM,CAER;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,gBAAgB,GAAG,0BAA0B,CAAC,GACzE,MAAM,CAKR;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;EAA8B,CAAC;AAC7D,eAAO,MAAM,0BAA0B;;;EAGrC,CAAC;AACH,eAAO,MAAM,8BAA8B;;;EAA4B,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,4CACG,CAAC;AAC5C,eAAO,MAAM,yBAAyB,iDACU,CAAC;AAEjD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAiD7B,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAIpB,CAAC;AAEZ,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqKnC,CAAC;AAEL,gDAAgD;AAChD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAA6B,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,KAAK,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAC/D,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,GAAG;IACnE,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;CACvD,CAAC;AACF,KAAK,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjE,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,oBAAoB,EACpB,SAAS,GAAG,OAAO,GAAG,WAAW,CAClC,GAAG;IACF,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC/C,QAAQ,CAAC,SAAS,CAAC,EAAE,oBAAoB,CAAC,WAAW,CAAC,CAAC;CACxD,CAAC;AACF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACxE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC1E,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAClD,OAAO,0BAA0B,CAClC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,GACrB,oBAAoB,CAEtB"}
@@ -13,5 +13,26 @@ export declare const CONSOLE_STYLE = "\n:root{color-scheme:dark;--bg:#0f0f0f;--s
13
13
  * cancelación/veredicto/linaje/artefacto).
14
14
  */
15
15
  export declare const GRAPH_STYLE = "\n.graph-wrap{overflow:auto;background:#0b0d11;border:1px solid var(--line);border-radius:8px;padding:8px}\nsvg.graph{display:block}\n.gedge{stroke:#3a4250;stroke-width:1.5;marker-end:url(#garrow)}\n.gnode rect{fill:var(--panel);stroke:var(--line);stroke-width:1.5;rx:8}\n.gnode .gname{fill:var(--fg);font:600 12px ui-monospace,Consolas,monospace}\n.gnode .grole{fill:var(--muted);font-size:11px}\n.gnode .gstate{font-size:10px;text-transform:uppercase;letter-spacing:.05em}\n.gnode.state-pending rect{stroke:#6e7681}\n.gnode.state-pending .gstate{fill:#6e7681}\n.gnode.state-ready rect{stroke:var(--local)}\n.gnode.state-ready .gstate{fill:var(--local)}\n.gnode.state-active rect{stroke:var(--frontier)}\n.gnode.state-active .gstate{fill:var(--frontier)}\n.gnode.state-succeeded rect{stroke:var(--good)}\n.gnode.state-succeeded .gstate{fill:var(--good)}\n.gnode.state-failed rect{stroke:#f85149}\n.gnode.state-failed .gstate{fill:#f85149}\n.gnode.state-cancelled rect{stroke:#484f58}\n.gnode.state-cancelled .gstate{fill:#484f58}\n.gbadge{font-size:10px;font-family:ui-monospace,Consolas,monospace}\n.gbadge.badge-retry{fill:var(--frontier)}\n.gbadge.badge-error{fill:#f85149}\n.gbadge.badge-cancelled{fill:#484f58}\n.gbadge.badge-verdict.verdict-approved{fill:var(--good)}\n.gbadge.badge-verdict.verdict-rejected{fill:#f85149}\n.gbadge.badge-verdict.verdict-inconclusive{fill:var(--frontier)}\n.gbadge.badge-lineage{fill:var(--local)}\n.gbadge.badge-artifact{fill:var(--muted)}\n.gnode[data-session]{cursor:pointer}\n.gnode[data-session]:hover rect{stroke-width:2.5}\n.graph-health{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px}\n.gchip{font-size:11px;padding:2px 10px;border-radius:10px;border:1px solid var(--line);color:var(--muted)}\n.gchip.on{font-weight:600}\n.gchip.gh-recovery.on,.gchip.gh-unknown.on{color:var(--frontier);border-color:var(--frontier)}\n.gchip.gh-conflict.on,.gchip.gh-kill.on{color:#f85149;border-color:#f85149}\n.graph-drill{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}\n.graph-drill h3{font-size:13px;margin:0 0 8px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em}\n.graph-drill .drilllog{background:#0b0d11;border:1px solid var(--line);border-radius:8px;padding:10px;max-height:280px;overflow:auto;font-family:ui-monospace,Consolas,monospace;font-size:12px;white-space:pre-wrap}\n.graph-drill .drilllog .tl{padding:1px 0}\n.graph-drill .drilllog .tl.tool{color:var(--frontier)}\n.graph-drill .drilllog .tl.status{color:var(--muted)}\n.graph-drill .drilllog .tl.permission{color:var(--frontier);font-weight:600}\n.graph-drill .drilllog .tl.error{color:#f85149}\n";
16
- export declare const CONSOLE_CLIENT_JS = "\n(function(){\n var authTok='';\n try{\n var qp=new URLSearchParams(window.location.search).get('token');\n if(qp){authTok='?token='+encodeURIComponent(qp)}\n }catch(e){/* ignore */}\n function reloadIfChanged(prev){\n fetch('/api/state'+authTok).then(function(r){return r.json()}).then(function(s){\n if(s.generatedAt!==prev&&!configActive()){location.reload()}\n }).catch(function(){});\n }\n var current=document.documentElement.getAttribute('data-generated')||'';\n if('EventSource' in window){\n try{\n var es=new EventSource('/events'+authTok);\n es.addEventListener('state',function(){if(!configActive()){location.reload()}});\n es.onerror=function(){/* fallback below */};\n }catch(e){/* ignore */}\n }\n var ms=parseInt(document.documentElement.getAttribute('data-refresh')||'2000',10);\n setInterval(function(){reloadIfChanged(current)},isNaN(ms)?2000:Math.max(250,ms));\n\n function configActive(){\n var s=document.getElementById('screen-config');\n return !!(s&&!s.hidden);\n }\n function wireLogsScreen(screen){\n if(screen.__logsWired){return}\n screen.__logsWired=true;\n var buttons=screen.querySelectorAll('[data-session-target]');\n var cards=screen.querySelectorAll('[data-session-view]');\n function showSession(id){\n var matched=false;\n for(var i=0;i<buttons.length;i++){\n var on=buttons[i].getAttribute('data-session-target')===id;\n buttons[i].classList.toggle('sel',on);\n buttons[i].setAttribute('aria-selected',on?'true':'false');\n }\n for(var j=0;j<cards.length;j++){\n var show=cards[j].getAttribute('data-session-view')===id;\n cards[j].hidden=!show;\n if(show){matched=true;connectTerminal(cards[j],id)}\n }\n return matched;\n }\n for(var k=0;k<buttons.length;k++){\n buttons[k].addEventListener('click',function(e){\n var id=e.currentTarget.getAttribute('data-session-target');\n if(id){showSession(id)}\n });\n }\n if(buttons.length>0){\n showSession(buttons[0].getAttribute('data-session-target'));\n }\n }\n function selectScreen(name){\n var screens=document.querySelectorAll('.screen');\n var items=document.querySelectorAll('[data-screen]');\n var matched=false;\n var titleText='';\n var activeScreen=null;\n for(var i=0;i<screens.length;i++){\n var show=screens[i].id==='screen-'+name;\n screens[i].classList.toggle('active',show);\n screens[i].hidden=!show;\n if(show){matched=true;activeScreen=screens[i]}\n }\n if(!matched){return false}\n for(var j=0;j<items.length;j++){\n var on=items[j].getAttribute('data-screen')===name;\n if(on){\n items[j].setAttribute('aria-current','page');\n titleText=items[j].getAttribute('data-title')||'';\n }else{\n items[j].removeAttribute('aria-current');\n }\n }\n var title=document.getElementById('screen-title');\n if(title){title.textContent=titleText}\n if(name==='config'&&activeScreen){loadConfig(activeScreen)}\n if(name==='logs'&&activeScreen){wireLogsScreen(activeScreen)}\n try{localStorage.setItem('openteam.screen',name)}catch(e){}\n document.body.classList.remove('nav-open');\n return true;\n }\n function esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}\n // Config editor (W7-S09 / #193). The config values travel only over the\n // token-gated /api/config, never in this open page, so the browser fetches\n // the server-rendered form with the bearer token and injects it. The\n // applied/pending-restart summary is likewise server-rendered and injected\n // verbatim, so the P14 honesty is enforced server-side, not here.\n function loadConfig(view){\n var root=document.documentElement;\n if(root.getAttribute('data-config')!=='1'||view.__configWired){return}\n var mount=view.querySelector('[data-config-mount]');\n if(!mount){return}\n var token=root.getAttribute('data-token');\n if(!token){mount.innerHTML='<p class=\"muted\">Read-only: no console token present.</p>';return}\n view.__configWired=true;\n fetch('/api/config',{headers:{Authorization:'Bearer '+token}})\n .then(function(r){return r.json()})\n .then(function(d){\n mount.innerHTML=d.render||'<p class=\"config-err\">Could not load configuration.</p>';\n wireConfigForm(mount,token);\n })\n .catch(function(){view.__configWired=false;mount.innerHTML='<p class=\"config-err\">Could not load configuration.</p>'});\n }\n function wireConfigForm(mount,token){\n var form=mount.querySelector('[data-config-form]');\n if(!form){return}\n var out=form.querySelector('[data-config-result]');\n form.addEventListener('submit',function(e){\n e.preventDefault();\n var ta=form.querySelector('textarea[name=\"config\"]');\n var parsed;\n try{parsed=JSON.parse(ta.value)}catch(err){out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">Invalid JSON: '+esc(err.message||err)+'</p></div>';return}\n var btn=form.querySelector('.config-save');\n if(btn){btn.disabled=true}\n fetch('/api/config',{method:'POST',headers:{Authorization:'Bearer '+token,'content-type':'application/json'},body:JSON.stringify(parsed)})\n .then(function(r){return r.json().then(function(b){return{status:r.status,body:b}})})\n .then(function(res){\n if(btn){btn.disabled=false}\n if(res.status===200){out.innerHTML=res.body.render||''}\n else{out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">'+esc(res.body&&res.body.error?res.body.error:'Save failed.')+'</p></div>'}\n })\n .catch(function(){if(btn){btn.disabled=false}out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">Save failed.</p></div>'});\n });\n }\n function connectTerminal(view,id){\n if(view.__wired){return}\n var root=document.documentElement;\n var token=root.getAttribute('data-token');\n if(root.getAttribute('data-terminal')!=='1'||!token){return}\n var log=view.querySelector('.termlog');\n if(!log){return}\n view.__wired=true;\n function append(cls,text){\n var line=document.createElement('div');\n line.className='tl '+cls;line.textContent=text;\n log.appendChild(line);log.scrollTop=log.scrollHeight;\n }\n var q='/console/session/'+encodeURIComponent(id);\n var tk='token='+encodeURIComponent(token);\n if('EventSource' in window){\n try{\n var es=new EventSource(q+'/stream?'+tk);\n es.addEventListener('frame',function(e){try{var f=JSON.parse(e.data);append(f.kind,f.text)}catch(_){}}); \n es.onerror=function(){/* reconnects on its own */};\n }catch(_){/* ignore */}\n }\n var form=view.querySelector('form.terminput');\n if(form){\n form.addEventListener('submit',function(e){\n e.preventDefault();\n var inp=form.querySelector('input[name=text]');\n var text=inp.value;\n if(!text){return}\n inp.value='';append('input','\u203A '+text);\n fetch(q+'/input?'+tk,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({text:text})})\n .then(function(r){if(!r.ok){append('error','\u2716 send rejected ('+r.status+')')}})\n .catch(function(){append('error','\u2716 could not send')});\n });\n }\n connectPty(view,id,q,tk);\n }\n function connectPty(view,id,q,tk){\n var root=document.documentElement;\n if(root.getAttribute('data-pty')!=='1'){return}\n var pane=view.querySelector('.pty');\n if(!pane){return}\n var log=pane.querySelector('.ptylog');\n var startBtn=pane.querySelector('.pty-start');\n var input=pane.querySelector('form.ptyinput');\n function plog(text){\n var d=document.createElement('span');d.textContent=text;\n log.appendChild(d);log.scrollTop=log.scrollHeight;\n }\n if(!startBtn){return}\n startBtn.addEventListener('click',function(){\n startBtn.disabled=true;plog('Opening shell\u2026\n');\n fetch(q+'/pty?'+tk,{method:'POST',headers:{'content-type':'application/json'},body:'{}'})\n .then(function(r){return r.ok?r.json():Promise.reject(r.status)})\n .then(function(info){openPtyWs(info.wsUrl)})\n .catch(function(s){plog('\u2716 could not open PTY ('+s+')\n');startBtn.disabled=false});\n });\n function openPtyWs(url){\n try{\n var ws=new WebSocket(url);\n ws.binaryType='arraybuffer';\n ws.onmessage=function(e){\n var data=e.data;\n if(data instanceof ArrayBuffer){data=new TextDecoder().decode(new Uint8Array(data))}\n plog(data);\n };\n ws.onclose=function(){plog('\n[shell closed]\n');startBtn.disabled=false};\n ws.onerror=function(){plog('\n\u2716 WebSocket error\n')};\n if(input){\n input.hidden=false;\n input.addEventListener('submit',function(e){\n e.preventDefault();\n var c=input.querySelector('input[name=cmd]');\n if(!c.value){return}\n ws.send(c.value+'\r');c.value='';\n });\n }\n }catch(_){plog('\n\u2716 WebSocket unavailable\n');startBtn.disabled=false}\n }\n }\n function wireGraphDrill(){\n var root=document.documentElement;\n if(root.getAttribute('data-drilldown')!=='1'){return}\n var token=root.getAttribute('data-token');\n if(!token){return}\n var drill=document.querySelector('.graph-drill');\n if(!drill){return}\n var gview=drill.closest('.screen');\n if(!gview){return}\n var log=drill.querySelector('.drilllog');\n var title=drill.querySelector('.drill-title');\n if(!log){return}\n var es=null;\n function append(cls,text){\n var line=document.createElement('div');\n line.className='tl '+cls;line.textContent=text;\n log.appendChild(line);log.scrollTop=log.scrollHeight;\n }\n function open(id){\n if(es){try{es.close()}catch(_){}}\n log.textContent='';drill.hidden=false;\n if(title){title.textContent='Conversation \u00B7 '+id}\n var tk='token='+encodeURIComponent(token);\n var base='/console/session/'+encodeURIComponent(id);\n fetch(base+'/messages?'+tk).then(function(r){return r.ok?r.json():Promise.reject(r.status)})\n .then(function(d){(d&&d.frames||[]).forEach(function(f){append(f.kind,f.text)})})\n .catch(function(s){append('error','\u2716 could not load conversation ('+s+')')});\n if('EventSource' in window){\n try{\n es=new EventSource(base+'/stream?'+tk);\n es.addEventListener('frame',function(e){try{var f=JSON.parse(e.data);append(f.kind,f.text)}catch(_){}}); \n es.onerror=function(){/* reconnects on its own */};\n }catch(_){/* ignore */}\n }\n }\n gview.addEventListener('click',function(e){\n var t=e.target;\n while(t&&t!==gview&&!(t.getAttribute&&t.getAttribute('data-session'))){t=t.parentNode}\n if(t&&t.getAttribute&&t.getAttribute('data-session')){open(t.getAttribute('data-session'))}\n });\n }\n var nav=document.querySelector('.nav');\n if(nav){\n nav.addEventListener('click',function(e){\n var t=e.target;\n while(t&&t!==nav&&!(t.getAttribute&&t.getAttribute('data-screen'))){t=t.parentNode}\n if(t&&t.getAttribute&&t.getAttribute('data-screen')){selectScreen(t.getAttribute('data-screen'))}\n });\n }\n var toggle=document.querySelector('[data-toggle-nav]');\n if(toggle){toggle.addEventListener('click',function(){document.body.classList.toggle('nav-open')})}\n var close=document.querySelector('[data-close-nav]');\n if(close){close.addEventListener('click',function(){document.body.classList.remove('nav-open')})}\n var saved='tree';\n try{saved=localStorage.getItem('openteam.screen')||'tree'}catch(e){}\n if(!selectScreen(saved)){selectScreen('tree')}\n wireGraphDrill();\n})();\n";
16
+ export declare const CONSOLE_CLIENT_JS = "\n(function(){\n var authTok='';\n try{\n var qp=new URLSearchParams(window.location.search).get('token');\n if(qp){authTok='?token='+encodeURIComponent(qp)}\n }catch(e){/* ignore */}\n function reloadIfChanged(prev){\n fetch('/api/state'+authTok).then(function(r){return r.json()}).then(function(s){\n if(s.generatedAt!==prev&&!configActive()&&!lifecycleActive()){location.reload()}\n }).catch(function(){});\n }\n var current=document.documentElement.getAttribute('data-generated')||'';\n if('EventSource' in window){\n try{\n var es=new EventSource('/events'+authTok);\n es.addEventListener('state',function(ev){\n try{\n var d=JSON.parse(ev.data||'{}');\n if(d.generatedAt&&d.generatedAt!==current&&!configActive()&&!lifecycleActive()){location.reload()}\n }catch(e){}\n });\n es.addEventListener('graph-append',function(ev){\n try{\n var d=JSON.parse(ev.data||'{}');\n document.dispatchEvent(new CustomEvent('lifecycle-append',{detail:{runID:d.runID,head:d.head}}));\n }catch(e){}\n });\n es.onerror=function(){/* fallback below */};\n }catch(e){/* ignore */}\n }\n var ms=parseInt(document.documentElement.getAttribute('data-refresh')||'2000',10);\n setInterval(function(){reloadIfChanged(current)},isNaN(ms)?2000:Math.max(250,ms));\n\n function configActive(){\n var s=document.getElementById('screen-config');\n return !!(s&&!s.hidden);\n }\n // Only the visible timeline owns incremental refresh. Other screens still\n // need state reloads; their navigation preserves the timeline URL selection.\n function lifecycleActive(){\n var mount=document.getElementById('lifecycle-timeline-mount');\n var screen=mount&&mount.closest('.screen');\n return !!(screen&&!screen.hidden);\n }\n function wireLogsScreen(screen){\n if(screen.__logsWired){return}\n screen.__logsWired=true;\n var buttons=screen.querySelectorAll('[data-session-target]');\n var cards=screen.querySelectorAll('[data-session-view]');\n function showSession(id){\n var matched=false;\n for(var i=0;i<buttons.length;i++){\n var on=buttons[i].getAttribute('data-session-target')===id;\n buttons[i].classList.toggle('sel',on);\n buttons[i].setAttribute('aria-selected',on?'true':'false');\n }\n for(var j=0;j<cards.length;j++){\n var show=cards[j].getAttribute('data-session-view')===id;\n cards[j].hidden=!show;\n if(show){matched=true;connectTerminal(cards[j],id)}\n }\n return matched;\n }\n for(var k=0;k<buttons.length;k++){\n buttons[k].addEventListener('click',function(e){\n var id=e.currentTarget.getAttribute('data-session-target');\n if(id){showSession(id)}\n });\n }\n if(buttons.length>0){\n showSession(buttons[0].getAttribute('data-session-target'));\n }\n }\n function selectScreen(name){\n var screens=document.querySelectorAll('.screen');\n var items=document.querySelectorAll('[data-screen]');\n var matched=false;\n var titleText='';\n var activeScreen=null;\n for(var i=0;i<screens.length;i++){\n var show=screens[i].id==='screen-'+name;\n screens[i].classList.toggle('active',show);\n screens[i].hidden=!show;\n if(show){matched=true;activeScreen=screens[i]}\n }\n if(!matched){return false}\n for(var j=0;j<items.length;j++){\n var on=items[j].getAttribute('data-screen')===name;\n if(on){\n items[j].setAttribute('aria-current','page');\n titleText=items[j].getAttribute('data-title')||'';\n }else{\n items[j].removeAttribute('aria-current');\n }\n }\n var title=document.getElementById('screen-title');\n if(title){title.textContent=titleText}\n if(name==='config'&&activeScreen){loadConfig(activeScreen)}\n if(name==='logs'&&activeScreen){wireLogsScreen(activeScreen)}\n try{localStorage.setItem('openteam.screen',name)}catch(e){}\n document.body.classList.remove('nav-open');\n return true;\n }\n function esc(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}\n // Config editor (W7-S09 / #193). The config values travel only over the\n // token-gated /api/config, never in this open page, so the browser fetches\n // the server-rendered form with the bearer token and injects it. The\n // applied/pending-restart summary is likewise server-rendered and injected\n // verbatim, so the P14 honesty is enforced server-side, not here.\n function loadConfig(view){\n var root=document.documentElement;\n if(root.getAttribute('data-config')!=='1'||view.__configWired){return}\n var mount=view.querySelector('[data-config-mount]');\n if(!mount){return}\n var token=root.getAttribute('data-token');\n if(!token){mount.innerHTML='<p class=\"muted\">Read-only: no console token present.</p>';return}\n view.__configWired=true;\n fetch('/api/config',{headers:{Authorization:'Bearer '+token}})\n .then(function(r){return r.json()})\n .then(function(d){\n mount.innerHTML=d.render||'<p class=\"config-err\">Could not load configuration.</p>';\n wireConfigForm(mount,token);\n })\n .catch(function(){view.__configWired=false;mount.innerHTML='<p class=\"config-err\">Could not load configuration.</p>'});\n }\n function wireConfigForm(mount,token){\n var form=mount.querySelector('[data-config-form]');\n if(!form){return}\n var out=form.querySelector('[data-config-result]');\n form.addEventListener('submit',function(e){\n e.preventDefault();\n var ta=form.querySelector('textarea[name=\"config\"]');\n var parsed;\n try{parsed=JSON.parse(ta.value)}catch(err){out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">Invalid JSON: '+esc(err.message||err)+'</p></div>';return}\n var btn=form.querySelector('.config-save');\n if(btn){btn.disabled=true}\n fetch('/api/config',{method:'POST',headers:{Authorization:'Bearer '+token,'content-type':'application/json'},body:JSON.stringify(parsed)})\n .then(function(r){return r.json().then(function(b){return{status:r.status,body:b}})})\n .then(function(res){\n if(btn){btn.disabled=false}\n if(res.status===200){out.innerHTML=res.body.render||''}\n else{out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">'+esc(res.body&&res.body.error?res.body.error:'Save failed.')+'</p></div>'}\n })\n .catch(function(){if(btn){btn.disabled=false}out.innerHTML='<div class=\"config-summary\"><p class=\"config-err\">Save failed.</p></div>'});\n });\n }\n function connectTerminal(view,id){\n if(view.__wired){return}\n var root=document.documentElement;\n var token=root.getAttribute('data-token');\n if(root.getAttribute('data-terminal')!=='1'||!token){return}\n var log=view.querySelector('.termlog');\n if(!log){return}\n view.__wired=true;\n function append(cls,text){\n var line=document.createElement('div');\n line.className='tl '+cls;line.textContent=text;\n log.appendChild(line);log.scrollTop=log.scrollHeight;\n }\n var q='/console/session/'+encodeURIComponent(id);\n var tk='token='+encodeURIComponent(token);\n if('EventSource' in window){\n try{\n var es=new EventSource(q+'/stream?'+tk);\n es.addEventListener('frame',function(e){try{var f=JSON.parse(e.data);append(f.kind,f.text)}catch(_){}}); \n es.onerror=function(){/* reconnects on its own */};\n }catch(_){/* ignore */}\n }\n var form=view.querySelector('form.terminput');\n if(form){\n form.addEventListener('submit',function(e){\n e.preventDefault();\n var inp=form.querySelector('input[name=text]');\n var text=inp.value;\n if(!text){return}\n inp.value='';append('input','\u203A '+text);\n fetch(q+'/input?'+tk,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({text:text})})\n .then(function(r){if(!r.ok){append('error','\u2716 send rejected ('+r.status+')')}})\n .catch(function(){append('error','\u2716 could not send')});\n });\n }\n connectPty(view,id,q,tk);\n }\n function connectPty(view,id,q,tk){\n var root=document.documentElement;\n if(root.getAttribute('data-pty')!=='1'){return}\n var pane=view.querySelector('.pty');\n if(!pane){return}\n var log=pane.querySelector('.ptylog');\n var startBtn=pane.querySelector('.pty-start');\n var input=pane.querySelector('form.ptyinput');\n function plog(text){\n var d=document.createElement('span');d.textContent=text;\n log.appendChild(d);log.scrollTop=log.scrollHeight;\n }\n if(!startBtn){return}\n startBtn.addEventListener('click',function(){\n startBtn.disabled=true;plog('Opening shell\u2026\\n');\n fetch(q+'/pty?'+tk,{method:'POST',headers:{'content-type':'application/json'},body:'{}'})\n .then(function(r){return r.ok?r.json():Promise.reject(r.status)})\n .then(function(info){openPtyWs(info.wsUrl)})\n .catch(function(s){plog('\u2716 could not open PTY ('+s+')\\n');startBtn.disabled=false});\n });\n function openPtyWs(url){\n try{\n var ws=new WebSocket(url);\n ws.binaryType='arraybuffer';\n ws.onmessage=function(e){\n var data=e.data;\n if(data instanceof ArrayBuffer){data=new TextDecoder().decode(new Uint8Array(data))}\n plog(data);\n };\n ws.onclose=function(){plog('\\n[shell closed]\\n');startBtn.disabled=false};\n ws.onerror=function(){plog('\\n\u2716 WebSocket error\\n')};\n if(input){\n input.hidden=false;\n input.addEventListener('submit',function(e){\n e.preventDefault();\n var c=input.querySelector('input[name=cmd]');\n if(!c.value){return}\n ws.send(c.value+'\\r');c.value='';\n });\n }\n }catch(_){plog('\\n\u2716 WebSocket unavailable\\n');startBtn.disabled=false}\n }\n }\n function wireGraphDrill(){\n var root=document.documentElement;\n if(root.getAttribute('data-drilldown')!=='1'){return}\n var token=root.getAttribute('data-token');\n if(!token){return}\n var drill=document.querySelector('.graph-drill');\n if(!drill){return}\n var gview=drill.closest('.screen');\n if(!gview){return}\n var log=drill.querySelector('.drilllog');\n var title=drill.querySelector('.drill-title');\n if(!log){return}\n var es=null;\n function append(cls,text){\n var line=document.createElement('div');\n line.className='tl '+cls;line.textContent=text;\n log.appendChild(line);log.scrollTop=log.scrollHeight;\n }\n function open(id){\n if(es){try{es.close()}catch(_){}}\n log.textContent='';drill.hidden=false;\n if(title){title.textContent='Conversation \u00B7 '+id}\n var tk='token='+encodeURIComponent(token);\n var base='/console/session/'+encodeURIComponent(id);\n fetch(base+'/messages?'+tk).then(function(r){return r.ok?r.json():Promise.reject(r.status)})\n .then(function(d){(d&&d.frames||[]).forEach(function(f){append(f.kind,f.text)})})\n .catch(function(s){append('error','\u2716 could not load conversation ('+s+')')});\n if('EventSource' in window){\n try{\n es=new EventSource(base+'/stream?'+tk);\n es.addEventListener('frame',function(e){try{var f=JSON.parse(e.data);append(f.kind,f.text)}catch(_){}}); \n es.onerror=function(){/* reconnects on its own */};\n }catch(_){/* ignore */}\n }\n }\n gview.addEventListener('click',function(e){\n var t=e.target;\n while(t&&t!==gview&&!(t.getAttribute&&t.getAttribute('data-session'))){t=t.parentNode}\n if(t&&t.getAttribute&&t.getAttribute('data-session')){open(t.getAttribute('data-session'))}\n });\n }\n var nav=document.querySelector('.nav');\n if(nav){\n nav.addEventListener('click',function(e){\n var t=e.target;\n while(t&&t!==nav&&!(t.getAttribute&&t.getAttribute('data-screen'))){t=t.parentNode}\n if(t&&t.getAttribute&&t.getAttribute('data-screen')){selectScreen(t.getAttribute('data-screen'))}\n });\n }\n var toggle=document.querySelector('[data-toggle-nav]');\n if(toggle){toggle.addEventListener('click',function(){document.body.classList.toggle('nav-open')})}\n var close=document.querySelector('[data-close-nav]');\n if(close){close.addEventListener('click',function(){document.body.classList.remove('nav-open')})}\n var saved='tree';\n try{saved=localStorage.getItem('openteam.screen')||'tree'}catch(e){}\n if(!selectScreen(saved)){selectScreen('tree')}\n wireGraphDrill();\n wireLifecycleTimeline();\n})();\n";
17
+ /**
18
+ * Styles for the lifecycle history timeline surface. Uses `var(--cp-*)` from
19
+ * the Clawpilot theme — injected only when lifecycle history is enabled.
20
+ * Theme detection (prefers-color-scheme / ?scoutTheme) is bootstrapped by
21
+ * LIFECYCLE_THEME_BOOT inserted once into the HTML <head>.
22
+ */
23
+ export declare const LIFECYCLE_STYLE = "\n:root {\n color-scheme: light;\n --cp-bg: #f7f4ef;\n --cp-bg-elevated: #fcfbf8;\n --cp-surface: #ffffff;\n --cp-surface-soft: #f5f5f5;\n --cp-border: #dedede;\n --cp-border-strong: #919191;\n --cp-text: #242424;\n --cp-text-muted: #5c5c5c;\n --cp-text-soft: #6f6f6f;\n --cp-accent: #b11f4b;\n --cp-accent-hover: #9a1a41;\n --cp-accent-soft: rgba(177, 31, 75, 0.08);\n --cp-accent-fg: #ffffff;\n --cp-success: #16a34a;\n --cp-danger: #dc2626;\n --cp-warning: #f59e0b;\n --cp-link: #0078d4;\n --cp-shadow: 0 18px 48px rgba(0, 0, 0, 0.12);\n --cp-overlay: rgba(255, 255, 255, 0.8);\n --cp-panel: rgba(255, 255, 255, 0.86);\n --cp-panel-strong: rgba(255, 255, 255, 0.96);\n --cp-sheen: rgba(255, 255, 255, 0.55);\n --cp-highlight: rgba(177, 31, 75, 0.12);\n --cp-card-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.14);\n}\nhtml[data-theme=\"dark\"] {\n color-scheme: dark;\n --cp-bg: #3d3b3a;\n --cp-bg-elevated: #343231;\n --cp-surface: #292929;\n --cp-surface-soft: #2e2e2e;\n --cp-border: #474747;\n --cp-border-strong: #5f5f5f;\n --cp-text: #dedede;\n --cp-text-muted: #919191;\n --cp-text-soft: #b0b0b0;\n --cp-accent: #fd8ea1;\n --cp-accent-hover: #fb7b91;\n --cp-accent-soft: rgba(253, 142, 161, 0.14);\n --cp-accent-fg: #1a1a1a;\n --cp-success: #4ade80;\n --cp-danger: #f87171;\n --cp-warning: #fbbf24;\n --cp-link: #4da6ff;\n --cp-shadow: 0 18px 48px rgba(0, 0, 0, 0.32);\n --cp-overlay: rgba(41, 41, 41, 0.88);\n --cp-panel: rgba(41, 41, 41, 0.72);\n --cp-panel-strong: rgba(41, 41, 41, 0.96);\n --cp-sheen: rgba(255, 255, 255, 0.04);\n --cp-highlight: rgba(253, 142, 161, 0.12);\n --cp-card-shadow: 0 0 2px rgba(0, 0, 0, 0.32), 0 1px 2px rgba(0, 0, 0, 0.36);\n}\n/* Clawpilot lifecycle hierarchy \u2014 scoped, no repaint of other Console screens. */\n.lifecycle-primary{background:var(--cp-bg-elevated);border-color:var(--cp-border)}\n.lc-host{box-sizing:border-box;color:var(--cp-text);font-family:\"Segoe UI\",Aptos,Calibri,-apple-system,BlinkMacSystemFont,sans-serif}\n.lc-host *{box-sizing:border-box}\n.lc-panel-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:16px}\n.lc-panel-head h3{margin:2px 0 0;color:var(--cp-text);font-size:18px}\n.lc-eyebrow{color:var(--cp-accent);font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase}\n.lc-cursor-feedback{display:flex;flex-direction:column;align-items:flex-end;gap:3px;min-width:180px;color:var(--cp-text-muted)}\n.lc-cursor-count{font-family:Consolas,\"Courier New\",Courier,monospace;font-size:12px;font-weight:700;color:var(--cp-text)}\n.lc-cursor-time{font-family:Consolas,\"Courier New\",Courier,monospace;font-size:10px}\n.lc-controls{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:12px}\n.lc-run-select{min-width:180px;max-width:300px;padding:7px 28px 7px 10px;border:1px solid var(--cp-border);border-radius:.625rem;background:var(--cp-surface);color:var(--cp-text);font:inherit;font-size:12px}\n.lc-live-btn{display:inline-flex;align-items:center;gap:6px;padding:7px 12px;border:1px solid var(--cp-border-strong);border-radius:.625rem;background:var(--cp-surface);color:var(--cp-text);font:600 12px inherit;cursor:pointer}\n.lc-live-btn.active{border-color:var(--cp-accent);background:var(--cp-accent);color:var(--cp-accent-fg)}\n.lc-live-btn:hover:not(:disabled){border-color:var(--cp-accent);color:var(--cp-accent)}\n.lc-live-btn.active:hover:not(:disabled){background:var(--cp-accent-hover);color:var(--cp-accent-fg)}\n.lc-live-btn.paused{border-color:var(--cp-accent);color:var(--cp-accent)}\n.lc-live-btn:disabled{opacity:.45;cursor:not-allowed}\n.lc-live-dot{width:7px;height:7px;border-radius:50%;background:var(--cp-text-muted)}\n.lc-live-btn.active .lc-live-dot{background:var(--cp-accent-fg)}\n.lc-activity{display:inline-flex;align-items:center;gap:5px;padding:5px 9px;border:1px solid var(--cp-border);border-radius:999px;background:var(--cp-surface);color:var(--cp-text-muted);font-size:11px}\n.lc-activity-dot{width:6px;height:6px;border-radius:50%;background:var(--cp-text-muted)}\n.lc-activity.active{border-color:var(--cp-success);color:var(--cp-success)}\n.lc-activity.active .lc-activity-dot{background:var(--cp-success);animation:lc-pulse 1.8s infinite}\n.lc-activity.unknown{border-color:var(--cp-warning);color:var(--cp-warning)}\n.lc-activity.unknown .lc-activity-dot{background:var(--cp-warning)}\n.lc-activity.terminal{border-color:var(--cp-border-strong);color:var(--cp-text-muted)}\n@keyframes lc-pulse{0%,100%{opacity:1}50%{opacity:.35}}\n.lc-incoming-badge{padding:4px 8px;border-radius:999px;background:var(--cp-accent-soft);color:var(--cp-accent);font-size:11px;font-weight:600}\n.lc-slider-row{display:flex;align-items:center;gap:10px;margin:8px 0 14px}\n.lc-slider{flex:1;min-width:120px;accent-color:var(--cp-accent)}\n.lc-slider:disabled{opacity:.4}\n.lc-counts{font-family:Consolas,\"Courier New\",Courier,monospace;font-size:11px;color:var(--cp-text-muted);white-space:nowrap}\n.lc-tree-mount{min-height:80px;max-height:min(70vh,760px);padding:4px 4px 16px;overflow:auto}\n.lc-empty,.lc-error,.lc-legacy-note,.lc-partial-note{padding:12px 14px;border:1px solid var(--cp-border);border-radius:.625rem;background:var(--cp-surface-soft);color:var(--cp-text-muted);font-size:12px}\n.lc-error{border-color:var(--cp-danger);color:var(--cp-danger);background:var(--cp-surface)}\n.lc-legacy-note,.lc-partial-note{border-color:var(--cp-warning);color:var(--cp-text);margin-bottom:10px}\n.lct-tree{min-width:42rem;padding:4px}\n.lct-operation{position:relative;display:block;min-width:38rem;margin:0 0 14px}\n.lct-operation-card{position:relative;z-index:1;padding:14px;border:1px solid var(--cp-border);border-left:4px solid var(--cp-accent);border-radius:16px;background:var(--cp-surface);box-shadow:var(--cp-card-shadow)}\n.lct-operation[data-op-state=\"succeeded\"]>.lct-operation-card{border-left-color:var(--cp-success)}\n.lct-operation[data-op-state=\"failed\"]>.lct-operation-card,.lct-operation[data-op-state=\"cancelled\"]>.lct-operation-card{border-left-color:var(--cp-danger)}\n.lct-operation-head,.lct-attempt-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}\n.lct-operation-label{display:block;margin-bottom:3px;color:var(--cp-text-muted);font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase}\n.lct-operation-id{display:block;max-width:48rem;overflow:hidden;color:var(--cp-text);font-size:13px;text-overflow:ellipsis;white-space:nowrap}\n.lct-state{display:inline-flex;flex:none;padding:3px 8px;border:1px solid var(--cp-border-strong);border-radius:999px;background:var(--cp-surface-soft);color:var(--cp-text);font-size:10px;font-weight:700}\n.lct-state[data-state=\"succeeded\"]{border-color:var(--cp-success);color:var(--cp-success)}\n.lct-state[data-state=\"failed\"],.lct-state[data-state=\"cancelled\"]{border-color:var(--cp-danger);color:var(--cp-danger)}\n.lct-state[data-state=\"running\"],.lct-state[data-state=\"queued\"],.lct-state[data-state=\"selected\"]{border-color:var(--cp-accent);color:var(--cp-accent)}\n.lct-operation-meta,.lct-attempt-meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px;margin:12px 0 0}\n.lct-meta-item{min-width:0}\n.lct-meta-item dt{margin:0 0 2px;color:var(--cp-text-muted);font-size:10px}\n.lct-meta-item dd{margin:0;overflow-wrap:anywhere;color:var(--cp-text);font-size:11px}\n.lct-dependencies,.lct-parent-reference{display:flex;align-items:flex-start;gap:8px;margin-top:12px;padding:9px 10px;border-left:3px solid var(--cp-warning);border-radius:.625rem;background:var(--cp-surface-soft);font-size:11px}\n.lct-relation-label,.lct-parent-reference>span:first-child{flex:none;color:var(--cp-text-muted);font-weight:700}\n.lct-dependencies ul{display:flex;flex-wrap:wrap;gap:6px;margin:0;padding:0;list-style:none}\n.lct-dependencies li{padding:2px 6px;border:1px dashed var(--cp-border-strong);border-radius:.625rem;background:var(--cp-surface)}\n.lct-missing-reference{color:var(--cp-danger);font-weight:700}\n.lct-attempts{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:10px;margin-top:14px}\n.lct-attempt{min-width:0;padding:11px;border:1px solid var(--cp-border);border-radius:.625rem;background:var(--cp-surface-soft)}\n.lct-attempt-head strong{font-size:12px}\n.lct-times{display:flex;flex-wrap:wrap;gap:6px 12px;margin-top:10px}\n.lct-time-item{display:flex;gap:5px;color:var(--cp-text-muted);font-size:10px}\n.lct-time-item time{font-family:Consolas,\"Courier New\",Courier,monospace;color:var(--cp-text-soft)}\n.lct-failure{display:flex;flex-wrap:wrap;gap:6px 10px;margin-top:10px;padding:8px;border:1px solid var(--cp-danger);border-radius:.625rem;background:var(--cp-surface);color:var(--cp-danger);font-size:10px}\n.lct-failure-label{font-weight:700}\n.lct-model,.lct-session,.lct-session-empty{margin-top:10px;padding:9px 10px;border-left:3px solid var(--cp-accent);border-radius:.625rem;background:var(--cp-surface);font-size:10px}\n.lct-model,.lct-session{display:flex;flex-wrap:wrap;gap:5px 8px;align-items:center}\n.lct-model>span:first-child,.lct-session>span:first-child{color:var(--cp-accent);font-weight:700}\n.lct-parent-session{color:var(--cp-text-muted)}\n.lct-session-empty,.lct-no-attempts{color:var(--cp-text-muted)}\n.lct-operation-children{position:relative;margin:14px 0 0 24px;padding-left:24px;border-left:2px solid var(--cp-border-strong)}\n.lct-operation-children>.lct-operation::before{position:absolute;top:30px;left:-24px;width:24px;border-top:2px solid var(--cp-border-strong);content:\"\"}\n.lct-operation-children>.lct-operation:last-child::after{position:absolute;top:32px;bottom:-15px;left:-26px;width:4px;background:var(--cp-bg-elevated);content:\"\"}\n.lct-unlinked{margin-top:18px;padding:12px;border:1px dashed var(--cp-warning);border-radius:16px;background:var(--cp-surface-soft)}\n.lct-unlinked h4{margin:0;color:var(--cp-warning)}\n.lct-unlinked p{margin:4px 0 12px;color:var(--cp-text-muted);font-size:11px}\n.lct-root-missing{margin-bottom:12px;color:var(--cp-danger);font-size:12px}\n.lct-route-local{color:var(--cp-link)}.lct-route-frontier{color:var(--cp-warning)}\n.lc-graph-supplement{margin-top:18px;border-top:1px solid var(--cp-border);padding-top:14px}\n.lc-graph-supplement summary{cursor:pointer;color:var(--cp-link);font-size:12px}\n.lc-graph-supplement-body{margin-top:12px}\n@media(max-width:700px){\n .lc-panel-head{flex-direction:column}\n .lc-cursor-feedback{align-items:flex-start;min-width:0}\n .lc-controls{align-items:stretch}\n .lc-run-select{max-width:none;flex:1}\n .lct-tree{min-width:34rem}\n .lct-operation{min-width:31rem}\n}\n";
24
+ /**
25
+ * Theme detection boot fragment — inserted once per page before lifecycle JS.
26
+ * Uses the Clawpilot `?scoutTheme` param + `prefers-color-scheme` fallback.
27
+ * Pure, side-effect-limited: only sets `data-theme` on the root element.
28
+ */
29
+ export declare const LIFECYCLE_THEME_BOOT = "\n(() => {\n const param = new URLSearchParams(window.location.search).get(\"scoutTheme\");\n const theme =\n param || (window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\");\n document.documentElement.setAttribute(\"data-theme\", theme);\n})();\n";
30
+ /**
31
+ * Lifecycle timeline client JS. Wired by `wireLifecycleTimeline()` (called
32
+ * from CONSOLE_CLIENT_JS after the console initialisation). No inline
33
+ * user-facing message strings — labels come from `data-*` attributes set
34
+ * server-side. No dynamic `innerHTML` from user data; escaping is done on
35
+ * the server side.
36
+ */
37
+ export declare const LIFECYCLE_CLIENT_JS = "\nfunction wireLifecycleTimeline(){\n var mount=document.getElementById('lifecycle-timeline-mount');\n if(!mount){return}\n var authTok='';\n try{var qp=new URLSearchParams(window.location.search).get('token');if(qp){authTok='?token='+encodeURIComponent(qp)}}catch(e){}\n\n var runSelect=mount.querySelector('[data-lifecycle-run-select]');\n var liveBtn=mount.querySelector('[data-lifecycle-live-btn]');\n var slider=mount.querySelector('[data-lifecycle-slider]');\n var treeMountEl=mount.querySelector('[data-lifecycle-tree-mount]');\n var countsEl=mount.querySelector('[data-lifecycle-counts]');\n var activityEl=mount.querySelector('[data-lifecycle-activity]');\n var incomingEl=mount.querySelector('[data-lifecycle-incoming]');\n var cursorCountEl=mount.querySelector('[data-lifecycle-cursor-count]');\n var cursorTimeEl=mount.querySelector('[data-lifecycle-cursor-time]');\n var screenEl=mount.closest('.screen');\n var screenHeadingEl=screenEl&&screenEl.querySelector('.screen-head h2');\n var screenDescriptionEl=screenEl&&screenEl.querySelector('.screen-head p');\n\n // scrubInProgress / sliderWired: gesture and wiring state shared by\n // wireSlider() \u2014 declared here so ensureViewControls() can call wireSlider()\n // after dynamically creating slider during an empty\u2192view promotion.\n var scrubInProgress=false;\n var sliderWired=false;\n\n var state={\n explicitRun:urlRun(),\n runID:mount.getAttribute('data-lifecycle-run')||null,\n cursor:urlCursor(),\n head:Number(mount.getAttribute('data-lifecycle-head'))||0,\n followLive:urlCursor()===null,\n generation:0,\n request:null,\n pending:false,\n stopped:false,\n lastSseHead:new Map()\n };\n var projectionKey='';\n\n function urlCursor(){\n try{\n var values=new URLSearchParams(window.location.search).getAll('cursor');\n if(values.length>1){return 'invalid'}\n return values.length?values[0]:null;\n }catch(e){return null}\n }\n function urlRun(){\n try{return new URLSearchParams(window.location.search).get('run')}catch(e){return null}\n }\n\n // buildUrl: compute the target URL string without touching history.\n function buildUrl(runID,cursor){\n try{\n var sp=new URLSearchParams(window.location.search);\n if(runID){sp.set('run',runID)}else{sp.delete('run')}\n if(cursor!==null&&cursor!==undefined){sp.set('cursor',String(cursor))}else{sp.delete('cursor')}\n var qs=sp.toString();\n return qs?('?'+qs):window.location.pathname;\n }catch(e){return window.location.href}\n }\n // replaceUrl: mid-drag / intermediate updates \u2014 no history entry.\n function replaceUrl(runID,cursor){\n try{history.replaceState(null,'',buildUrl(runID,cursor));}catch(e){}\n }\n // pushUrl: committed navigation \u2014 creates a traversable history entry.\n function pushUrl(runID,cursor){\n try{history.pushState(null,'',buildUrl(runID,cursor));}catch(e){}\n }\n\n function buildApiUrl(runID,cursor){\n var u='/api/graph'+authTok;\n var sep=authTok?'&':'?';\n if(runID!==null&&runID!==undefined){u+=sep+'run='+encodeURIComponent(runID);sep='&'}\n if(cursor!==null&&cursor!==undefined){u+=sep+'cursor='+encodeURIComponent(String(cursor))}\n return u;\n }\n\n function cancelRequest(){\n var request=state.request;\n state.request=null;\n if(request){clearTimeout(request.timeout);request.controller.abort()}\n }\n\n // Background invalidations share one flight and one pending bit. Only user\n // navigation advances the epoch; a busy stream cannot starve valid replies.\n function fetchHistory(){\n if(state.stopped){return}\n if(state.request){state.pending=true;return}\n state.pending=false;\n var cursor=state.followLive?null:state.cursor;\n var runID=state.explicitRun;\n if(runID===null&&!state.followLive){runID=state.runID}\n var request={generation:state.generation,controller:new AbortController(),timeout:null};\n state.request=request;\n function current(){return !state.stopped&&state.request===request&&request.generation===state.generation}\n function finish(){\n if(!current()){return}\n clearTimeout(request.timeout);\n state.request=null;\n if(state.pending){fetchHistory()}\n }\n request.timeout=setTimeout(function(){\n if(!current()){return}\n request.controller.abort();\n showError();\n finish();\n },15000);\n fetch(buildApiUrl(runID,cursor),{signal:request.controller.signal}).then(function(r){return r.json()}).then(function(d){\n if(!current()){return}\n handleResponse(d,cursor);\n finish();\n }).catch(function(){\n if(!current()){return}\n showError();\n finish();\n });\n }\n\n function navigateFromUrl(initial){\n state.generation++;\n cancelRequest();\n state.pending=false;\n scrubInProgress=false;\n state.explicitRun=urlRun();\n state.cursor=urlCursor();\n state.followLive=state.cursor===null;\n state.runID=state.explicitRun!==null?state.explicitRun:initial&&!state.followLive?mount.getAttribute('data-lifecycle-run'):null;\n state.head=0;\n fetchHistory();\n }\n\n function handleResponse(d,requestedCursor){\n if(!d||d.version!==1){showError();return}\n if(d.kind==='error'){showApiError(d.error);return}\n if(d.kind==='disabled'){showDisabled(d);return}\n if(d.kind==='empty'){showEmpty();return}\n if(d.kind==='legacy'){renderLegacy(d);return}\n if(d.kind==='view'){renderView(d,requestedCursor);return}\n showError();\n }\n\n // wireSlider: attach input/change listeners once (guarded by sliderWired).\n function wireSlider(){\n if(sliderWired||!slider){return}\n sliderWired=true;\n slider.addEventListener('input',function(){\n var c=parseInt(slider.value,10);\n if(!scrubInProgress){\n history.pushState(null,'',window.location.href);\n scrubInProgress=true;\n }\n replaceUrl(state.runID,c);\n navigateFromUrl(false);\n scrubInProgress=true;\n });\n slider.addEventListener('change',function(){\n var c=parseInt(slider.value,10);\n replaceUrl(state.runID,c);\n scrubInProgress=false;\n });\n }\n\n // ensureViewControls: promote the empty SSR shell to a full view shell when\n // the first run data arrives. SSR empty only renders runSelect+liveBtn; all\n // other controls (activity, incoming, slider, treeMount) are missing. Build\n // and append them so renderView/renderLegacy can update them normally.\n function ensureViewControls(){\n if(slider!==null){return} // already promoted or SSR was full view/legacy\n // Remove placeholder status element (lc-empty or lc-legacy-note).\n var placeholder=mount.querySelector('.lc-empty,.lc-legacy-note');\n if(placeholder){mount.removeChild(placeholder)}\n // Append activity badge + incoming badge to the controls div.\n var controlsDiv=mount.querySelector('.lc-controls');\n if(controlsDiv){\n var actSpan=document.createElement('span');\n actSpan.className='lc-activity unknown';\n actSpan.setAttribute('data-lifecycle-activity','writer-unknown');\n actSpan.setAttribute('aria-live','polite');\n var actDot=document.createElement('span');actDot.className='lc-activity-dot';actDot.setAttribute('aria-hidden','true');\n var actLbl=document.createElement('span');actLbl.setAttribute('data-lc-activity-label','');\n actSpan.appendChild(actDot);actSpan.appendChild(actLbl);\n controlsDiv.appendChild(actSpan);\n activityEl=actSpan;\n var incSpan=document.createElement('span');\n incSpan.className='lc-incoming-badge';\n incSpan.setAttribute('data-lifecycle-incoming','');\n incSpan.hidden=true;\n controlsDiv.appendChild(incSpan);\n incomingEl=incSpan;\n }\n // Build slider row: <div class=\"lc-slider-row\"><input ...><span data-lifecycle-counts>\n var sliderRow=document.createElement('div');sliderRow.className='lc-slider-row';\n var inp=document.createElement('input');\n inp.type='range';inp.className='lc-slider';\n inp.setAttribute('data-lifecycle-slider','');\n inp.min='0';inp.max='0';inp.value='0';\n inp.setAttribute('aria-label',mount.getAttribute('data-msg-slider-aria')||'Timeline cursor');\n inp.setAttribute('aria-valuenow','0');inp.setAttribute('aria-valuemax','0');\n inp.disabled=true;\n var cntSpan=document.createElement('span');\n cntSpan.className='lc-counts';\n cntSpan.setAttribute('data-lifecycle-counts','');\n var evtLabel=mount.getAttribute('data-msg-events')||'{n} events';\n cntSpan.textContent=evtLabel.replace('{n}','0');\n sliderRow.appendChild(inp);sliderRow.appendChild(cntSpan);\n mount.appendChild(sliderRow);\n slider=inp;countsEl=cntSpan;\n // Build tree mount.\n var tm=document.createElement('div');tm.className='lc-tree-mount';\n tm.setAttribute('data-lifecycle-tree-mount','');\n mount.appendChild(tm);\n treeMountEl=tm;\n // Wire slider now that the element exists.\n wireSlider();\n }\n\n function message(name){\n return mount.getAttribute('data-msg-'+name)||'';\n }\n\n function fillTemplate(template,values){\n var result=template;\n Object.keys(values).forEach(function(key){\n result=result.split('{'+key+'}').join(String(values[key]));\n });\n return result;\n }\n\n function updateCursorFeedback(proj){\n if(cursorCountEl){\n if(!proj){\n cursorCountEl.textContent='';\n }else{\n var countTemplate=message(proj.head===1?'cursor-count-one':'cursor-count');\n cursorCountEl.textContent=fillTemplate(countTemplate,{cursor:proj.cursor,head:proj.head});\n }\n }\n if(cursorTimeEl){\n if(!proj||proj.lastEventAt===null||proj.lastEventAt===undefined){\n cursorTimeEl.removeAttribute('datetime');\n cursorTimeEl.textContent=message('no-event-time');\n }else{\n var iso=new Date(proj.lastEventAt).toISOString();\n cursorTimeEl.setAttribute('datetime',iso);\n cursorTimeEl.textContent=message('latest-event')+': '+iso;\n }\n }\n }\n\n function updateScreenCopy(kind,followLive,activity){\n var headingKey='screen-heading';\n var descriptionKey='screen-description';\n if(kind==='legacy'){\n headingKey='activity-legacy';\n descriptionKey='legacy-note';\n }else if(kind==='unavailable'){\n descriptionKey='screen-description-unavailable';\n }else if(kind==='view'&&!followLive){\n headingKey='screen-heading-historical';\n descriptionKey='screen-description-historical';\n }else if(kind==='view'&&activity&&activity.kind==='terminal'){\n headingKey='screen-heading-completed';\n descriptionKey='screen-description-completed';\n }else if(kind==='view'&&activity&&activity.kind==='writer-active'){\n headingKey='screen-heading-live';\n descriptionKey='screen-description-live';\n }\n if(screenHeadingEl){screenHeadingEl.textContent=message(headingKey)}\n if(screenDescriptionEl){screenDescriptionEl.textContent=message(descriptionKey)}\n }\n\n function updateFollowControl(followLive,activity){\n if(!liveBtn){return}\n var writerActive=followLive&&activity&&activity.kind==='writer-active';\n var labelKey=!followLive?'return-live':activity&&activity.kind==='terminal'?'latest':writerActive?'live':'following-head';\n var label=message(labelKey);\n liveBtn.classList.toggle('paused',!followLive);\n liveBtn.classList.toggle('active',writerActive);\n liveBtn.setAttribute('aria-pressed',followLive?'true':'false');\n liveBtn.setAttribute('aria-label',!followLive?message('return-live-aria'):writerActive?message('live-aria'):label);\n var labelEl=liveBtn.querySelector('[data-lc-live-label]');\n if(labelEl){labelEl.textContent=label}\n liveBtn.disabled=false;\n }\n\n function renderView(d,requestedCursor){\n ensureViewControls();\n state.runID=d.selection.runID;\n state.head=d.selection.head;\n state.cursor=d.selection.cursor;\n state.followLive=requestedCursor===null;\n if(!state.followLive&&state.explicitRun===null){\n state.explicitRun=state.runID;\n replaceUrl(state.runID,state.cursor);\n }\n\n // Update run selector.\n if(runSelect&&d.runs){\n syncRunOptions(d.runs,d.selection.runID);\n }\n\n // Update slider.\n if(slider){\n slider.max=String(state.head);\n slider.value=String(state.cursor);\n slider.disabled=(state.head===0);\n slider.setAttribute('aria-valuenow',String(state.cursor));\n slider.setAttribute('aria-valuemax',String(state.head));\n }\n\n // Update counts.\n if(countsEl){\n var countLabel=mount.getAttribute('data-msg-events')||'{n} events';\n countsEl.textContent=countLabel.replace('{n}',String(state.head));\n countsEl.hidden=false;\n }\n if(incomingEl){\n var inc=d.selection.incomingEvents||0;\n var incomingLabel=mount.getAttribute('data-msg-incoming')||'';\n incomingEl.textContent=inc>0?incomingLabel.replace('{n}',String(inc)):'';\n incomingEl.hidden=(inc===0);\n }\n\n updateFollowControl(state.followLive,d.activity);\n updateActivity(d.activity);\n updateScreenCopy('view',state.followLive,d.activity);\n updateCursorFeedback(d.projection);\n\n // Render tree projection.\n renderProjection(d.projection,d.recording);\n\n // Sync mount data attributes so QA selectors and popstate reads reflect\n // current state. These were set by SSR but never updated by client JS.\n mount.setAttribute('data-lifecycle-state', state.followLive?'live':'paused');\n mount.setAttribute('data-lifecycle-run', d.selection.runID||'');\n mount.setAttribute('data-lifecycle-head', String(state.head));\n }\n\n function syncRunOptions(runs,selectedID){\n if(!runSelect){return}\n var current=runSelect.value;\n // Rebuild options only if the set changed.\n var existingIds=Array.prototype.map.call(runSelect.options,function(o){return o.value});\n var newIds=runs.map(function(r){return r.runID});\n var changed=JSON.stringify(existingIds)!==JSON.stringify(newIds);\n if(changed){\n runSelect.innerHTML='';\n for(var i=0;i<runs.length;i++){\n var opt=document.createElement('option');\n opt.value=runs[i].runID;\n var label=runs[i].runID.slice(0,16)+(runs[i].source==='legacy-graph'?' (legacy)':'');\n opt.textContent=label;\n runSelect.appendChild(opt);\n }\n }\n runSelect.value=selectedID;\n }\n\n function renderLegacy(d){\n ensureViewControls();\n state.runID=d.selection.runID;\n state.head=0;\n if(runSelect&&d.runs){syncRunOptions(d.runs,d.selection.runID)}\n if(slider){\n slider.disabled=true;slider.value='0';slider.max='0';\n slider.setAttribute('aria-valuenow','0');slider.setAttribute('aria-valuemax','0');\n }\n if(incomingEl){incomingEl.textContent='';incomingEl.hidden=true}\n if(countsEl){countsEl.textContent='';countsEl.hidden=true}\n updateFollowControl(false,{kind:'legacy'});\n if(liveBtn){liveBtn.disabled=true}\n updateActivity({kind:'legacy'});\n updateScreenCopy('legacy',false,{kind:'legacy'});\n updateCursorFeedback(null);\n // Show legacy graph using existing graph render (the projection is GraphViewProjectionV1).\n if(treeMountEl){\n projectionKey='';\n var legacyNote=document.createElement('div');\n legacyNote.className='lc-legacy-note';\n legacyNote.setAttribute('role','status');\n var noteMsg=mount.getAttribute('data-msg-legacy-note')||'';\n legacyNote.textContent=noteMsg;\n treeMountEl.innerHTML='';\n treeMountEl.appendChild(legacyNote);\n // Render the legacy graph SVG if the projection has nodes.\n if(d.projection&&d.projection.nodes){\n renderGraphViewInline(d.projection,treeMountEl);\n }\n }\n mount.setAttribute('data-lifecycle-state','legacy');\n mount.setAttribute('data-lifecycle-run',d.selection.runID||'');\n mount.setAttribute('data-lifecycle-head','0');\n }\n\n function renderProjection(proj,recording){\n if(!proj||!treeMountEl){return}\n var degraded=recording&&recording.state==='degraded';\n var key=JSON.stringify([proj.runID,proj.cursor,proj.rootOperationID,proj.operations,degraded]);\n if(key===projectionKey){return}\n projectionKey=key;\n treeMountEl.textContent='';\n if(degraded){\n var note=makeElement('div','lc-partial-note',message('partial-tail'));\n note.setAttribute('role','status');\n treeMountEl.appendChild(note);\n }\n treeMountEl.appendChild(buildOperationTree(proj));\n }\n\n function makeElement(tag,className,text){\n var element=document.createElement(tag);\n if(className){element.className=className}\n if(text!==undefined&&text!==null){element.textContent=String(text)}\n return element;\n }\n\n function appendMeta(parent,label,value,className){\n var item=makeElement('div','lct-meta-item');\n item.appendChild(makeElement('dt','',label));\n var detail=makeElement('dd',className||'',value);\n item.appendChild(detail);\n parent.appendChild(item);\n }\n\n function stateBadge(stateValue){\n var badge=makeElement('span','lct-state',stateValue);\n badge.setAttribute('data-state',stateValue);\n badge.setAttribute('aria-label',message('state')+': '+stateValue);\n return badge;\n }\n\n function appendTime(parent,label,value){\n if(value===undefined||value===null){return}\n var iso=new Date(value).toISOString();\n var item=makeElement('div','lct-time-item');\n item.appendChild(makeElement('span','',label));\n var time=makeElement('time','',iso);\n time.setAttribute('datetime',iso);\n item.appendChild(time);\n parent.appendChild(item);\n }\n\n function appendFailure(parent,failure){\n if(!failure){return}\n var box=makeElement('div','lct-failure');\n box.appendChild(makeElement('span','lct-failure-label',message('failure')));\n box.appendChild(makeElement('code','',failure.class));\n if(failure.statusCode!==undefined){\n var status=makeElement('span','',message('status-code')+' ');\n status.appendChild(makeElement('code','',failure.statusCode));\n box.appendChild(status);\n }\n if(failure.retryable!==undefined){\n box.appendChild(makeElement('span','',message('retryable')+' '+message(failure.retryable?'yes':'no')));\n }\n parent.appendChild(box);\n }\n\n function appendSession(parent,attempt){\n if(!attempt.sessionID){\n parent.appendChild(makeElement('div','lct-session-empty',message('no-session')));\n return;\n }\n var session=makeElement('div','lct-session');\n session.setAttribute('data-lifecycle-session-id',attempt.sessionID);\n session.appendChild(makeElement('span','',message('session')));\n session.appendChild(makeElement('code','',attempt.sessionID));\n if(attempt.parentSessionID){\n var parentSession=makeElement('span','lct-parent-session',message('parent-session')+' ');\n parentSession.appendChild(makeElement('code','',attempt.parentSessionID));\n session.appendChild(parentSession);\n }\n parent.appendChild(session);\n }\n\n function buildAttempt(attempt){\n var article=makeElement('article','lct-attempt');\n article.setAttribute('data-lifecycle-attempt-id',attempt.attemptID);\n article.setAttribute('data-lifecycle-attempt-state',attempt.state);\n article.setAttribute('data-lifecycle-retry-index',String(attempt.retryIndex));\n var header=makeElement('header','lct-attempt-head');\n header.appendChild(makeElement('strong','',fillTemplate(message('attempt'),{n:Number(attempt.attempt)+1})));\n header.appendChild(stateBadge(attempt.state));\n article.appendChild(header);\n\n var metadata=makeElement('dl','lct-attempt-meta');\n if(!attempt.model){appendMeta(metadata,message('model'),message('no-model'),'muted')}\n appendMeta(metadata,message('route'),attempt.routeKind||message('no-route'),attempt.routeKind?'lct-route-'+attempt.routeKind:'muted');\n appendMeta(metadata,message('retry-label'),attempt.retryIndex,'mono');\n if(attempt.selectionCause){appendMeta(metadata,message('selection'),attempt.selectionCause,'mono')}\n if(attempt.runtimeID){appendMeta(metadata,message('runtime'),attempt.runtimeID,'mono')}\n article.appendChild(metadata);\n\n var times=makeElement('div','lct-times');\n appendTime(times,message('selected-at'),attempt.selectedAt);\n appendTime(times,message('queued-at'),attempt.queuedAt);\n appendTime(times,message('started-at'),attempt.startedAt);\n appendTime(times,message('terminal-at'),attempt.terminalAt);\n article.appendChild(times);\n appendFailure(article,attempt.failure);\n if(attempt.model){\n var identity=attempt.model.providerID+'/'+attempt.model.modelID;\n var model=makeElement('div','lct-model');\n model.setAttribute('data-lifecycle-model-id',identity);\n model.appendChild(makeElement('span','',message('model')));\n model.appendChild(makeElement('code','',identity));\n article.appendChild(model);\n }\n appendSession(article,attempt);\n return article;\n }\n\n function appendParentReference(card,op,known){\n if(!op.parentOperationID||known.has(op.parentOperationID)){return}\n var reference=makeElement('div','lct-parent-reference');\n reference.appendChild(makeElement('span','',message('parent-reference')));\n reference.appendChild(makeElement('code','',op.parentOperationID));\n reference.appendChild(makeElement('span','lct-missing-reference',message('missing-operation')));\n card.appendChild(reference);\n }\n\n function appendDependencies(card,op,known){\n var dependencyIDs=op.dependsOnOperationIDs||[];\n if(dependencyIDs.length===0){return}\n var box=makeElement('div','lct-dependencies');\n box.appendChild(makeElement('span','lct-relation-label',message('depends-on')));\n var list=makeElement('ul','');\n dependencyIDs.forEach(function(dependencyID){\n var item=makeElement('li','');\n item.setAttribute('data-lifecycle-dependency-from',dependencyID);\n item.appendChild(makeElement('code','',dependencyID));\n if(!known.has(dependencyID)){\n item.appendChild(document.createTextNode(' '));\n item.appendChild(makeElement('span','lct-missing-reference',message('missing-operation')));\n }\n list.appendChild(item);\n });\n box.appendChild(list);\n card.appendChild(box);\n }\n\n function buildOperation(op,known,depth){\n var article=makeElement('article','lct-operation');\n article.setAttribute('role','treeitem');\n article.setAttribute('aria-level',String(depth));\n article.setAttribute('data-lifecycle-operation-id',op.operationID);\n if(op.parentOperationID){article.setAttribute('data-lifecycle-parent-operation-id',op.parentOperationID)}\n article.setAttribute('data-lifecycle-operation-state',op.state);\n article.setAttribute('data-op-id',op.operationID);\n article.setAttribute('data-op-state',op.state);\n\n var card=makeElement('div','lct-operation-card');\n var header=makeElement('header','lct-operation-head');\n var identity=makeElement('div','');\n identity.appendChild(makeElement('span','lct-operation-label',message('operation')));\n identity.appendChild(makeElement('code','lct-operation-id',op.operationID));\n header.appendChild(identity);\n header.appendChild(stateBadge(op.state));\n card.appendChild(header);\n\n var metadata=makeElement('dl','lct-operation-meta');\n appendMeta(metadata,message('role'),op.roleID,'mono');\n appendMeta(metadata,message('kind'),op.kind,'mono');\n appendMeta(metadata,message('task'),op.taskID,'mono');\n if(op.agentID){appendMeta(metadata,message('agent'),op.agentID,'mono')}\n card.appendChild(metadata);\n appendParentReference(card,op,known);\n appendDependencies(card,op,known);\n\n var attempts=makeElement('section','lct-attempts');\n attempts.setAttribute('aria-label',message('attempts'));\n var attemptList=op.attempts||[];\n if(attemptList.length===0){\n attempts.appendChild(makeElement('div','lct-no-attempts',message('no-attempts')));\n }else{\n attemptList.forEach(function(attempt){attempts.appendChild(buildAttempt(attempt))});\n }\n card.appendChild(attempts);\n article.appendChild(card);\n return article;\n }\n\n function buildOperationTree(proj){\n var operations=Array.isArray(proj.operations)?proj.operations:[];\n if(operations.length===0){\n return makeElement('div','lc-empty',message('no-operations'));\n }\n var byID=new Map();\n operations.forEach(function(op){if(!byID.has(op.operationID)){byID.set(op.operationID,op)}});\n var uniqueOperations=Array.from(byID.values());\n var known=new Set(byID.keys());\n var childrenByParent=new Map();\n uniqueOperations.forEach(function(op){\n if(!op.parentOperationID||!known.has(op.parentOperationID)){return}\n var children=childrenByParent.get(op.parentOperationID)||[];\n children.push(op);\n childrenByParent.set(op.parentOperationID,children);\n });\n var visited=new Set();\n function buildBranch(op,depth){\n if(visited.has(op.operationID)){return null}\n visited.add(op.operationID);\n var article=buildOperation(op,known,depth);\n var children=childrenByParent.get(op.operationID)||[];\n var childNodes=[];\n children.forEach(function(child){\n var node=buildBranch(child,depth+1);\n if(node){childNodes.push(node)}\n });\n if(childNodes.length>0){\n var group=makeElement('div','lct-operation-children');\n group.setAttribute('role','group');\n childNodes.forEach(function(node){group.appendChild(node)});\n article.appendChild(group);\n }\n return article;\n }\n\n var tree=makeElement('div','lct-tree');\n tree.setAttribute('role','tree');\n tree.setAttribute('aria-label',message('tree-aria'));\n var root=byID.get(proj.rootOperationID);\n if(root){\n var rootNode=buildBranch(root,1);\n if(rootNode){tree.appendChild(rootNode)}\n }else{\n tree.appendChild(makeElement('div','lct-root-missing',message('root-missing')));\n }\n\n var unlinked=null;\n var unlinkedGroup=null;\n while(visited.size<uniqueOperations.length){\n var next=uniqueOperations.find(function(op){\n return !visited.has(op.operationID)&&(!op.parentOperationID||!known.has(op.parentOperationID)||visited.has(op.parentOperationID));\n })||uniqueOperations.find(function(op){return !visited.has(op.operationID)});\n if(!next){break}\n if(!unlinked){\n unlinked=makeElement('section','lct-unlinked');\n unlinked.appendChild(makeElement('h4','',message('unlinked')));\n unlinked.appendChild(makeElement('p','',message('unlinked-note')));\n unlinkedGroup=makeElement('div','');\n unlinkedGroup.setAttribute('role','group');\n unlinked.appendChild(unlinkedGroup);\n tree.appendChild(unlinked);\n }\n var unlinkedNode=buildBranch(next,1);\n if(unlinkedNode){unlinkedGroup.appendChild(unlinkedNode)}\n }\n return tree;\n }\n\n function renderGraphViewInline(proj,container){\n // Minimal DAG SVG for legacy projections (GraphViewProjectionV1).\n // Uses existing .graph-wrap / .gnode styles from GRAPH_STYLE.\n if(!proj.nodes||proj.nodes.length===0){return}\n var COL_W=220,ROW_H=96,NODE_W=180,NODE_H=64,PAD=20;\n var layer={};\n proj.nodes.forEach(function(n){layer[n.nodeID]=0});\n for(var pass=0;pass<proj.nodes.length;pass++){\n var changed=false;\n for(var e=0;e<(proj.edges||[]).length;e++){\n var edge=proj.edges[e];\n var from=(layer[edge.from]||0),to=(layer[edge.to]||0);\n if(from+1>to){layer[edge.to]=from+1;changed=true}\n }\n if(!changed){break}\n }\n var byLayer=[];\n proj.nodes.forEach(function(n){\n var l=layer[n.nodeID]||0;\n if(!byLayer[l]){byLayer[l]=[]}\n byLayer[l].push(n.nodeID);\n });\n var pos={};var maxL=0,maxR=0;\n byLayer.forEach(function(ids,l){\n if(l>maxL){maxL=l}if(ids.length>maxR){maxR=ids.length}\n ids.forEach(function(id,r){pos[id]={x:PAD+l*COL_W,y:PAD+r*ROW_H}});\n });\n var W=PAD*2+maxL*COL_W+NODE_W,H=PAD*2+Math.max(0,maxR-1)*ROW_H+NODE_H;\n var svgParts=['<svg class=\"graph\" viewBox=\"0 0 '+W+' '+H+'\" width=\"'+W+'\" height=\"'+H+'\" role=\"img\"><defs><marker id=\"ga2\" viewBox=\"0 0 8 8\" refX=\"7\" refY=\"4\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L8 4 L0 8 z\" fill=\"var(--cp-border-strong)\"></path></marker></defs>'];\n (proj.edges||[]).forEach(function(e){\n var a=pos[e.from],b=pos[e.to];\n if(!a||!b){return}\n svgParts.push('<line class=\"gedge\" x1=\"'+(a.x+NODE_W)+'\" y1=\"'+(a.y+NODE_H/2)+'\" x2=\"'+b.x+'\" y2=\"'+(b.y+NODE_H/2)+'\" marker-end=\"url(#ga2)\"></line>');\n });\n proj.nodes.forEach(function(n){\n var p=pos[n.nodeID];if(!p){return}\n function escape(value){return String(value).replace(/[&<>\"']/g,function(c){return{'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[c]||c})}\n var safe=escape(n.nodeID);\n var session=typeof n.sessionRef==='string'&&n.sessionRef?' data-session=\"'+escape(n.sessionRef)+'\"':'';\n svgParts.push('<g class=\"gnode state-'+escape(n.state)+'\" data-node=\"'+safe+'\"'+session+' transform=\"translate('+p.x+','+p.y+')\"><rect width=\"'+NODE_W+'\" height=\"'+NODE_H+'\"></rect><text class=\"gname\" x=\"10\" y=\"20\">'+safe+'</text><text class=\"gstate\" x=\"10\" y=\"40\">'+escape(n.state)+'</text></g>');\n });\n svgParts.push('</svg>');\n var wrap=document.createElement('div');wrap.className='graph-wrap';\n wrap.innerHTML=svgParts.join('');\n container.appendChild(wrap);\n }\n\n function updateActivity(activity){\n if(!activityEl){return}\n var kind=activity&&activity.kind?activity.kind:'writer-unknown';\n var cssKind=kind==='writer-active'?'active':kind==='writer-unknown'?'unknown':kind;\n var dot=activityEl.querySelector('.lc-activity-dot');\n activityEl.className='lc-activity '+cssKind;\n activityEl.setAttribute('data-lifecycle-activity',kind);\n var label=mount.getAttribute('data-msg-activity-'+kind)||kind;\n var textNode=activityEl.querySelector('[data-lc-activity-label]');\n if(textNode){textNode.textContent=label}\n if(dot){dot.setAttribute('aria-hidden','true')}\n }\n\n function showError(){\n projectionKey='';\n mount.setAttribute('data-lifecycle-state','error');\n updateScreenCopy('unavailable',false,null);\n updateCursorFeedback(null);\n if(liveBtn){liveBtn.disabled=true}\n if(slider){slider.disabled=true}\n if(treeMountEl){\n treeMountEl.innerHTML='';\n var div=document.createElement('div');div.className='lc-error';div.setAttribute('role','alert');\n div.textContent=mount.getAttribute('data-msg-error-loading')||'';\n treeMountEl.appendChild(div);\n }\n }\n\n function showApiError(err){\n projectionKey='';\n mount.setAttribute('data-lifecycle-state','error');\n updateScreenCopy('unavailable',false,null);\n updateCursorFeedback(null);\n if(liveBtn){liveBtn.disabled=true}\n if(slider){slider.disabled=true}\n if(!treeMountEl||!err){showError();return}\n var code=err.code||'';\n var msg=mount.getAttribute('data-msg-error-'+code)||mount.getAttribute('data-msg-error-loading')||'';\n treeMountEl.innerHTML='';\n var div=document.createElement('div');div.className='lc-error';div.setAttribute('role','alert');\n div.textContent=msg;\n treeMountEl.appendChild(div);\n }\n\n function showDisabled(d){\n projectionKey='';\n mount.setAttribute('data-lifecycle-state','disabled');\n updateScreenCopy('unavailable',false,null);\n updateCursorFeedback(null);\n if(liveBtn){liveBtn.disabled=true}\n if(slider){slider.disabled=true}\n var reason=d&&d.reason?d.reason:'history-disabled';\n var msg=mount.getAttribute('data-msg-disabled-'+reason)||'';\n if(treeMountEl){\n treeMountEl.innerHTML='';\n var div=document.createElement('div');div.className='lc-empty';div.setAttribute('role','status');\n div.textContent=msg;\n treeMountEl.appendChild(div);\n }\n }\n\n function showEmpty(){\n projectionKey='';\n mount.setAttribute('data-lifecycle-state','empty');\n updateScreenCopy('empty',false,null);\n updateCursorFeedback(null);\n if(liveBtn){liveBtn.disabled=true}\n if(slider){slider.disabled=true}\n var msg=mount.getAttribute('data-msg-no-runs')||'';\n if(treeMountEl){\n treeMountEl.innerHTML='';\n var div=document.createElement('div');div.className='lc-empty';div.setAttribute('role','status');\n div.textContent=msg;\n treeMountEl.appendChild(div);\n }\n }\n\n // --- Run selector change ---\n if(runSelect){\n runSelect.addEventListener('change',function(){\n var newRun=runSelect.value;\n pushUrl(newRun,null); // committed selection \u2192 traversable entry\n navigateFromUrl(false);\n });\n }\n\n // --- Slider scrub ---\n // Wire slider event listeners if slider was present in SSR (view/legacy state).\n // When SSR is empty, wireSlider() is deferred to ensureViewControls().\n wireSlider();\n\n // --- Live / Return to live ---\n if(liveBtn){\n liveBtn.addEventListener('click',function(){\n pushUrl(state.explicitRun,null); // return-to-live preserves automatic run selection\n navigateFromUrl(false);\n });\n }\n\n // --- SSE graph-append handler ---\n function onAppend(e){\n if(state.stopped){return}\n var detail=e.detail||{};\n var runID=detail.runID;var head=detail.head;\n if(typeof runID!=='string'||!runID||!Number.isSafeInteger(head)||head<0){return}\n if((state.explicitRun!==null||!state.followLive)&&runID!==state.runID){return}\n var known=Math.max(state.lastSseHead.get(runID)||0,runID===state.runID?state.head:0);\n if(head<=known){return}\n state.lastSseHead.set(runID,head);\n if(state.lastSseHead.size>64){state.lastSseHead.delete(state.lastSseHead.keys().next().value)}\n // Hints never change displayed head/incoming; the confirmed API selection\n // is authoritative, including while paused at zero or exactly at head.\n fetchHistory();\n }\n document.addEventListener('lifecycle-append',onAppend);\n\n // --- Browser back/forward ---\n window.addEventListener('popstate',function(){\n navigateFromUrl(false);\n });\n\n // --- Catch-up polling (SSE-absent / coalesced-event recovery) ---\n // Paused requests retain their exact prefix while refreshing head metadata.\n var lcRefreshMs=parseInt(document.documentElement.getAttribute('data-refresh')||'2000',10);\n if(isNaN(lcRefreshMs)||lcRefreshMs<500){lcRefreshMs=2000;}\n var pollTimer=setInterval(fetchHistory,lcRefreshMs);\n window.addEventListener('pagehide',function(){\n state.stopped=true;\n state.generation++;\n state.pending=false;\n cancelRequest();\n clearInterval(pollTimer);\n document.removeEventListener('lifecycle-append',onAppend);\n });\n window.addEventListener('pageshow',function(e){\n if(!e.persisted||!state.stopped){return}\n state.stopped=false;\n document.addEventListener('lifecycle-append',onAppend);\n pollTimer=setInterval(fetchHistory,lcRefreshMs);\n navigateFromUrl(false);\n });\n\n navigateFromUrl(true);\n}\n";
17
38
  //# sourceMappingURL=assets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/console/assets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,aAAa,upYA6BzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,klFA4CvB,CAAC;AAEF,eAAO,MAAM,iBAAiB,4vXA2Q7B,CAAC"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/console/assets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,aAAa,upYA6BzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,klFA4CvB,CAAC;AAEF,eAAO,MAAM,iBAAiB,qjZA8R7B,CAAC;AAMF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,w/UAiJ3B,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,gSAOhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,u6lCA20B/B,CAAC"}
@@ -38,6 +38,8 @@ export type ConfigWriteView = {
38
38
  readonly wroteBase: boolean;
39
39
  readonly wroteOverlay: boolean;
40
40
  };
41
+ /** Compact summary above the existing JSON editor; the JSON remains editable. */
42
+ export declare function renderExecutionPolicyOverview(config: unknown): string;
41
43
  /**
42
44
  * The pre-save reload legend, built from the read result's `reload` arrays. It
43
45
  * tells the operator, before they save, which keys apply live and which need a
@@ -71,11 +73,4 @@ export declare function renderConfigSaveSummary(write: ConfigWriteView): string;
71
73
  export declare function renderConfigEditorPanel(opts: {
72
74
  hasToken: boolean;
73
75
  }): string;
74
- /**
75
- * Legacy wrapper retained for callers/tests that exercise the standalone config
76
- * view shell. The main console now mounts the panel inside `#screen-config`.
77
- */
78
- export declare function renderConfigView(opts: {
79
- hasToken: boolean;
80
- }): string;
81
76
  //# sourceMappingURL=configView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configView.d.ts","sourceRoot":"","sources":["../../src/console/configView.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;QAC1C,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;KAC7C,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;KACjD,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,SAAS;QACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;KACvB,EAAE,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC,CAAC;AAQF;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAkBpE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CA0BnE;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAkCtE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAa3E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAMpE"}
1
+ {"version":3,"file":"configView.d.ts","sourceRoot":"","sources":["../../src/console/configView.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;QAC1C,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;KAC7C,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC;KACjD,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,SAAS;QACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;KACvB,EAAE,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;CAChC,CAAC;AAgCF,iFAAiF;AACjF,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CA+BrE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAkBpE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CA2BnE;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAkCtE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAa3E"}
@@ -1,4 +1,5 @@
1
1
  import type { GraphMode } from "../config/schema";
2
+ import type { LifecycleHistoryResponseV1 } from "../lifecycle/contracts";
2
3
  import type { GraphViewProjectionV1 } from "../telemetry/graphView";
3
4
  import type { ConsoleState } from "./types";
4
5
  export declare const GRAPH_EMPTY_REMEDIATION: "No graph run yet. The tree fills when openteam-orchestrate dispatches roles; ordinary chat does not create a graph run.";
@@ -58,6 +59,17 @@ export type RenderOptions = {
58
59
  configEditor?: {
59
60
  readonly hasToken: boolean;
60
61
  };
62
+ /**
63
+ * Lifecycle history timeline surface (#222). When provided, renders the
64
+ * timeline panel in the tree screen and injects the lifecycle CSS/JS.
65
+ * `response` is the current history view (or disabled/empty/etc.); may be
66
+ * `null` when the provider is wired but has not yet responded.
67
+ */
68
+ lifecycleView?: {
69
+ readonly response: LifecycleHistoryResponseV1 | null;
70
+ /** Run ID from the URL query (for initial state). */
71
+ readonly initialRunID?: string;
72
+ };
61
73
  };
62
74
  /**
63
75
  * Renderiza el console como un único HTML autocontenido (CSS + JS inline, sin
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/console/render.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQlD,OAAO,KAAK,EAGV,qBAAqB,EACtB,MAAM,wBAAwB,CAAC;AAKhC,OAAO,KAAK,EAGV,YAAY,EAIb,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,uBAAuB,EAClC,yHAAkI,CAAC;AASrI,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhD;AAwmBD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,qBAAqB,GAAG,IAAI,EACxC,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,MAAM,CA2BR;AAuOD,MAAM,MAAM,aAAa,GAAG;IAC1B,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;QAClD,sEAAsE;QACtE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;QACzB;;;WAGG;QACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;KAC7B,CAAC;IACF;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;CAC/C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CAmGR"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/console/render.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAEV,0BAA0B,EAK3B,MAAM,wBAAwB,CAAC;AAUhC,OAAO,KAAK,EAGV,qBAAqB,EACtB,MAAM,wBAAwB,CAAC;AAYhC,OAAO,KAAK,EAGV,YAAY,EAIb,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,uBAAuB,EAClC,yHAAkI,CAAC;AASrI,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhD;AA4mBD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,qBAAqB,GAAG,IAAI,EACxC,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,MAAM,CA2BR;AA67BD,MAAM,MAAM,aAAa,GAAG;IAC1B,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;QAClD,sEAAsE;QACtE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;QACzB;;;WAGG;QACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;KAC7B,CAAC;IACF;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9C;;;;;OAKG;IACH,aAAa,CAAC,EAAE;QACd,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,GAAG,IAAI,CAAC;QACrD,qDAAqD;QACrD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;CACH,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,aAAkB,GAC1B,MAAM,CA2GR"}
@@ -50,8 +50,8 @@ export type RouteView = {
50
50
  model: string;
51
51
  /** NUNCA el prompt. */
52
52
  promptHash: string;
53
- estimatedCostUSD: number;
54
- estimatedSavingsUSD: number;
53
+ estimatedCostUSD: number | null;
54
+ estimatedSavingsUSD: number | null;
55
55
  budgetAction: string;
56
56
  };
57
57
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/console/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/console/types.ts"],"names":[],"mappings":"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"}