@vibe-hero/server 0.1.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 (150) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +151 -0
  3. package/dist/catalog/bundled/claude-code/.gitkeep +0 -0
  4. package/dist/catalog/bundled/claude-code/context-management.yaml +302 -0
  5. package/dist/catalog/bundled/claude-code/planning.yaml +313 -0
  6. package/dist/catalog/bundled/claude-code/subagents.yaml +357 -0
  7. package/dist/catalog/bundled/general/.gitkeep +0 -0
  8. package/dist/catalog/bundled/general/_placeholder.yaml +39 -0
  9. package/dist/catalog/bundled/general/task-decomposition.yaml +390 -0
  10. package/dist/catalog/bundled/index.d.ts +39 -0
  11. package/dist/catalog/bundled/index.d.ts.map +1 -0
  12. package/dist/catalog/bundled/index.js +41 -0
  13. package/dist/catalog/bundled/index.js.map +1 -0
  14. package/dist/catalog/fetcher.d.ts +201 -0
  15. package/dist/catalog/fetcher.d.ts.map +1 -0
  16. package/dist/catalog/fetcher.js +452 -0
  17. package/dist/catalog/fetcher.js.map +1 -0
  18. package/dist/catalog/loader.d.ts +165 -0
  19. package/dist/catalog/loader.d.ts.map +1 -0
  20. package/dist/catalog/loader.js +241 -0
  21. package/dist/catalog/loader.js.map +1 -0
  22. package/dist/catalog/resolve.d.ts +85 -0
  23. package/dist/catalog/resolve.d.ts.map +1 -0
  24. package/dist/catalog/resolve.js +103 -0
  25. package/dist/catalog/resolve.js.map +1 -0
  26. package/dist/cli/getOffer.d.ts +38 -0
  27. package/dist/cli/getOffer.d.ts.map +1 -0
  28. package/dist/cli/getOffer.js +150 -0
  29. package/dist/cli/getOffer.js.map +1 -0
  30. package/dist/cli/index.d.ts +46 -0
  31. package/dist/cli/index.d.ts.map +1 -0
  32. package/dist/cli/index.js +88 -0
  33. package/dist/cli/index.js.map +1 -0
  34. package/dist/config.d.ts +34 -0
  35. package/dist/config.d.ts.map +1 -0
  36. package/dist/config.js +63 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/engine/elo.d.ts +76 -0
  39. package/dist/engine/elo.d.ts.map +1 -0
  40. package/dist/engine/elo.js +79 -0
  41. package/dist/engine/elo.js.map +1 -0
  42. package/dist/engine/graduation.d.ts +108 -0
  43. package/dist/engine/graduation.d.ts.map +1 -0
  44. package/dist/engine/graduation.js +161 -0
  45. package/dist/engine/graduation.js.map +1 -0
  46. package/dist/engine/lapse.d.ts +80 -0
  47. package/dist/engine/lapse.d.ts.map +1 -0
  48. package/dist/engine/lapse.js +125 -0
  49. package/dist/engine/lapse.js.map +1 -0
  50. package/dist/engine/selection.d.ts +84 -0
  51. package/dist/engine/selection.d.ts.map +1 -0
  52. package/dist/engine/selection.js +119 -0
  53. package/dist/engine/selection.js.map +1 -0
  54. package/dist/grading/deterministic.d.ts +102 -0
  55. package/dist/grading/deterministic.d.ts.map +1 -0
  56. package/dist/grading/deterministic.js +118 -0
  57. package/dist/grading/deterministic.js.map +1 -0
  58. package/dist/grading/freeform.d.ts +64 -0
  59. package/dist/grading/freeform.d.ts.map +1 -0
  60. package/dist/grading/freeform.js +85 -0
  61. package/dist/grading/freeform.js.map +1 -0
  62. package/dist/index.d.ts +52 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +91 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/observation/hookEvents.d.ts +113 -0
  67. package/dist/observation/hookEvents.d.ts.map +1 -0
  68. package/dist/observation/hookEvents.js +170 -0
  69. package/dist/observation/hookEvents.js.map +1 -0
  70. package/dist/observation/offers.d.ts +215 -0
  71. package/dist/observation/offers.d.ts.map +1 -0
  72. package/dist/observation/offers.js +327 -0
  73. package/dist/observation/offers.js.map +1 -0
  74. package/dist/observation/source.d.ts +133 -0
  75. package/dist/observation/source.d.ts.map +1 -0
  76. package/dist/observation/source.js +105 -0
  77. package/dist/observation/source.js.map +1 -0
  78. package/dist/profile/migrate.d.ts +122 -0
  79. package/dist/profile/migrate.d.ts.map +1 -0
  80. package/dist/profile/migrate.js +147 -0
  81. package/dist/profile/migrate.js.map +1 -0
  82. package/dist/profile/store.d.ts +84 -0
  83. package/dist/profile/store.d.ts.map +1 -0
  84. package/dist/profile/store.js +267 -0
  85. package/dist/profile/store.js.map +1 -0
  86. package/dist/schemas/common.d.ts +95 -0
  87. package/dist/schemas/common.d.ts.map +1 -0
  88. package/dist/schemas/common.js +106 -0
  89. package/dist/schemas/common.js.map +1 -0
  90. package/dist/schemas/content.d.ts +828 -0
  91. package/dist/schemas/content.d.ts.map +1 -0
  92. package/dist/schemas/content.js +219 -0
  93. package/dist/schemas/content.js.map +1 -0
  94. package/dist/schemas/profile.d.ts +599 -0
  95. package/dist/schemas/profile.d.ts.map +1 -0
  96. package/dist/schemas/profile.js +177 -0
  97. package/dist/schemas/profile.js.map +1 -0
  98. package/dist/schemas/tools.d.ts +1581 -0
  99. package/dist/schemas/tools.d.ts.map +1 -0
  100. package/dist/schemas/tools.js +286 -0
  101. package/dist/schemas/tools.js.map +1 -0
  102. package/dist/tools/config.d.ts +51 -0
  103. package/dist/tools/config.d.ts.map +1 -0
  104. package/dist/tools/config.js +104 -0
  105. package/dist/tools/config.js.map +1 -0
  106. package/dist/tools/gate.d.ts +50 -0
  107. package/dist/tools/gate.d.ts.map +1 -0
  108. package/dist/tools/gate.js +67 -0
  109. package/dist/tools/gate.js.map +1 -0
  110. package/dist/tools/guidance.d.ts +36 -0
  111. package/dist/tools/guidance.d.ts.map +1 -0
  112. package/dist/tools/guidance.js +117 -0
  113. package/dist/tools/guidance.js.map +1 -0
  114. package/dist/tools/listTopics.d.ts +55 -0
  115. package/dist/tools/listTopics.d.ts.map +1 -0
  116. package/dist/tools/listTopics.js +78 -0
  117. package/dist/tools/listTopics.js.map +1 -0
  118. package/dist/tools/offers.d.ts +60 -0
  119. package/dist/tools/offers.d.ts.map +1 -0
  120. package/dist/tools/offers.js +152 -0
  121. package/dist/tools/offers.js.map +1 -0
  122. package/dist/tools/placeholders.d.ts +27 -0
  123. package/dist/tools/placeholders.d.ts.map +1 -0
  124. package/dist/tools/placeholders.js +49 -0
  125. package/dist/tools/placeholders.js.map +1 -0
  126. package/dist/tools/recordObservation.d.ts +52 -0
  127. package/dist/tools/recordObservation.d.ts.map +1 -0
  128. package/dist/tools/recordObservation.js +87 -0
  129. package/dist/tools/recordObservation.js.map +1 -0
  130. package/dist/tools/startQuiz.d.ts +82 -0
  131. package/dist/tools/startQuiz.d.ts.map +1 -0
  132. package/dist/tools/startQuiz.js +180 -0
  133. package/dist/tools/startQuiz.js.map +1 -0
  134. package/dist/tools/status.d.ts +59 -0
  135. package/dist/tools/status.d.ts.map +1 -0
  136. package/dist/tools/status.js +133 -0
  137. package/dist/tools/status.js.map +1 -0
  138. package/dist/tools/submitAnswer.d.ts +156 -0
  139. package/dist/tools/submitAnswer.d.ts.map +1 -0
  140. package/dist/tools/submitAnswer.js +402 -0
  141. package/dist/tools/submitAnswer.js.map +1 -0
  142. package/dist/tools/types.d.ts +82 -0
  143. package/dist/tools/types.d.ts.map +1 -0
  144. package/dist/tools/types.js +48 -0
  145. package/dist/tools/types.js.map +1 -0
  146. package/dist/tools/us2/standing.d.ts +111 -0
  147. package/dist/tools/us2/standing.d.ts.map +1 -0
  148. package/dist/tools/us2/standing.js +143 -0
  149. package/dist/tools/us2/standing.js.map +1 -0
  150. package/package.json +62 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../../src/catalog/fetcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * @file Content catalog loader (T015).
3
+ *
4
+ * Reads YAML topic files from disk, parses them with `js-yaml`, and validates
5
+ * each against {@link TopicSchema}. Authoring format is YAML (research OD-004):
6
+ * one file per `(topic × class)` carrying every tier and trigger signal
7
+ * (FR-004a). Validation is the load-time gate that prevents malformed content
8
+ * from ever being served (FR-004) — a bad file is reported, never silently
9
+ * served incorrectly.
10
+ *
11
+ * IO is intentionally thin (read file, list directory); the logic that matters
12
+ * is parse + Zod validation + path-qualified diagnostics.
13
+ *
14
+ * Source of truth: specs/001-vibe-hero-mvp/data-model.md (§ Content Catalog),
15
+ * spec FR-001/003a/004/004a/025, research.md OD-004.
16
+ */
17
+ import { type CatalogManifest, type Topic } from "../schemas/content.js";
18
+ /**
19
+ * Placeholder catalog version used by {@link buildManifest} when no explicit
20
+ * version is supplied and no manifest file is present. The fetch/publish layer
21
+ * (later tasks) overwrites this with a real semver; until then a stable,
22
+ * obviously-non-real sentinel keeps the manifest valid and self-documenting.
23
+ */
24
+ export declare const PLACEHOLDER_CATALOG_VERSION = "0.0.0-bundled";
25
+ /**
26
+ * Highest catalog **major** version this engine can read (T056, analyze finding
27
+ * E6). The `CatalogManifest.version` is a semver string; its MAJOR component is
28
+ * the content-format compatibility axis.
29
+ *
30
+ * **Compatibility rule:** the engine accepts a manifest whose major version is
31
+ * `<= SUPPORTED_CONTENT_MAJOR` and REJECTS one whose major is strictly greater
32
+ * (an unknown, future, potentially-incompatible content format). Minor/patch
33
+ * bumps within a supported major are always accepted — content is additive
34
+ * within a major, mirroring the additive-via-Zod-defaults policy on the profile
35
+ * side. The bundled baseline (`0.0.0-bundled`, major 0) therefore always passes;
36
+ * only a major we *predate* is rejected.
37
+ *
38
+ * The ceiling is intentionally GENEROUS. The catalog `version` is a plain semver
39
+ * with no historical breaking-format change, so every major published so far is
40
+ * readable by the current YAML/Zod pipeline; the guard exists to fail safe
41
+ * against a hypothetical *far*-future incompatible format rather than to gate
42
+ * routine content bumps. Raise it deliberately when (and only when) a real
43
+ * breaking content-format change ships with a new major.
44
+ *
45
+ * A rejected (too-new) fetched/cached manifest is treated as **invalid remote
46
+ * content** and reuses the existing soft-fallback path (resolve.ts): the fetch
47
+ * fails softly and the resolver falls through to cache → bundled with no
48
+ * user-facing error (FR-027). We never serve content we cannot guarantee we
49
+ * understand, and we never crash on it (FR-025–027).
50
+ */
51
+ export declare const SUPPORTED_CONTENT_MAJOR = 9;
52
+ /**
53
+ * Parse the MAJOR component of a semver-ish version string. Tolerant by design:
54
+ * it reads the leading integer before the first `.` (e.g. `"1.2.3"` → 1,
55
+ * `"0.0.0-bundled"` → 0). Returns `undefined` when no leading integer is present
56
+ * so the caller can decide how to treat an unparseable version.
57
+ */
58
+ export declare const parseMajorVersion: (version: string) => number | undefined;
59
+ /**
60
+ * Whether a {@link CatalogManifest} version is readable by this engine per the
61
+ * {@link SUPPORTED_CONTENT_MAJOR} compatibility rule. An unparseable version is
62
+ * conservatively treated as readable (`true`) — it will still face full Zod
63
+ * validation elsewhere; the major-version guard only ever *rejects* a clearly
64
+ * too-new major, it does not gate on version-string formatting.
65
+ */
66
+ export declare const isContentVersionSupported: (version: string) => boolean;
67
+ /**
68
+ * Build a clear diagnostic for a content version this engine cannot read
69
+ * (major newer than {@link SUPPORTED_CONTENT_MAJOR}). Used as the soft-failure
70
+ * `detail` so logs/tests can see *why* a fetch/cache was rejected (FR-004).
71
+ */
72
+ export declare const contentVersionRejection: (version: string) => string;
73
+ /** A per-file load failure: which file failed and a human-readable reason. */
74
+ export interface CatalogLoadError {
75
+ /** Absolute or caller-relative path of the file that failed to load. */
76
+ readonly file: string;
77
+ /** Path-qualified, human-readable diagnostic (FR-004). */
78
+ readonly message: string;
79
+ }
80
+ /** Outcome of loading a directory of topic files. */
81
+ export interface CatalogLoadResult {
82
+ /** Every topic that parsed and validated cleanly. */
83
+ readonly topics: Topic[];
84
+ /** One entry per file that failed to parse or validate. */
85
+ readonly errors: CatalogLoadError[];
86
+ }
87
+ /**
88
+ * Parse + Zod-validate a single topic from in-memory YAML text into a
89
+ * {@link Topic}. This is the shared content-validation core used by BOTH the
90
+ * on-disk loader ({@link loadTopicFromYaml}) and the network fetcher
91
+ * (`fetcher.ts`), so fetched content runs through the **exact same**
92
+ * {@link TopicSchema} validation before it can ever be cached or served
93
+ * (research E8, FR-004).
94
+ *
95
+ * @param raw - The YAML document text.
96
+ * @param sourceLabel - A label for diagnostics (a file path or a URL); appears
97
+ * in the thrown error messages so failures stay path/source-qualified.
98
+ * @returns The validated topic.
99
+ * @throws {Error} with a source-qualified, human-readable diagnostic if the text
100
+ * is not valid YAML or fails {@link TopicSchema} validation (FR-004). A
101
+ * malformed topic is rejected outright — never partially returned.
102
+ */
103
+ export declare const parseTopicYaml: (raw: string, sourceLabel: string) => Topic;
104
+ /**
105
+ * Read, parse, and validate a single topic YAML file into a {@link Topic}.
106
+ *
107
+ * Thin IO wrapper over {@link parseTopicYaml}: it only adds the file read; the
108
+ * parse + validation (and thus all diagnostics) are shared with the fetcher.
109
+ *
110
+ * @param filePath - Path to a `.yaml`/`.yml` file describing one topic × class.
111
+ * @returns The validated topic.
112
+ * @throws {Error} with a path-qualified, human-readable diagnostic if the file
113
+ * cannot be read, is not valid YAML, or fails {@link TopicSchema} validation
114
+ * (FR-004). The error never partially returns — a malformed topic is rejected
115
+ * outright so it cannot be silently served incorrectly.
116
+ */
117
+ export declare const loadTopicFromYaml: (filePath: string) => Topic;
118
+ /**
119
+ * Recursively load every `.yaml`/`.yml` topic file under `dir`, validating each
120
+ * independently. One bad file does NOT abort the load: valid topics are
121
+ * collected and every failure is reported as a {@link CatalogLoadError} so the
122
+ * caller can surface a clear diagnostic while still serving the good content
123
+ * (FR-004). Files are sorted by path for deterministic ordering.
124
+ *
125
+ * Subdirectories (`general/`, `claude-code/`, etc.) are walked transparently —
126
+ * the directory layout is an authoring convenience; the `(id, class)` identity
127
+ * lives inside each file.
128
+ *
129
+ * @param dir - Directory root to scan for topic files.
130
+ */
131
+ export declare const loadCatalogFromDir: (dir: string) => CatalogLoadResult;
132
+ /** Options for {@link buildManifest}. */
133
+ export interface BuildManifestOptions {
134
+ /**
135
+ * Catalog version (semver). Defaults to {@link PLACEHOLDER_CATALOG_VERSION}
136
+ * when omitted and no `version` can be read from a manifest file. The real
137
+ * version is supplied by the fetch/publish layer in a later task.
138
+ */
139
+ readonly version?: string;
140
+ /**
141
+ * `publishedAt` timestamp (ISO datetime). Defaults to "now" at call time.
142
+ */
143
+ readonly publishedAt?: string;
144
+ /**
145
+ * Root directory the topics were loaded from. When provided, each manifest
146
+ * topic's `file` is recorded relative to this root for a portable index;
147
+ * otherwise the synthesized `<class-token>/<id>.yaml` convention is used.
148
+ */
149
+ readonly sourceDir?: string;
150
+ }
151
+ /**
152
+ * Derive a {@link CatalogManifest} (version + fast topic index) from a set of
153
+ * validated topics. The manifest is the lightweight listing the runtime uses to
154
+ * enumerate topics without re-reading every file.
155
+ *
156
+ * `version` resolution order: explicit `options.version` → otherwise the
157
+ * documented {@link PLACEHOLDER_CATALOG_VERSION} sentinel. (A future task may
158
+ * read it from a manifest file shipped alongside the catalog; the option hook
159
+ * is in place for that.)
160
+ *
161
+ * @param topics - Topics that have already passed {@link TopicSchema}.
162
+ * @param options - Version/timestamp/source-dir overrides.
163
+ */
164
+ export declare const buildManifest: (topics: readonly Topic[], options?: BuildManifestOptions) => CatalogManifest;
165
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/catalog/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,KAAK,EACX,MAAM,uBAAuB,CAAC;AAE/B;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,kBAAkB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,KAAG,MAAM,GAAG,SAK5D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,MAAM,KAAG,OAI3D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAAI,SAAS,MAAM,KAAG,MAE0B,CAAC;AAErF,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,qDAAqD;AACrD,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;CACrC;AAsBD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,EAAE,aAAa,MAAM,KAAG,KAgBjE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,KAAG,KAWpD,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,KAAG,iBAsBhD,CAAC;AAEF,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAMD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,SAAS,KAAK,EAAE,EACxB,UAAS,oBAAyB,KACjC,eA8BF,CAAC"}
@@ -0,0 +1,241 @@
1
+ /**
2
+ * @file Content catalog loader (T015).
3
+ *
4
+ * Reads YAML topic files from disk, parses them with `js-yaml`, and validates
5
+ * each against {@link TopicSchema}. Authoring format is YAML (research OD-004):
6
+ * one file per `(topic × class)` carrying every tier and trigger signal
7
+ * (FR-004a). Validation is the load-time gate that prevents malformed content
8
+ * from ever being served (FR-004) — a bad file is reported, never silently
9
+ * served incorrectly.
10
+ *
11
+ * IO is intentionally thin (read file, list directory); the logic that matters
12
+ * is parse + Zod validation + path-qualified diagnostics.
13
+ *
14
+ * Source of truth: specs/001-vibe-hero-mvp/data-model.md (§ Content Catalog),
15
+ * spec FR-001/003a/004/004a/025, research.md OD-004.
16
+ */
17
+ import { globSync, readFileSync } from "node:fs";
18
+ import { relative } from "node:path";
19
+ import { load as parseYaml } from "js-yaml";
20
+ import { CatalogManifestSchema, TopicSchema, } from "../schemas/content.js";
21
+ /**
22
+ * Placeholder catalog version used by {@link buildManifest} when no explicit
23
+ * version is supplied and no manifest file is present. The fetch/publish layer
24
+ * (later tasks) overwrites this with a real semver; until then a stable,
25
+ * obviously-non-real sentinel keeps the manifest valid and self-documenting.
26
+ */
27
+ export const PLACEHOLDER_CATALOG_VERSION = "0.0.0-bundled";
28
+ /**
29
+ * Highest catalog **major** version this engine can read (T056, analyze finding
30
+ * E6). The `CatalogManifest.version` is a semver string; its MAJOR component is
31
+ * the content-format compatibility axis.
32
+ *
33
+ * **Compatibility rule:** the engine accepts a manifest whose major version is
34
+ * `<= SUPPORTED_CONTENT_MAJOR` and REJECTS one whose major is strictly greater
35
+ * (an unknown, future, potentially-incompatible content format). Minor/patch
36
+ * bumps within a supported major are always accepted — content is additive
37
+ * within a major, mirroring the additive-via-Zod-defaults policy on the profile
38
+ * side. The bundled baseline (`0.0.0-bundled`, major 0) therefore always passes;
39
+ * only a major we *predate* is rejected.
40
+ *
41
+ * The ceiling is intentionally GENEROUS. The catalog `version` is a plain semver
42
+ * with no historical breaking-format change, so every major published so far is
43
+ * readable by the current YAML/Zod pipeline; the guard exists to fail safe
44
+ * against a hypothetical *far*-future incompatible format rather than to gate
45
+ * routine content bumps. Raise it deliberately when (and only when) a real
46
+ * breaking content-format change ships with a new major.
47
+ *
48
+ * A rejected (too-new) fetched/cached manifest is treated as **invalid remote
49
+ * content** and reuses the existing soft-fallback path (resolve.ts): the fetch
50
+ * fails softly and the resolver falls through to cache → bundled with no
51
+ * user-facing error (FR-027). We never serve content we cannot guarantee we
52
+ * understand, and we never crash on it (FR-025–027).
53
+ */
54
+ export const SUPPORTED_CONTENT_MAJOR = 9;
55
+ /**
56
+ * Parse the MAJOR component of a semver-ish version string. Tolerant by design:
57
+ * it reads the leading integer before the first `.` (e.g. `"1.2.3"` → 1,
58
+ * `"0.0.0-bundled"` → 0). Returns `undefined` when no leading integer is present
59
+ * so the caller can decide how to treat an unparseable version.
60
+ */
61
+ export const parseMajorVersion = (version) => {
62
+ const match = /^(\d+)\b/.exec(version.trim());
63
+ if (match === null)
64
+ return undefined;
65
+ const major = Number.parseInt(match[1], 10);
66
+ return Number.isNaN(major) ? undefined : major;
67
+ };
68
+ /**
69
+ * Whether a {@link CatalogManifest} version is readable by this engine per the
70
+ * {@link SUPPORTED_CONTENT_MAJOR} compatibility rule. An unparseable version is
71
+ * conservatively treated as readable (`true`) — it will still face full Zod
72
+ * validation elsewhere; the major-version guard only ever *rejects* a clearly
73
+ * too-new major, it does not gate on version-string formatting.
74
+ */
75
+ export const isContentVersionSupported = (version) => {
76
+ const major = parseMajorVersion(version);
77
+ if (major === undefined)
78
+ return true;
79
+ return major <= SUPPORTED_CONTENT_MAJOR;
80
+ };
81
+ /**
82
+ * Build a clear diagnostic for a content version this engine cannot read
83
+ * (major newer than {@link SUPPORTED_CONTENT_MAJOR}). Used as the soft-failure
84
+ * `detail` so logs/tests can see *why* a fetch/cache was rejected (FR-004).
85
+ */
86
+ export const contentVersionRejection = (version) => `catalog version "${version}" has a major newer than this engine supports ` +
87
+ `(max major ${SUPPORTED_CONTENT_MAJOR}); refusing to serve unknown content format`;
88
+ /**
89
+ * Format a Zod error into a multi-line, path-qualified diagnostic that names
90
+ * the offending file and each failing field path (FR-004). Example:
91
+ *
92
+ * ```
93
+ * Invalid topic in /catalog/general/subagents.yaml:
94
+ * - items.0.choices: multiple_choice requires at least 2 choices
95
+ * - items.1.answerKey: short_answer requires an answerKey of kind "keyword"
96
+ * ```
97
+ */
98
+ const formatZodError = (filePath, error) => {
99
+ const issues = error.issues
100
+ .map((issue) => {
101
+ const path = issue.path.length > 0 ? issue.path.join(".") : "<root>";
102
+ return ` - ${path}: ${issue.message}`;
103
+ })
104
+ .join("\n");
105
+ return `Invalid topic in ${filePath}:\n${issues}`;
106
+ };
107
+ /**
108
+ * Parse + Zod-validate a single topic from in-memory YAML text into a
109
+ * {@link Topic}. This is the shared content-validation core used by BOTH the
110
+ * on-disk loader ({@link loadTopicFromYaml}) and the network fetcher
111
+ * (`fetcher.ts`), so fetched content runs through the **exact same**
112
+ * {@link TopicSchema} validation before it can ever be cached or served
113
+ * (research E8, FR-004).
114
+ *
115
+ * @param raw - The YAML document text.
116
+ * @param sourceLabel - A label for diagnostics (a file path or a URL); appears
117
+ * in the thrown error messages so failures stay path/source-qualified.
118
+ * @returns The validated topic.
119
+ * @throws {Error} with a source-qualified, human-readable diagnostic if the text
120
+ * is not valid YAML or fails {@link TopicSchema} validation (FR-004). A
121
+ * malformed topic is rejected outright — never partially returned.
122
+ */
123
+ export const parseTopicYaml = (raw, sourceLabel) => {
124
+ let parsed;
125
+ try {
126
+ parsed = parseYaml(raw, { filename: sourceLabel });
127
+ }
128
+ catch (cause) {
129
+ const reason = cause instanceof Error ? cause.message : String(cause);
130
+ throw new Error(`Invalid YAML in ${sourceLabel}: ${reason}`, { cause });
131
+ }
132
+ const result = TopicSchema.safeParse(parsed);
133
+ if (!result.success) {
134
+ throw new Error(formatZodError(sourceLabel, result.error), {
135
+ cause: result.error,
136
+ });
137
+ }
138
+ return result.data;
139
+ };
140
+ /**
141
+ * Read, parse, and validate a single topic YAML file into a {@link Topic}.
142
+ *
143
+ * Thin IO wrapper over {@link parseTopicYaml}: it only adds the file read; the
144
+ * parse + validation (and thus all diagnostics) are shared with the fetcher.
145
+ *
146
+ * @param filePath - Path to a `.yaml`/`.yml` file describing one topic × class.
147
+ * @returns The validated topic.
148
+ * @throws {Error} with a path-qualified, human-readable diagnostic if the file
149
+ * cannot be read, is not valid YAML, or fails {@link TopicSchema} validation
150
+ * (FR-004). The error never partially returns — a malformed topic is rejected
151
+ * outright so it cannot be silently served incorrectly.
152
+ */
153
+ export const loadTopicFromYaml = (filePath) => {
154
+ let raw;
155
+ try {
156
+ raw = readFileSync(filePath, "utf8");
157
+ }
158
+ catch (cause) {
159
+ const reason = cause instanceof Error ? cause.message : String(cause);
160
+ throw new Error(`Cannot read topic file ${filePath}: ${reason}`, {
161
+ cause,
162
+ });
163
+ }
164
+ return parseTopicYaml(raw, filePath);
165
+ };
166
+ /**
167
+ * Recursively load every `.yaml`/`.yml` topic file under `dir`, validating each
168
+ * independently. One bad file does NOT abort the load: valid topics are
169
+ * collected and every failure is reported as a {@link CatalogLoadError} so the
170
+ * caller can surface a clear diagnostic while still serving the good content
171
+ * (FR-004). Files are sorted by path for deterministic ordering.
172
+ *
173
+ * Subdirectories (`general/`, `claude-code/`, etc.) are walked transparently —
174
+ * the directory layout is an authoring convenience; the `(id, class)` identity
175
+ * lives inside each file.
176
+ *
177
+ * @param dir - Directory root to scan for topic files.
178
+ */
179
+ export const loadCatalogFromDir = (dir) => {
180
+ const matches = globSync("**/*.{yaml,yml}", { cwd: dir });
181
+ // Resolve to absolute paths and sort for deterministic, reproducible loads.
182
+ const files = matches
183
+ .map((m) => `${dir}/${m}`)
184
+ .sort((a, b) => a.localeCompare(b));
185
+ const topics = [];
186
+ const errors = [];
187
+ for (const file of files) {
188
+ try {
189
+ topics.push(loadTopicFromYaml(file));
190
+ }
191
+ catch (cause) {
192
+ errors.push({
193
+ file,
194
+ message: cause instanceof Error ? cause.message : String(cause),
195
+ });
196
+ }
197
+ }
198
+ return { topics, errors };
199
+ };
200
+ /** Serialize a {@link Topic.class} into a stable directory/token prefix. */
201
+ const classToken = (cls) => cls.kind === "general" ? "general" : cls.tool;
202
+ /**
203
+ * Derive a {@link CatalogManifest} (version + fast topic index) from a set of
204
+ * validated topics. The manifest is the lightweight listing the runtime uses to
205
+ * enumerate topics without re-reading every file.
206
+ *
207
+ * `version` resolution order: explicit `options.version` → otherwise the
208
+ * documented {@link PLACEHOLDER_CATALOG_VERSION} sentinel. (A future task may
209
+ * read it from a manifest file shipped alongside the catalog; the option hook
210
+ * is in place for that.)
211
+ *
212
+ * @param topics - Topics that have already passed {@link TopicSchema}.
213
+ * @param options - Version/timestamp/source-dir overrides.
214
+ */
215
+ export const buildManifest = (topics, options = {}) => {
216
+ const version = options.version ?? PLACEHOLDER_CATALOG_VERSION;
217
+ const publishedAt = options.publishedAt ?? new Date().toISOString();
218
+ const sourceDir = options.sourceDir;
219
+ const manifest = {
220
+ version,
221
+ publishedAt,
222
+ topics: topics.map((topic) => {
223
+ // Distinct, sorted tiers present in this topic's items.
224
+ const tiers = [...new Set(topic.items.map((item) => item.tier))].sort((a, b) => a - b);
225
+ const file = sourceDir !== undefined
226
+ ? relative(sourceDir, `${classToken(topic.class)}/${topic.id}.yaml`)
227
+ : `${classToken(topic.class)}/${topic.id}.yaml`;
228
+ return {
229
+ id: topic.id,
230
+ class: topic.class,
231
+ file,
232
+ itemCount: topic.items.length,
233
+ tiers,
234
+ };
235
+ }),
236
+ };
237
+ // Validate the synthesized manifest so a programming error here surfaces the
238
+ // same way a bad topic file would, rather than emitting a subtly-wrong index.
239
+ return CatalogManifestSchema.parse(manifest);
240
+ };
241
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/catalog/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @file Catalog resolution order: fresh-fetch → cache → bundled (T054).
3
+ *
4
+ * Decides which catalog the runtime serves, honoring the spec's freshness +
5
+ * offline-resilience contract (FR-025/026/027, SC-006/007):
6
+ *
7
+ * 1. **fresh-fetch** — if a content source is configured AND reachable AND the
8
+ * fetched content is valid (Zod-validated BEFORE caching, research E8), use
9
+ * it and update the cache.
10
+ * 2. **cache** — otherwise, if a previously-fetched cache exists, serve it
11
+ * (covers: offline, source unreachable, 304 not-modified, invalid remote).
12
+ * 3. **bundled** — otherwise serve the in-package bundled snapshot (FR-025),
13
+ * so the product ALWAYS works offline / on first run with no network.
14
+ *
15
+ * Every remote failure is **silent** to the user (FR-027): an offline / 4xx-5xx
16
+ * / timeout / DNS / invalid-content situation simply downgrades the source and
17
+ * serves the next tier; no error surfaces. The `source` discriminator lets
18
+ * callers/tests observe which tier won without changing behavior.
19
+ *
20
+ * `catalogVersion` is taken from the winning manifest so `list_topics` reports a
21
+ * version that **advances after an update** (SC-007): bundled →
22
+ * `PLACEHOLDER_CATALOG_VERSION`; fetched/cached → the published manifest semver.
23
+ *
24
+ * ## Default behavior preserves the existing tools
25
+ *
26
+ * When no content URL is configured (the default), step 1 is `disabled` and, if
27
+ * no cache exists, the resolver returns the **bundled** catalog — exactly what
28
+ * the tools served before this task. So switching a tool from
29
+ * `loadBundledCatalog()` to `resolveCatalog()` is behavior-preserving offline
30
+ * (keeps the 124 existing tests green); fetching only ever engages when a URL is
31
+ * explicitly set.
32
+ *
33
+ * Source of truth: spec FR-025/026/027, SC-006/007, research.md E8,
34
+ * contracts/mcp-tools.md (`list_topics` → `catalogVersion`).
35
+ */
36
+ import { type CatalogLoadError } from "./loader.js";
37
+ import { type FetchImpl } from "./fetcher.js";
38
+ import type { Topic } from "../schemas/content.js";
39
+ /** Which tier of the resolution order produced the served catalog. */
40
+ export type CatalogSource = "fetched" | "cache" | "bundled";
41
+ /** The resolved catalog the runtime serves. */
42
+ export interface ResolvedCatalog {
43
+ /** The topics to serve (already Zod-validated for every source). */
44
+ readonly topics: Topic[];
45
+ /** The catalog version of the winning source (advances after an update). */
46
+ readonly catalogVersion: string;
47
+ /** Which tier of the order won — observability/test seam, never user-facing. */
48
+ readonly source: CatalogSource;
49
+ /**
50
+ * Per-file load errors from the bundled snapshot, when it is the served
51
+ * source. Empty for fetched/cache (those validate the whole catalog up front
52
+ * and reject any invalid file). Mirrors {@link loadBundledCatalog}'s contract.
53
+ */
54
+ readonly errors: CatalogLoadError[];
55
+ }
56
+ /** Options controlling {@link resolveCatalog}. */
57
+ export interface ResolveOptions {
58
+ /**
59
+ * Whether to attempt a fresh network fetch this resolution. Defaults to
60
+ * `true`, but a fetch only actually happens when a content URL is configured
61
+ * (otherwise it is reported `disabled` and we fall through). Pass `false` to
62
+ * force a cache/bundled resolution without touching the network at all.
63
+ */
64
+ readonly fetch?: boolean;
65
+ /** Published content base URL (overrides `VIBE_HERO_CONTENT_URL`). */
66
+ readonly contentUrl?: string;
67
+ /** Injected `fetch` (test seam); defaults to the global `fetch`. */
68
+ readonly fetchImpl?: FetchImpl;
69
+ /** Per-request fetch timeout (ms). */
70
+ readonly timeoutMs?: number;
71
+ }
72
+ /**
73
+ * Resolve the catalog to serve using the **fresh-fetch → cache → bundled** order.
74
+ *
75
+ * Asynchronous because the fetch + cache tiers do IO. Never throws: a remote or
76
+ * cache failure silently degrades to the next tier and ultimately the bundled
77
+ * snapshot, which is always present (FR-027, SC-006).
78
+ *
79
+ * @param dirOverride - Profile-home override (test seam) used for the cache dir
80
+ * (sibling of the profile dir, same `VIBE_HERO_HOME` seam).
81
+ * @param options - Fetch toggle, source URL, injected fetch, timeout.
82
+ * @returns The resolved catalog with its version and winning source.
83
+ */
84
+ export declare const resolveCatalog: (dirOverride?: string, options?: ResolveOptions) => Promise<ResolvedCatalog>;
85
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/catalog/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAE5D,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC;CACrC;AAED,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GACzB,cAAc,MAAM,EACpB,UAAS,cAAmB,KAC3B,OAAO,CAAC,eAAe,CA0CzB,CAAC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * @file Catalog resolution order: fresh-fetch → cache → bundled (T054).
3
+ *
4
+ * Decides which catalog the runtime serves, honoring the spec's freshness +
5
+ * offline-resilience contract (FR-025/026/027, SC-006/007):
6
+ *
7
+ * 1. **fresh-fetch** — if a content source is configured AND reachable AND the
8
+ * fetched content is valid (Zod-validated BEFORE caching, research E8), use
9
+ * it and update the cache.
10
+ * 2. **cache** — otherwise, if a previously-fetched cache exists, serve it
11
+ * (covers: offline, source unreachable, 304 not-modified, invalid remote).
12
+ * 3. **bundled** — otherwise serve the in-package bundled snapshot (FR-025),
13
+ * so the product ALWAYS works offline / on first run with no network.
14
+ *
15
+ * Every remote failure is **silent** to the user (FR-027): an offline / 4xx-5xx
16
+ * / timeout / DNS / invalid-content situation simply downgrades the source and
17
+ * serves the next tier; no error surfaces. The `source` discriminator lets
18
+ * callers/tests observe which tier won without changing behavior.
19
+ *
20
+ * `catalogVersion` is taken from the winning manifest so `list_topics` reports a
21
+ * version that **advances after an update** (SC-007): bundled →
22
+ * `PLACEHOLDER_CATALOG_VERSION`; fetched/cached → the published manifest semver.
23
+ *
24
+ * ## Default behavior preserves the existing tools
25
+ *
26
+ * When no content URL is configured (the default), step 1 is `disabled` and, if
27
+ * no cache exists, the resolver returns the **bundled** catalog — exactly what
28
+ * the tools served before this task. So switching a tool from
29
+ * `loadBundledCatalog()` to `resolveCatalog()` is behavior-preserving offline
30
+ * (keeps the 124 existing tests green); fetching only ever engages when a URL is
31
+ * explicitly set.
32
+ *
33
+ * Source of truth: spec FR-025/026/027, SC-006/007, research.md E8,
34
+ * contracts/mcp-tools.md (`list_topics` → `catalogVersion`).
35
+ */
36
+ import { loadBundledCatalog } from "./bundled/index.js";
37
+ import { buildManifest, PLACEHOLDER_CATALOG_VERSION, } from "./loader.js";
38
+ import { readCachedCatalog, refreshCatalogCache, } from "./fetcher.js";
39
+ /**
40
+ * Resolve the catalog to serve using the **fresh-fetch → cache → bundled** order.
41
+ *
42
+ * Asynchronous because the fetch + cache tiers do IO. Never throws: a remote or
43
+ * cache failure silently degrades to the next tier and ultimately the bundled
44
+ * snapshot, which is always present (FR-027, SC-006).
45
+ *
46
+ * @param dirOverride - Profile-home override (test seam) used for the cache dir
47
+ * (sibling of the profile dir, same `VIBE_HERO_HOME` seam).
48
+ * @param options - Fetch toggle, source URL, injected fetch, timeout.
49
+ * @returns The resolved catalog with its version and winning source.
50
+ */
51
+ export const resolveCatalog = async (dirOverride, options = {}) => {
52
+ const tryFetch = options.fetch ?? true;
53
+ // --- 1. fresh-fetch (only if enabled + a source is configured) -----------
54
+ if (tryFetch) {
55
+ // Build the fetch options immutably, omitting absent keys so
56
+ // `exactOptionalPropertyTypes` is satisfied (no `undefined` assignments).
57
+ const fetchOpts = {
58
+ ...(options.contentUrl !== undefined ? { contentUrl: options.contentUrl } : {}),
59
+ ...(options.fetchImpl !== undefined ? { fetchImpl: options.fetchImpl } : {}),
60
+ ...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
61
+ };
62
+ const outcome = await refreshCatalogCache(dirOverride, fetchOpts);
63
+ if (outcome.ok) {
64
+ return {
65
+ topics: outcome.catalog.topics,
66
+ catalogVersion: outcome.catalog.manifest.version,
67
+ source: "fetched",
68
+ errors: [],
69
+ };
70
+ }
71
+ // disabled / not_modified / unreachable / invalid all fall through to the
72
+ // cache tier — silently, no user-facing error (FR-027). For not_modified
73
+ // and a write-skipped success, the cache below already holds the content.
74
+ }
75
+ // --- 2. cache (a prior successful fetch) ---------------------------------
76
+ const cached = await readCachedCatalog(dirOverride);
77
+ if (cached !== undefined) {
78
+ return {
79
+ topics: cached.topics,
80
+ catalogVersion: cached.manifest.version,
81
+ source: "cache",
82
+ errors: [],
83
+ };
84
+ }
85
+ // --- 3. bundled (always present; offline / first-run guarantee) ----------
86
+ const { topics, errors } = loadBundledCatalog();
87
+ const version = bundledVersion(topics);
88
+ return { topics, catalogVersion: version, source: "bundled", errors };
89
+ };
90
+ /**
91
+ * Derive the version reported for the bundled snapshot. {@link buildManifest}
92
+ * stamps {@link PLACEHOLDER_CATALOG_VERSION} when no explicit version is given,
93
+ * which is exactly the right "this is the un-versioned baseline" signal — a real
94
+ * fetched/cached version is a semver and thus always compares as newer.
95
+ */
96
+ const bundledVersion = (topics) => {
97
+ // buildManifest validates and stamps the placeholder version; reuse it so the
98
+ // bundled version stays consistent with the manifest the tools build elsewhere.
99
+ if (topics.length === 0)
100
+ return PLACEHOLDER_CATALOG_VERSION;
101
+ return buildManifest(topics).version;
102
+ };
103
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/catalog/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,aAAa,EACb,2BAA2B,GAE5B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,GAEpB,MAAM,cAAc,CAAC;AAuCtB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,WAAoB,EACpB,UAA0B,EAAE,EACF,EAAE;IAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC;IAEvC,4EAA4E;IAC5E,IAAI,QAAQ,EAAE,CAAC;QACb,6DAA6D;QAC7D,0EAA0E;QAC1E,MAAM,SAAS,GAA8C;YAC3D,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5E,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7E,CAAC;QAEF,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAClE,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;YACf,OAAO;gBACL,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM;gBAC9B,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAChD,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,EAAE;aACX,CAAC;QACJ,CAAC;QACD,0EAA0E;QAC1E,yEAAyE;QACzE,0EAA0E;IAC5E,CAAC;IAED,4EAA4E;IAC5E,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACpD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,OAAO;YACvC,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,EAAE;SACX,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACxE,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,cAAc,GAAG,CAAC,MAAwB,EAAU,EAAE;IAC1D,8EAA8E;IAC9E,gFAAgF;IAChF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,2BAA2B,CAAC;IAC5D,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;AACvC,CAAC,CAAC"}