@cleocode/core 2026.9.16 → 2026.9.17

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 (216) hide show
  1. package/dist/changesets/parser.d.ts.map +1 -1
  2. package/dist/changesets/parser.js +67 -0
  3. package/dist/changesets/parser.js.map +1 -1
  4. package/dist/crypto/credentials.d.ts +128 -26
  5. package/dist/crypto/credentials.d.ts.map +1 -1
  6. package/dist/crypto/credentials.js +183 -142
  7. package/dist/crypto/credentials.js.map +1 -1
  8. package/dist/docs/export-document.js +14705 -12949
  9. package/dist/docs/export-document.js.map +3 -3
  10. package/dist/doctor/index.d.ts +1 -1
  11. package/dist/doctor/index.d.ts.map +1 -1
  12. package/dist/doctor/index.js +1 -1
  13. package/dist/doctor/index.js.map +1 -1
  14. package/dist/doctor/nexus-schema-residency.d.ts +1 -1
  15. package/dist/doctor/nexus-schema-residency.d.ts.map +1 -1
  16. package/dist/doctor/nexus-schema-residency.js +1 -0
  17. package/dist/doctor/nexus-schema-residency.js.map +1 -1
  18. package/dist/doctor/project-identity.d.ts +124 -0
  19. package/dist/doctor/project-identity.d.ts.map +1 -0
  20. package/dist/doctor/project-identity.js +307 -0
  21. package/dist/doctor/project-identity.js.map +1 -0
  22. package/dist/doctor/superseded-store.d.ts +8 -0
  23. package/dist/doctor/superseded-store.d.ts.map +1 -1
  24. package/dist/doctor/superseded-store.js +48 -3
  25. package/dist/doctor/superseded-store.js.map +1 -1
  26. package/dist/init.d.ts +7 -0
  27. package/dist/init.d.ts.map +1 -1
  28. package/dist/init.js +17 -2
  29. package/dist/init.js.map +1 -1
  30. package/dist/internal.d.ts +5 -2
  31. package/dist/internal.d.ts.map +1 -1
  32. package/dist/internal.js +4 -2
  33. package/dist/internal.js.map +1 -1
  34. package/dist/llm/credentials-store.d.ts +10 -0
  35. package/dist/llm/credentials-store.d.ts.map +1 -1
  36. package/dist/llm/credentials-store.js +7 -1
  37. package/dist/llm/credentials-store.js.map +1 -1
  38. package/dist/llm/plugin-facade.js +13368 -1550
  39. package/dist/llm/plugin-facade.js.map +3 -3
  40. package/dist/nexus/analyze-orchestrator.d.ts +20 -3
  41. package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
  42. package/dist/nexus/analyze-orchestrator.js +159 -10
  43. package/dist/nexus/analyze-orchestrator.js.map +1 -1
  44. package/dist/nexus/assessment-store.d.ts +57 -0
  45. package/dist/nexus/assessment-store.d.ts.map +1 -0
  46. package/dist/nexus/assessment-store.js +73 -0
  47. package/dist/nexus/assessment-store.js.map +1 -0
  48. package/dist/nexus/freshness.d.ts +131 -0
  49. package/dist/nexus/freshness.d.ts.map +1 -0
  50. package/dist/nexus/freshness.js +391 -0
  51. package/dist/nexus/freshness.js.map +1 -0
  52. package/dist/nexus/graph-manifest.d.ts +88 -0
  53. package/dist/nexus/graph-manifest.d.ts.map +1 -0
  54. package/dist/nexus/graph-manifest.js +114 -0
  55. package/dist/nexus/graph-manifest.js.map +1 -0
  56. package/dist/nexus/knowledge.d.ts +21 -1
  57. package/dist/nexus/knowledge.d.ts.map +1 -1
  58. package/dist/nexus/knowledge.js +76 -37
  59. package/dist/nexus/knowledge.js.map +1 -1
  60. package/dist/nexus/path-map.d.ts +55 -0
  61. package/dist/nexus/path-map.d.ts.map +1 -0
  62. package/dist/nexus/path-map.js +87 -0
  63. package/dist/nexus/path-map.js.map +1 -0
  64. package/dist/nexus/projects-clean.d.ts +21 -28
  65. package/dist/nexus/projects-clean.d.ts.map +1 -1
  66. package/dist/nexus/projects-clean.js +168 -85
  67. package/dist/nexus/projects-clean.js.map +1 -1
  68. package/dist/nexus/query.d.ts.map +1 -1
  69. package/dist/nexus/query.js +3 -2
  70. package/dist/nexus/query.js.map +1 -1
  71. package/dist/nexus/registry-hygiene.d.ts +70 -0
  72. package/dist/nexus/registry-hygiene.d.ts.map +1 -0
  73. package/dist/nexus/registry-hygiene.js +113 -0
  74. package/dist/nexus/registry-hygiene.js.map +1 -0
  75. package/dist/nexus/registry.d.ts +2 -2
  76. package/dist/nexus/registry.d.ts.map +1 -1
  77. package/dist/nexus/registry.js +48 -12
  78. package/dist/nexus/registry.js.map +1 -1
  79. package/dist/paths.d.ts +26 -0
  80. package/dist/paths.d.ts.map +1 -1
  81. package/dist/paths.js +99 -6
  82. package/dist/paths.js.map +1 -1
  83. package/dist/render/nexus/graph/index.d.ts.map +1 -1
  84. package/dist/render/nexus/graph/index.js +8 -0
  85. package/dist/render/nexus/graph/index.js.map +1 -1
  86. package/dist/scaffold/ensure-config.d.ts +12 -3
  87. package/dist/scaffold/ensure-config.d.ts.map +1 -1
  88. package/dist/scaffold/ensure-config.js +61 -38
  89. package/dist/scaffold/ensure-config.js.map +1 -1
  90. package/dist/scaffold/project-identity.d.ts +136 -0
  91. package/dist/scaffold/project-identity.d.ts.map +1 -0
  92. package/dist/scaffold/project-identity.js +225 -0
  93. package/dist/scaffold/project-identity.js.map +1 -0
  94. package/dist/selfimprove/fix-gen.js +13319 -1556
  95. package/dist/selfimprove/fix-gen.js.map +3 -3
  96. package/dist/store/agent-api-key.d.ts +114 -0
  97. package/dist/store/agent-api-key.d.ts.map +1 -0
  98. package/dist/store/agent-api-key.js +136 -0
  99. package/dist/store/agent-api-key.js.map +1 -0
  100. package/dist/store/agent-registry-accessor.d.ts +4 -2
  101. package/dist/store/agent-registry-accessor.d.ts.map +1 -1
  102. package/dist/store/agent-registry-accessor.js +39 -89
  103. package/dist/store/agent-registry-accessor.js.map +1 -1
  104. package/dist/store/api-key-kdf.d.ts +7 -0
  105. package/dist/store/api-key-kdf.d.ts.map +1 -1
  106. package/dist/store/api-key-kdf.js +7 -0
  107. package/dist/store/api-key-kdf.js.map +1 -1
  108. package/dist/store/backup-crypto.d.ts +49 -0
  109. package/dist/store/backup-crypto.d.ts.map +1 -1
  110. package/dist/store/backup-crypto.js +154 -0
  111. package/dist/store/backup-crypto.js.map +1 -1
  112. package/dist/store/credential-transfer.d.ts +303 -0
  113. package/dist/store/credential-transfer.d.ts.map +1 -0
  114. package/dist/store/credential-transfer.js +774 -0
  115. package/dist/store/credential-transfer.js.map +1 -0
  116. package/dist/store/exodus/column-transforms.d.ts +79 -4
  117. package/dist/store/exodus/column-transforms.d.ts.map +1 -1
  118. package/dist/store/exodus/column-transforms.js +121 -4
  119. package/dist/store/exodus/column-transforms.js.map +1 -1
  120. package/dist/store/exodus/index.d.ts +1 -0
  121. package/dist/store/exodus/index.d.ts.map +1 -1
  122. package/dist/store/exodus/index.js +1 -0
  123. package/dist/store/exodus/index.js.map +1 -1
  124. package/dist/store/exodus/migrate.d.ts +17 -1
  125. package/dist/store/exodus/migrate.d.ts.map +1 -1
  126. package/dist/store/exodus/migrate.js +155 -33
  127. package/dist/store/exodus/migrate.js.map +1 -1
  128. package/dist/store/exodus/on-open.d.ts +14 -0
  129. package/dist/store/exodus/on-open.d.ts.map +1 -1
  130. package/dist/store/exodus/on-open.js +115 -6
  131. package/dist/store/exodus/on-open.js.map +1 -1
  132. package/dist/store/exodus/reconcile.d.ts +103 -0
  133. package/dist/store/exodus/reconcile.d.ts.map +1 -0
  134. package/dist/store/exodus/reconcile.js +728 -0
  135. package/dist/store/exodus/reconcile.js.map +1 -0
  136. package/dist/store/exodus/recovery.d.ts.map +1 -1
  137. package/dist/store/exodus/recovery.js +14 -2
  138. package/dist/store/exodus/recovery.js.map +1 -1
  139. package/dist/store/exodus/runtime-targets.d.ts +39 -0
  140. package/dist/store/exodus/runtime-targets.d.ts.map +1 -0
  141. package/dist/store/exodus/runtime-targets.js +63 -0
  142. package/dist/store/exodus/runtime-targets.js.map +1 -0
  143. package/dist/store/exodus/table-name-map.d.ts.map +1 -1
  144. package/dist/store/exodus/table-name-map.js +5 -0
  145. package/dist/store/exodus/table-name-map.js.map +1 -1
  146. package/dist/store/exodus/table-order.d.ts +35 -0
  147. package/dist/store/exodus/table-order.d.ts.map +1 -0
  148. package/dist/store/exodus/table-order.js +62 -0
  149. package/dist/store/exodus/table-order.js.map +1 -0
  150. package/dist/store/exodus/verify-migration.d.ts +4 -1
  151. package/dist/store/exodus/verify-migration.d.ts.map +1 -1
  152. package/dist/store/exodus/verify-migration.js +142 -10
  153. package/dist/store/exodus/verify-migration.js.map +1 -1
  154. package/dist/store/global-salt.d.ts +16 -0
  155. package/dist/store/global-salt.d.ts.map +1 -1
  156. package/dist/store/global-salt.js +22 -7
  157. package/dist/store/global-salt.js.map +1 -1
  158. package/dist/store/legacy-tasks-lineage.d.ts +86 -0
  159. package/dist/store/legacy-tasks-lineage.d.ts.map +1 -0
  160. package/dist/store/legacy-tasks-lineage.js +285 -0
  161. package/dist/store/legacy-tasks-lineage.js.map +1 -0
  162. package/dist/store/migration-manager.d.ts +27 -0
  163. package/dist/store/migration-manager.d.ts.map +1 -1
  164. package/dist/store/migration-manager.js +63 -0
  165. package/dist/store/migration-manager.js.map +1 -1
  166. package/dist/store/portable-bundle-import.d.ts +117 -0
  167. package/dist/store/portable-bundle-import.d.ts.map +1 -0
  168. package/dist/store/portable-bundle-import.js +589 -0
  169. package/dist/store/portable-bundle-import.js.map +1 -0
  170. package/dist/store/portable-bundle-relocate.d.ts +66 -0
  171. package/dist/store/portable-bundle-relocate.d.ts.map +1 -0
  172. package/dist/store/portable-bundle-relocate.js +304 -0
  173. package/dist/store/portable-bundle-relocate.js.map +1 -0
  174. package/dist/store/portable-bundle-scan.d.ts +167 -0
  175. package/dist/store/portable-bundle-scan.d.ts.map +1 -0
  176. package/dist/store/portable-bundle-scan.js +569 -0
  177. package/dist/store/portable-bundle-scan.js.map +1 -0
  178. package/dist/store/portable-bundle.d.ts +146 -0
  179. package/dist/store/portable-bundle.d.ts.map +1 -0
  180. package/dist/store/portable-bundle.js +674 -0
  181. package/dist/store/portable-bundle.js.map +1 -0
  182. package/dist/store/regenerators.d.ts +3 -1
  183. package/dist/store/regenerators.d.ts.map +1 -1
  184. package/dist/store/regenerators.js +6 -2
  185. package/dist/store/regenerators.js.map +1 -1
  186. package/dist/store/schema/cleo-global/nexus.d.ts +98 -0
  187. package/dist/store/schema/cleo-global/nexus.d.ts.map +1 -1
  188. package/dist/store/schema/cleo-global/nexus.js +19 -0
  189. package/dist/store/schema/cleo-global/nexus.js.map +1 -1
  190. package/dist/store/schema/nexus-schema.d.ts +102 -0
  191. package/dist/store/schema/nexus-schema.d.ts.map +1 -1
  192. package/dist/store/schema/nexus-schema.js +24 -0
  193. package/dist/store/schema/nexus-schema.js.map +1 -1
  194. package/dist/store/split-brain-import.d.ts +176 -0
  195. package/dist/store/split-brain-import.d.ts.map +1 -0
  196. package/dist/store/split-brain-import.js +680 -0
  197. package/dist/store/split-brain-import.js.map +1 -0
  198. package/dist/store/sqlite.d.ts +29 -0
  199. package/dist/store/sqlite.d.ts.map +1 -1
  200. package/dist/store/sqlite.js +57 -5
  201. package/dist/store/sqlite.js.map +1 -1
  202. package/dist/system/health.d.ts.map +1 -1
  203. package/dist/system/health.js +30 -5
  204. package/dist/system/health.js.map +1 -1
  205. package/dist/upgrade.d.ts.map +1 -1
  206. package/dist/upgrade.js +60 -0
  207. package/dist/upgrade.js.map +1 -1
  208. package/dist/validation/doctor/checks.d.ts +14 -0
  209. package/dist/validation/doctor/checks.d.ts.map +1 -1
  210. package/dist/validation/doctor/checks.js +33 -0
  211. package/dist/validation/doctor/checks.js.map +1 -1
  212. package/migrations/drizzle-cleo-global/20260924000000_t12354-project-paths/migration.sql +40 -0
  213. package/migrations/drizzle-nexus/20260924000000_t12315-nexus-parse-cache/migration.sql +21 -0
  214. package/package.json +13 -13
  215. package/templates/CLEO-INJECTION.md +3 -3
  216. package/templates/cleo-gitignore +7 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Code-graph index freshness — disclosed on every graph query, and repaired
3
+ * inline when the repair is small (T12316).
4
+ *
5
+ * A graph answer from a stale index is a confident answer about code that no
6
+ * longer exists. The check compares the published generation's file manifest
7
+ * against the working tree: a file whose size and mtime are unchanged keeps its
8
+ * recorded hash, and only a metadata mismatch is re-hashed, so a checkout or
9
+ * `touch` that changed no bytes is not reported stale.
10
+ *
11
+ * Code placed in `packages/core/` per Package-Boundary Check — verified against AGENTS.md.
12
+ *
13
+ * @task T12316
14
+ * @module nexus/freshness
15
+ */
16
+ import type { GraphIndexFreshness } from '@cleocode/contracts';
17
+ /** Command that refreshes the index; incremental by default since T12315. */
18
+ export declare const NEXUS_REFRESH_COMMAND = "cleo nexus analyze";
19
+ /** Default number of stale files an index query may refresh inline. */
20
+ export declare const DEFAULT_AUTO_REFRESH_MAX_FILES = 25;
21
+ /** Default wall-clock budget for an inline refresh. */
22
+ export declare const DEFAULT_AUTO_REFRESH_BUDGET_MS = 60000;
23
+ /** Options for {@link assessNexusIndexFreshness}. */
24
+ export interface NexusFreshnessOptions {
25
+ /** Files of the queried symbol(s); their own staleness is reported separately. */
26
+ symbolFiles?: readonly string[];
27
+ /** Maximum stale paths listed in the result. @defaultValue 10 */
28
+ sampleLimit?: number;
29
+ }
30
+ /**
31
+ * A freshness verdict plus the complete stale set it was computed from, so the
32
+ * files of a symbol identified only AFTER the query can still be judged.
33
+ */
34
+ export interface NexusFreshnessAssessment {
35
+ /** Disclosed freshness facts. */
36
+ freshness: GraphIndexFreshness;
37
+ /** Every stale path (modified, added, deleted or unreadable). */
38
+ staleFiles: ReadonlySet<string>;
39
+ }
40
+ /**
41
+ * Judge the queried symbol's own files against an assessment.
42
+ * @param assessment - Assessment taken before the query ran.
43
+ * @param files - Files of the queried symbol(s), e.g. from {@link querySymbolFiles}.
44
+ * @returns The freshness facts with `symbolFileStale`/`symbolFile` set when files are known.
45
+ */
46
+ export declare function judgeSymbolFiles(assessment: NexusFreshnessAssessment, files: readonly string[]): GraphIndexFreshness;
47
+ /** Auto-refresh policy, read from `nexus.autoRefresh.*` config unless given. */
48
+ export interface NexusAutoRefreshPolicy {
49
+ /** Whether queries may refresh the index inline. @defaultValue true */
50
+ enabled: boolean;
51
+ /** Most stale files a query refreshes inline. @defaultValue 25 */
52
+ maxFiles: number;
53
+ /** Wall-clock budget; a refresh estimated to exceed it is not started. @defaultValue 60000 */
54
+ budgetMs: number;
55
+ }
56
+ /**
57
+ * Assess how far the published code graph lags the working tree.
58
+ *
59
+ * @param projectRoot - Project whose graph database is inspected.
60
+ * @param options - Symbol files to judge individually and the stale-path sample size.
61
+ * @returns Freshness facts; `status: 'unknown'` carries a `reason` and is never a pass.
62
+ * @example
63
+ * ```ts
64
+ * const freshness = await assessNexusIndexFreshness('/repo', { symbolFiles: ['src/a.ts'] });
65
+ * if (freshness.status === 'stale') console.error(freshness.refreshCommand);
66
+ * ```
67
+ */
68
+ export declare function assessNexusIndexFreshness(projectRoot: string, options?: NexusFreshnessOptions): Promise<GraphIndexFreshness>;
69
+ /**
70
+ * Read the auto-refresh policy from `nexus.autoRefresh.*`, applying defaults.
71
+ * @param projectRoot - Project whose merged config is read.
72
+ * @returns The effective policy.
73
+ */
74
+ export declare function readNexusAutoRefreshPolicy(projectRoot: string): Promise<NexusAutoRefreshPolicy>;
75
+ /**
76
+ * Assess freshness and, when only a few files are stale, refresh the index
77
+ * inline before the caller answers from it.
78
+ *
79
+ * A refresh runs only when `0 < stale ≤ maxFiles` and the recorded cost
80
+ * estimate fits `budgetMs`; the budget also cancels the run at its next phase
81
+ * boundary, and publication is atomic, so an abandoned refresh leaves the
82
+ * previous graph intact. Every decision — refreshed, skipped or failed — is
83
+ * disclosed in `autoRefresh`, and the returned freshness describes the index
84
+ * the caller is about to read.
85
+ *
86
+ * @param projectRoot - Project whose graph is about to be queried.
87
+ * @param policy - Explicit policy; read from config when omitted.
88
+ * @returns Freshness of the index as it stands after any refresh, with its stale set.
89
+ */
90
+ export declare function ensureNexusIndexFresh(projectRoot: string, policy?: NexusAutoRefreshPolicy): Promise<NexusFreshnessAssessment>;
91
+ /**
92
+ * Collect the source files a graph query answer is about.
93
+ *
94
+ * Graph node ids are `<file>::<symbol>`, so a target id names its file; an
95
+ * explicit `filePath` is used when present. Only the answer's own target (or,
96
+ * for symbol lookups, each matched symbol) is considered — callers listed in
97
+ * the answer are not "the queried symbol".
98
+ *
99
+ * @param data - A query operation's result payload.
100
+ * @returns Repository-relative files of the queried symbol(s); empty when none are identifiable.
101
+ */
102
+ export declare function querySymbolFiles(data: unknown): string[];
103
+ /**
104
+ * Assess (and when small, repair) index freshness before a graph query.
105
+ *
106
+ * Never throws: a failed assessment is returned as `status: 'unknown'` with its
107
+ * reason, so it neither blocks the query nor is ever mistaken for fresh.
108
+ *
109
+ * @param projectRoot - Project whose graph is about to be queried.
110
+ * @returns The assessment to judge the answer against.
111
+ */
112
+ export declare function assessNexusFreshnessForQuery(projectRoot: string): Promise<NexusFreshnessAssessment>;
113
+ /**
114
+ * Disclose a non-fresh index as an envelope warning
115
+ * (`W_NEXUS_INDEX_STALE` / `W_NEXUS_INDEX_FRESHNESS_UNKNOWN`), and an inline
116
+ * refresh that just happened as `W_NEXUS_INDEX_REFRESHED` (info). Warnings
117
+ * reach `meta.warnings` through the active collector — never stderr, which
118
+ * would break the one-envelope stream contract (T9775).
119
+ *
120
+ * @param subject - What answered, e.g. `nexus impact`.
121
+ * @param freshness - Freshness of the index the answer came from.
122
+ */
123
+ export declare function discloseNexusFreshness(subject: string, freshness: GraphIndexFreshness): void;
124
+ /**
125
+ * Merge a freshness verdict into envelope extensions' `_nexus` block.
126
+ * @param extensions - Envelope extensions, possibly already carrying `_nexus`.
127
+ * @param freshness - Freshness of the index the answer came from.
128
+ * @returns New extensions with `_nexus.indexFreshness` and `_nexus.freshness` set.
129
+ */
130
+ export declare function withNexusFreshnessMeta(extensions: Record<string, unknown>, freshness: GraphIndexFreshness): Record<string, unknown>;
131
+ //# sourceMappingURL=freshness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freshness.d.ts","sourceRoot":"","sources":["../../src/nexus/freshness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAQ/D,6EAA6E;AAC7E,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAE1D,uEAAuE;AACvE,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,uDAAuD;AACvD,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAKrD,qDAAqD;AACrD,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,iCAAiC;IACjC,SAAS,EAAE,mBAAmB,CAAC;IAC/B,iEAAiE;IACjE,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,wBAAwB,EACpC,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,mBAAmB,CASrB;AAED,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,8FAA8F;IAC9F,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6BD;;;;;;;;;;;GAWG;AACH,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAG9B;AAwFD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,sBAAsB,CAAC,CAwBjC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAAC,wBAAwB,CAAC,CA+DnC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAyBxD;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,CAChD,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,wBAAwB,CAAC,CAoBnC;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,GAAG,IAAI,CA0B5F;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,SAAS,EAAE,mBAAmB,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB"}
@@ -0,0 +1,391 @@
1
+ /**
2
+ * Code-graph index freshness — disclosed on every graph query, and repaired
3
+ * inline when the repair is small (T12316).
4
+ *
5
+ * A graph answer from a stale index is a confident answer about code that no
6
+ * longer exists. The check compares the published generation's file manifest
7
+ * against the working tree: a file whose size and mtime are unchanged keeps its
8
+ * recorded hash, and only a metadata mismatch is re-hashed, so a checkout or
9
+ * `touch` that changed no bytes is not reported stale.
10
+ *
11
+ * Code placed in `packages/core/` per Package-Boundary Check — verified against AGENTS.md.
12
+ *
13
+ * @task T12316
14
+ * @module nexus/freshness
15
+ */
16
+ import { performance } from 'node:perf_hooks';
17
+ import { getConfigValue } from '../config/registry.js';
18
+ import { pushWarning } from '../output.js';
19
+ import { getNexusDb } from '../store/nexus-sqlite.js';
20
+ import { runNexusAnalysis } from './analyze-orchestrator.js';
21
+ import { readFileManifest, readRunCost } from './graph-manifest.js';
22
+ /** Command that refreshes the index; incremental by default since T12315. */
23
+ export const NEXUS_REFRESH_COMMAND = 'cleo nexus analyze';
24
+ /** Default number of stale files an index query may refresh inline. */
25
+ export const DEFAULT_AUTO_REFRESH_MAX_FILES = 25;
26
+ /** Default wall-clock budget for an inline refresh. */
27
+ export const DEFAULT_AUTO_REFRESH_BUDGET_MS = 60_000;
28
+ /** Share of changed files above which analysis rebuilds fully (mirrors the pipeline). */
29
+ const FULL_REBUILD_RATIO = 0.3;
30
+ /**
31
+ * Judge the queried symbol's own files against an assessment.
32
+ * @param assessment - Assessment taken before the query ran.
33
+ * @param files - Files of the queried symbol(s), e.g. from {@link querySymbolFiles}.
34
+ * @returns The freshness facts with `symbolFileStale`/`symbolFile` set when files are known.
35
+ */
36
+ export function judgeSymbolFiles(assessment, files) {
37
+ const unique = [...new Set(files)];
38
+ if (unique.length === 0)
39
+ return assessment.freshness;
40
+ const stale = unique.find((file) => assessment.staleFiles.has(file));
41
+ return {
42
+ ...assessment.freshness,
43
+ symbolFileStale: stale !== undefined,
44
+ symbolFile: stale ?? unique[0],
45
+ };
46
+ }
47
+ /** Estimate a refresh from the last recorded run, or `null` when nothing is recorded. */
48
+ function estimateRefreshMs(cost, staleFiles, fileCount) {
49
+ if (!cost)
50
+ return null;
51
+ const parseMs = cost.summary.phaseMs['parse'] ?? 0;
52
+ const parsed = cost.summary.parsedFiles;
53
+ const fixedMs = Math.max(0, cost.durationMs - parseMs);
54
+ const perFileMs = parsed > 0 ? parseMs / parsed : 0;
55
+ const full = fileCount > 0 && staleFiles / fileCount > FULL_REBUILD_RATIO;
56
+ const reparsed = full ? Math.max(parsed, cost.summary.resolvedFiles) : staleFiles;
57
+ return Math.round(fixedMs + reparsed * perFileMs);
58
+ }
59
+ /** Render an estimate for humans and agents alike. */
60
+ function describeEstimate(ms, staleFiles, fileCount) {
61
+ if (staleFiles === 0)
62
+ return 'none needed';
63
+ const kind = fileCount > 0 && staleFiles / fileCount > FULL_REBUILD_RATIO
64
+ ? 'full rebuild'
65
+ : `incremental, re-parses ~${staleFiles} file(s)`;
66
+ if (ms === null)
67
+ return `unknown duration (${kind}; no previous analysis cost recorded)`;
68
+ return `~${Math.max(1, Math.round(ms / 1000))}s (${kind})`;
69
+ }
70
+ /**
71
+ * Assess how far the published code graph lags the working tree.
72
+ *
73
+ * @param projectRoot - Project whose graph database is inspected.
74
+ * @param options - Symbol files to judge individually and the stale-path sample size.
75
+ * @returns Freshness facts; `status: 'unknown'` carries a `reason` and is never a pass.
76
+ * @example
77
+ * ```ts
78
+ * const freshness = await assessNexusIndexFreshness('/repo', { symbolFiles: ['src/a.ts'] });
79
+ * if (freshness.status === 'stale') console.error(freshness.refreshCommand);
80
+ * ```
81
+ */
82
+ export async function assessNexusIndexFreshness(projectRoot, options = {}) {
83
+ const assessment = await assessWithStaleSet(projectRoot, options.sampleLimit);
84
+ return judgeSymbolFiles(assessment, options.symbolFiles ?? []);
85
+ }
86
+ /** Walk the tree once and keep the full stale set alongside the disclosed facts. */
87
+ async function assessWithStaleSet(projectRoot, sampleLimit = 10) {
88
+ const started = performance.now();
89
+ const base = {
90
+ refreshCommand: NEXUS_REFRESH_COMMAND,
91
+ stalePaths: [],
92
+ };
93
+ const db = await getNexusDb(projectRoot);
94
+ let manifest;
95
+ const none = new Set();
96
+ try {
97
+ manifest = readFileManifest(db);
98
+ }
99
+ catch (error) {
100
+ const freshness = {
101
+ ...base,
102
+ indexed: true,
103
+ status: 'unknown',
104
+ lastIndexedAt: null,
105
+ fileCount: 0,
106
+ staleFileCount: -1,
107
+ refreshEstimate: 'unknown',
108
+ checkMs: Math.round(performance.now() - started),
109
+ reason: `the recorded file manifest is unreadable: ${error instanceof Error ? error.message : String(error)}`,
110
+ };
111
+ return { freshness, staleFiles: none };
112
+ }
113
+ if (!manifest) {
114
+ const freshness = {
115
+ ...base,
116
+ indexed: false,
117
+ status: 'unknown',
118
+ lastIndexedAt: null,
119
+ fileCount: 0,
120
+ staleFileCount: -1,
121
+ refreshEstimate: 'unknown',
122
+ checkMs: Math.round(performance.now() - started),
123
+ reason: 'no file manifest is recorded — the project was never indexed, or its index predates ' +
124
+ `freshness tracking; run ${NEXUS_REFRESH_COMMAND} once`,
125
+ };
126
+ return { freshness, staleFiles: none };
127
+ }
128
+ const known = new Map();
129
+ for (const [path, size, mtimeMs, contentHash] of manifest.files)
130
+ known.set(path, { size, mtimeMs, contentHash });
131
+ const { walkRepositoryPaths } = await import('@cleocode/nexus/pipeline');
132
+ const unreadable = [];
133
+ const current = await walkRepositoryPaths(manifest.sourceRoot, undefined, (report) => {
134
+ if (report.status === 'failed')
135
+ unreadable.push(report.path);
136
+ }, manifest.includedRepositories, { knownFiles: known });
137
+ const stale = new Set(unreadable);
138
+ const seen = new Set();
139
+ for (const file of current) {
140
+ seen.add(file.path);
141
+ if (known.get(file.path)?.contentHash !== file.contentHash)
142
+ stale.add(file.path);
143
+ }
144
+ for (const path of known.keys())
145
+ if (!seen.has(path))
146
+ stale.add(path);
147
+ const fileCount = manifest.files.length;
148
+ const estimate = estimateRefreshMs(readRunCost(db), stale.size, fileCount);
149
+ const freshness = {
150
+ ...base,
151
+ indexed: true,
152
+ status: stale.size === 0 ? 'fresh' : 'stale',
153
+ lastIndexedAt: manifest.assessedAt,
154
+ fileCount,
155
+ staleFileCount: stale.size,
156
+ stalePaths: [...stale].sort().slice(0, sampleLimit),
157
+ refreshEstimate: describeEstimate(estimate, stale.size, fileCount),
158
+ checkMs: Math.round(performance.now() - started),
159
+ };
160
+ return { freshness, staleFiles: stale };
161
+ }
162
+ /**
163
+ * Read the auto-refresh policy from `nexus.autoRefresh.*`, applying defaults.
164
+ * @param projectRoot - Project whose merged config is read.
165
+ * @returns The effective policy.
166
+ */
167
+ export async function readNexusAutoRefreshPolicy(projectRoot) {
168
+ const read = async (key) => {
169
+ try {
170
+ return await getConfigValue(`nexus.autoRefresh.${key}`, { projectRoot });
171
+ }
172
+ catch {
173
+ return undefined;
174
+ }
175
+ };
176
+ const [enabled, maxFiles, budgetMs] = await Promise.all([
177
+ read('enabled'),
178
+ read('maxFiles'),
179
+ read('budgetMs'),
180
+ ]);
181
+ return {
182
+ enabled: typeof enabled === 'boolean' ? enabled : true,
183
+ maxFiles: typeof maxFiles === 'number' && Number.isInteger(maxFiles) && maxFiles >= 0
184
+ ? maxFiles
185
+ : DEFAULT_AUTO_REFRESH_MAX_FILES,
186
+ budgetMs: typeof budgetMs === 'number' && Number.isFinite(budgetMs) && budgetMs > 0
187
+ ? budgetMs
188
+ : DEFAULT_AUTO_REFRESH_BUDGET_MS,
189
+ };
190
+ }
191
+ /**
192
+ * Assess freshness and, when only a few files are stale, refresh the index
193
+ * inline before the caller answers from it.
194
+ *
195
+ * A refresh runs only when `0 < stale ≤ maxFiles` and the recorded cost
196
+ * estimate fits `budgetMs`; the budget also cancels the run at its next phase
197
+ * boundary, and publication is atomic, so an abandoned refresh leaves the
198
+ * previous graph intact. Every decision — refreshed, skipped or failed — is
199
+ * disclosed in `autoRefresh`, and the returned freshness describes the index
200
+ * the caller is about to read.
201
+ *
202
+ * @param projectRoot - Project whose graph is about to be queried.
203
+ * @param policy - Explicit policy; read from config when omitted.
204
+ * @returns Freshness of the index as it stands after any refresh, with its stale set.
205
+ */
206
+ export async function ensureNexusIndexFresh(projectRoot, policy) {
207
+ const initial = await assessWithStaleSet(projectRoot);
208
+ const before = initial.freshness;
209
+ if (before.status !== 'stale')
210
+ return initial;
211
+ const effective = policy ?? (await readNexusAutoRefreshPolicy(projectRoot));
212
+ const skip = (reason) => ({
213
+ staleFiles: initial.staleFiles,
214
+ freshness: {
215
+ ...before,
216
+ autoRefresh: { refreshed: false, staleFiles: before.staleFileCount, durationMs: 0, reason },
217
+ },
218
+ });
219
+ if (!effective.enabled)
220
+ return skip('auto-refresh is disabled (nexus.autoRefresh.enabled = false)');
221
+ if (before.staleFileCount > effective.maxFiles)
222
+ return skip(`${before.staleFileCount} stale files exceed nexus.autoRefresh.maxFiles = ${effective.maxFiles}; ` +
223
+ 'answered from the stale index');
224
+ const db = await getNexusDb(projectRoot);
225
+ const estimate = estimateRefreshMs(readRunCost(db), before.staleFileCount, before.fileCount);
226
+ if (estimate !== null && estimate > effective.budgetMs)
227
+ return skip(`estimated refresh ${Math.round(estimate / 1000)}s exceeds nexus.autoRefresh.budgetMs = ` +
228
+ `${effective.budgetMs}; answered from the stale index`);
229
+ const manifest = readFileManifest(db);
230
+ const started = performance.now();
231
+ try {
232
+ const result = await runNexusAnalysis({
233
+ projectRoot,
234
+ repoPath: manifest?.sourceRoot ?? projectRoot,
235
+ ...(manifest ? { includedRepositories: manifest.includedRepositories } : {}),
236
+ parserLimits: { signal: AbortSignal.timeout(effective.budgetMs) },
237
+ });
238
+ const after = await assessWithStaleSet(projectRoot);
239
+ return {
240
+ staleFiles: after.staleFiles,
241
+ freshness: {
242
+ ...after.freshness,
243
+ autoRefresh: {
244
+ refreshed: result.summary.mode !== 'unchanged',
245
+ staleFiles: before.staleFileCount,
246
+ durationMs: Math.round(performance.now() - started),
247
+ reason: `${result.summary.mode}: ${result.summary.reason}`,
248
+ },
249
+ },
250
+ };
251
+ }
252
+ catch (error) {
253
+ return {
254
+ staleFiles: initial.staleFiles,
255
+ freshness: {
256
+ ...before,
257
+ autoRefresh: {
258
+ refreshed: false,
259
+ staleFiles: before.staleFileCount,
260
+ durationMs: Math.round(performance.now() - started),
261
+ reason: `refresh failed, previous graph retained: ${error instanceof Error ? error.message : String(error)}`,
262
+ },
263
+ },
264
+ };
265
+ }
266
+ }
267
+ /**
268
+ * Collect the source files a graph query answer is about.
269
+ *
270
+ * Graph node ids are `<file>::<symbol>`, so a target id names its file; an
271
+ * explicit `filePath` is used when present. Only the answer's own target (or,
272
+ * for symbol lookups, each matched symbol) is considered — callers listed in
273
+ * the answer are not "the queried symbol".
274
+ *
275
+ * @param data - A query operation's result payload.
276
+ * @returns Repository-relative files of the queried symbol(s); empty when none are identifiable.
277
+ */
278
+ export function querySymbolFiles(data) {
279
+ const files = new Set();
280
+ const fromId = (id) => {
281
+ if (typeof id === 'string' && id.includes('::'))
282
+ files.add(id.slice(0, id.indexOf('::')));
283
+ };
284
+ const visit = (value) => {
285
+ if (!value || typeof value !== 'object' || Array.isArray(value))
286
+ return;
287
+ const record = value;
288
+ if (typeof record['filePath'] === 'string')
289
+ files.add(record['filePath']);
290
+ fromId(record['targetNodeId']);
291
+ fromId(record['nodeId']);
292
+ fromId(record['symbolId']);
293
+ };
294
+ visit(data);
295
+ if (data && typeof data === 'object' && !Array.isArray(data)) {
296
+ const record = data;
297
+ for (const key of ['target', 'symbol', 'node'])
298
+ visit(record[key]);
299
+ // Symbol lookups (e.g. `context`) answer with one entry per matched symbol;
300
+ // each entry's own identity counts, never the callers nested inside it.
301
+ for (const key of ['results', 'matches']) {
302
+ const entries = record[key];
303
+ if (Array.isArray(entries))
304
+ for (const entry of entries)
305
+ visit(entry);
306
+ }
307
+ }
308
+ return [...files];
309
+ }
310
+ /**
311
+ * Assess (and when small, repair) index freshness before a graph query.
312
+ *
313
+ * Never throws: a failed assessment is returned as `status: 'unknown'` with its
314
+ * reason, so it neither blocks the query nor is ever mistaken for fresh.
315
+ *
316
+ * @param projectRoot - Project whose graph is about to be queried.
317
+ * @returns The assessment to judge the answer against.
318
+ */
319
+ export async function assessNexusFreshnessForQuery(projectRoot) {
320
+ try {
321
+ return await ensureNexusIndexFresh(projectRoot);
322
+ }
323
+ catch (error) {
324
+ return {
325
+ staleFiles: new Set(),
326
+ freshness: {
327
+ indexed: false,
328
+ status: 'unknown',
329
+ lastIndexedAt: null,
330
+ fileCount: 0,
331
+ staleFileCount: -1,
332
+ stalePaths: [],
333
+ refreshCommand: NEXUS_REFRESH_COMMAND,
334
+ refreshEstimate: 'unknown',
335
+ checkMs: 0,
336
+ reason: `freshness could not be assessed: ${error instanceof Error ? error.message : String(error)}`,
337
+ },
338
+ };
339
+ }
340
+ }
341
+ /**
342
+ * Disclose a non-fresh index as an envelope warning
343
+ * (`W_NEXUS_INDEX_STALE` / `W_NEXUS_INDEX_FRESHNESS_UNKNOWN`), and an inline
344
+ * refresh that just happened as `W_NEXUS_INDEX_REFRESHED` (info). Warnings
345
+ * reach `meta.warnings` through the active collector — never stderr, which
346
+ * would break the one-envelope stream contract (T9775).
347
+ *
348
+ * @param subject - What answered, e.g. `nexus impact`.
349
+ * @param freshness - Freshness of the index the answer came from.
350
+ */
351
+ export function discloseNexusFreshness(subject, freshness) {
352
+ const refresh = freshness.autoRefresh;
353
+ if (refresh?.refreshed) {
354
+ pushWarning({
355
+ code: 'W_NEXUS_INDEX_REFRESHED',
356
+ severity: 'info',
357
+ message: `Refreshed the index inline before answering (${refresh.staleFiles} stale file(s), ${refresh.durationMs}ms): ${refresh.reason}`,
358
+ });
359
+ }
360
+ if (freshness.status === 'fresh')
361
+ return;
362
+ const symbol = freshness.symbolFileStale === true
363
+ ? ` The queried symbol's own file (${freshness.symbolFile}) is among them.`
364
+ : '';
365
+ const message = freshness.status === 'stale'
366
+ ? `${subject} answered from an index ${freshness.staleFileCount} file(s) behind the working tree ` +
367
+ `(indexed ${freshness.lastIndexedAt ?? 'at an unknown time'}; e.g. ${freshness.stalePaths.slice(0, 3).join(', ')}).${symbol} ` +
368
+ `Refresh: ${freshness.refreshCommand} — ${freshness.refreshEstimate}.` +
369
+ (refresh && !refresh.refreshed ? ` Not refreshed inline: ${refresh.reason}.` : '')
370
+ : `${subject} could not establish index freshness: ${freshness.reason ?? 'unknown reason'}.`;
371
+ pushWarning({
372
+ code: freshness.status === 'stale' ? 'W_NEXUS_INDEX_STALE' : 'W_NEXUS_INDEX_FRESHNESS_UNKNOWN',
373
+ severity: 'warn',
374
+ message,
375
+ });
376
+ }
377
+ /**
378
+ * Merge a freshness verdict into envelope extensions' `_nexus` block.
379
+ * @param extensions - Envelope extensions, possibly already carrying `_nexus`.
380
+ * @param freshness - Freshness of the index the answer came from.
381
+ * @returns New extensions with `_nexus.indexFreshness` and `_nexus.freshness` set.
382
+ */
383
+ export function withNexusFreshnessMeta(extensions, freshness) {
384
+ const current = extensions['_nexus'];
385
+ const nexusMeta = current && typeof current === 'object' ? current : {};
386
+ return {
387
+ ...extensions,
388
+ _nexus: { ...nexusMeta, indexFreshness: freshness.status, freshness },
389
+ };
390
+ }
391
+ //# sourceMappingURL=freshness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freshness.js","sourceRoot":"","sources":["../../src/nexus/freshness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Compact per-generation bookkeeping for cheap freshness checks (T12316).
3
+ *
4
+ * The published `graph_assessment` carries every retained reference with its
5
+ * full evidence — 472 MB of JSON on this repository — so it cannot be read on
6
+ * the query path. The file manifest records only what a freshness check needs
7
+ * (path, size, mtime, content hash per indexed file), and the run summary
8
+ * records what the last analysis cost, so a refresh can be estimated before it
9
+ * is started. Both live in `_nexus_meta` next to the generation they describe.
10
+ *
11
+ * Code placed in `packages/core/` per Package-Boundary Check — verified against AGENTS.md.
12
+ *
13
+ * @task T12316
14
+ * @module nexus/graph-manifest
15
+ */
16
+ import type { GraphIndexAssessment, GraphIndexRunSummary } from '@cleocode/contracts';
17
+ import type { NodeSQLiteDatabase } from 'drizzle-orm/node-sqlite';
18
+ /** One indexed file: `[path, size, mtimeMs, contentHash]`. */
19
+ export type GraphManifestEntry = [path: string, size: number, mtimeMs: number, hash: string];
20
+ /** Compact description of the files a published generation was built from. */
21
+ export interface GraphFileManifest {
22
+ /** Generation the manifest describes. */
23
+ generation: string | null;
24
+ /** Canonical root the paths are relative to. */
25
+ sourceRoot: string;
26
+ /** Explicitly included nested repositories, needed to walk the same tree. */
27
+ includedRepositories: string[];
28
+ /** When the generation was assessed. */
29
+ assessedAt: string;
30
+ /** Every indexed file with a content hash. */
31
+ files: GraphManifestEntry[];
32
+ }
33
+ /** Cost record of the last analysis that published a generation. */
34
+ export interface GraphRunCost {
35
+ /** Mode, counts and per-phase milliseconds of that run. */
36
+ summary: GraphIndexRunSummary;
37
+ /** End-to-end milliseconds, including provenance and publication. */
38
+ durationMs: number;
39
+ /** When the run finished. */
40
+ recordedAt: string;
41
+ }
42
+ /** Files with an observed size, mtime and hash, as recorded by an index scan. */
43
+ interface ObservedFile {
44
+ path: string;
45
+ size?: number;
46
+ mtimeMs?: number;
47
+ contentHash?: string;
48
+ }
49
+ /**
50
+ * Build the manifest for a generation from its observed files.
51
+ * @param assessment - Assessment of the generation (source root, scope, timestamp).
52
+ * @param files - Files whose size, mtime and hash were observed; others are omitted.
53
+ * @returns The compact manifest.
54
+ */
55
+ export declare function buildFileManifest(assessment: Pick<GraphIndexAssessment, 'generation' | 'sourceRoot' | 'includedRepositories' | 'assessedAt'>, files: readonly ObservedFile[]): GraphFileManifest;
56
+ /**
57
+ * Write the manifest; call inside the transaction that publishes its generation.
58
+ * @param tx - Open transaction on the project graph database.
59
+ * @param manifest - Manifest of the generation being committed.
60
+ */
61
+ export declare function writeFileManifest(tx: NodeSQLiteDatabase, manifest: GraphFileManifest): void;
62
+ /**
63
+ * Remove the manifest; call when a generation is published without one, so a
64
+ * stale manifest can never describe a different generation.
65
+ * @param tx - Open transaction on the project graph database.
66
+ */
67
+ export declare function clearFileManifest(tx: NodeSQLiteDatabase): void;
68
+ /**
69
+ * Read the manifest of the committed generation.
70
+ * @param db - Project graph database.
71
+ * @returns The manifest, or `null` when the generation predates manifests.
72
+ * @throws When a stored manifest is malformed.
73
+ */
74
+ export declare function readFileManifest(db: NodeSQLiteDatabase): GraphFileManifest | null;
75
+ /**
76
+ * Record what the last publishing analysis cost; advisory, used for estimates.
77
+ * @param db - Project graph database.
78
+ * @param cost - Summary and duration of the run.
79
+ */
80
+ export declare function writeRunCost(db: NodeSQLiteDatabase, cost: GraphRunCost): void;
81
+ /**
82
+ * Read the last recorded run cost.
83
+ * @param db - Project graph database.
84
+ * @returns The cost, or `null` when none (or an unreadable one) is recorded.
85
+ */
86
+ export declare function readRunCost(db: NodeSQLiteDatabase): GraphRunCost | null;
87
+ export {};
88
+ //# sourceMappingURL=graph-manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-manifest.d.ts","sourceRoot":"","sources":["../../src/nexus/graph-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEtF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAQlE,8DAA8D;AAC9D,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAE7F,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED,oEAAoE;AACpE,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,OAAO,EAAE,oBAAoB,CAAC;IAC9B,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;CACpB;AA0BD,iFAAiF;AACjF,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,IAAI,CACd,oBAAoB,EACpB,YAAY,GAAG,YAAY,GAAG,sBAAsB,GAAG,YAAY,CACpE,EACD,KAAK,EAAE,SAAS,YAAY,EAAE,GAC7B,iBAAiB,CAanB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,kBAAkB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAG3F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,IAAI,CAMjF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAG7E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,kBAAkB,GAAG,YAAY,GAAG,IAAI,CAOvE"}