@openspecui/core 3.5.2 → 3.6.1

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 (50) hide show
  1. package/dist/hosted-app.d.mts +1 -1
  2. package/dist/hosted-app.mjs +1 -1
  3. package/dist/index.d.mts +74 -632
  4. package/dist/index.mjs +81 -97
  5. package/dist/markdown-facts-BmSmZmpB.mjs +136 -0
  6. package/dist/markdown-facts-f3kXnqXb.d.mts +39 -0
  7. package/dist/markdown-facts.d.mts +2 -0
  8. package/dist/markdown-facts.mjs +3 -0
  9. package/dist/markdown-reading-CrchEfoW.mjs +104 -0
  10. package/dist/markdown-reading-D36W693c.d.mts +74 -0
  11. package/dist/markdown-reading.d.mts +3 -0
  12. package/dist/markdown-reading.mjs +4 -0
  13. package/dist/{notifications-BWvRNkRJ.d.mts → notifications-CCV2bgWG.d.mts} +9 -9
  14. package/dist/{notifications-F81mmO55.mjs → notifications-fD-V5hyP.mjs} +2 -2
  15. package/dist/notifications.d.mts +2 -2
  16. package/dist/notifications.mjs +3 -3
  17. package/dist/openspec-annotations-BMy9nWUe.mjs +436 -0
  18. package/dist/openspec-annotations-CJmYcfAu.d.mts +30 -0
  19. package/dist/openspec-annotations.d.mts +4 -0
  20. package/dist/openspec-annotations.mjs +5 -0
  21. package/dist/openspec-projection-DWqBxedv.mjs +223 -0
  22. package/dist/openspec-projection-DmB448No.d.mts +1142 -0
  23. package/dist/openspec-projection.d.mts +5 -0
  24. package/dist/openspec-projection.mjs +6 -0
  25. package/dist/opsx-display-path.d.mts +1 -1
  26. package/dist/opsx-display-path.mjs +1 -1
  27. package/dist/{sounds-Bw-sSyFZ.d.mts → sounds-B0sH3QwE.d.mts} +5 -5
  28. package/dist/sounds.d.mts +1 -1
  29. package/dist/sounds.mjs +1 -1
  30. package/dist/{terminal-audio-DDwxz9sJ.mjs → terminal-audio-UEv3j655.mjs} +1 -1
  31. package/dist/{terminal-audio-8E82E0AM.d.mts → terminal-audio-qSc6nZUI.d.mts} +2 -2
  32. package/dist/terminal-audio.d.mts +2 -2
  33. package/dist/terminal-audio.mjs +2 -2
  34. package/dist/terminal-control.d.mts +2 -2
  35. package/dist/terminal-control.mjs +1 -1
  36. package/dist/{terminal-invocation-CpdllJff.d.mts → terminal-invocation-BCqjtd4p.d.mts} +36 -36
  37. package/dist/terminal-invocation.d.mts +1 -1
  38. package/dist/terminal-invocation.mjs +1 -1
  39. package/dist/terminal-theme.d.mts +1 -1
  40. package/dist/terminal-theme.mjs +1 -1
  41. package/package.json +25 -3
  42. /package/dist/{hosted-app-CIOJpbzc.mjs → hosted-app-DFFffbJc.mjs} +0 -0
  43. /package/dist/{hosted-app-DaGUbBJn.d.mts → hosted-app-DZrYivji.d.mts} +0 -0
  44. /package/dist/{opsx-display-path-CuQyGB_A.d.mts → opsx-display-path-CkV9sq_j.d.mts} +0 -0
  45. /package/dist/{opsx-display-path-B6Owu17P.mjs → opsx-display-path-D4KLYRXQ.mjs} +0 -0
  46. /package/dist/{sounds-C0dNSFm8.mjs → sounds-BzNKMW05.mjs} +0 -0
  47. /package/dist/{terminal-control-DtBprY6-.mjs → terminal-control-Bxois59k.mjs} +0 -0
  48. /package/dist/{terminal-invocation-Cdi6_Kl6.mjs → terminal-invocation-BRCuSBjE.mjs} +0 -0
  49. /package/dist/{terminal-theme-CMQqJvIQ.mjs → terminal-theme-CIv3YMfi.mjs} +0 -0
  50. /package/dist/{terminal-theme-wbkK9vVH.d.mts → terminal-theme-lPZGfVA_.d.mts} +0 -0
@@ -0,0 +1,223 @@
1
+ import { c as getMarkdownHeadingFacts, l as trimMarkdownSlice, n as createMarkdownReadingDocument, o as getMarkdownFactSpan, s as getMarkdownHeadingEnd } from "./markdown-reading-CrchEfoW.mjs";
2
+ import { r as builtinOpenSpecReadingPlugin } from "./openspec-annotations-BMy9nWUe.mjs";
3
+
4
+ //#region src/openspec-projection.ts
5
+ const OPEN_SPEC_SPEC_PROJECTION_ID = "openspec.projection.spec.v2";
6
+ const OPEN_SPEC_READING_SECTIONS_PROJECTION_ID = "openspec.projection.reading-sections.v2";
7
+ function createOpenSpecReadingPlugin(options) {
8
+ return {
9
+ ...builtinOpenSpecReadingPlugin,
10
+ id: "openspec.builtin-reading-with-projections.v2",
11
+ projectionRules: [createOpenSpecReadingSectionsProjectionRule(), createOpenSpecSpecProjectionRule(options)]
12
+ };
13
+ }
14
+ function parseOpenSpecMarkdownToSpec(specId, content) {
15
+ return projectOpenSpecMarkdown(content, { specId }).projections[OPEN_SPEC_SPEC_PROJECTION_ID];
16
+ }
17
+ function projectOpenSpecMarkdown(sourceMarkdown, options, plugins = [createOpenSpecReadingPlugin(options)]) {
18
+ return toProjectedOpenSpecDocument(createMarkdownReadingDocument(sourceMarkdown, plugins));
19
+ }
20
+ function projectAnnotatedOpenSpecToSpec(specId, document) {
21
+ return projectOpenSpecContextToSpec(createDetachedProjectionContext(document), { specId });
22
+ }
23
+ function getOpenSpecReadingSections(document) {
24
+ const context = createDetachedProjectionContext(document);
25
+ return {
26
+ sections: collectSpecSections(context),
27
+ requirements: collectRequirementBlocks(context)
28
+ };
29
+ }
30
+ function getOpenSpecProjectionAnnotation(annotations, factId, kind) {
31
+ return annotations.find((annotation) => annotation.targetFactId === factId && annotation.kind === kind);
32
+ }
33
+ function createOpenSpecReadingSectionsProjectionRule() {
34
+ return {
35
+ id: OPEN_SPEC_READING_SECTIONS_PROJECTION_ID,
36
+ project(context) {
37
+ return {
38
+ sections: collectSpecSections(toOpenSpecProjectionContext(context)),
39
+ requirements: collectRequirementBlocks(toOpenSpecProjectionContext(context))
40
+ };
41
+ }
42
+ };
43
+ }
44
+ function createOpenSpecSpecProjectionRule(options) {
45
+ return {
46
+ id: OPEN_SPEC_SPEC_PROJECTION_ID,
47
+ project(context) {
48
+ return projectOpenSpecContextToSpec(toOpenSpecProjectionContext(context), options);
49
+ }
50
+ };
51
+ }
52
+ function projectOpenSpecContextToSpec(context, options) {
53
+ const name = context.annotations.find((annotation) => annotation.kind === "document-title")?.metadata?.title || options.specId;
54
+ const overviewSection = collectSpecSections(context).find((section) => section.kind === "overview");
55
+ const overview = overviewSection ? trimMarkdownSlice(context.sourceMarkdown, getContentStartAfterHeading(context, overviewSection.factId, overviewSection.start), overviewSection.end) : "";
56
+ const requirements = collectRequirementBlocks(context).map((requirement) => projectRequirement(context, requirement));
57
+ return {
58
+ id: options.specId,
59
+ name: name || options.specId,
60
+ overview: overview.trim(),
61
+ requirements,
62
+ metadata: {
63
+ version: "1.0.0",
64
+ format: "openspec"
65
+ }
66
+ };
67
+ }
68
+ function createRequirementText(title, bodyMarkdown, scenarioText) {
69
+ return [
70
+ title,
71
+ bodyMarkdown,
72
+ scenarioText
73
+ ].filter((part) => part.trim()).join("\n\n");
74
+ }
75
+ function collectSpecSections(context) {
76
+ const headings = getMarkdownHeadingFacts(context);
77
+ return headings.reduce((sections, fact, index) => {
78
+ if (fact.depth !== 2) return sections;
79
+ const span = getFactSpan(fact);
80
+ if (!span) return sections;
81
+ sections.push({
82
+ id: fact.id,
83
+ title: fact.text,
84
+ kind: getSectionKind(context.annotations, fact.id),
85
+ factId: fact.id,
86
+ start: span.start,
87
+ end: getMarkdownHeadingEnd(headings, index, context.sourceMarkdown.length)
88
+ });
89
+ return sections;
90
+ }, []);
91
+ }
92
+ function collectRequirementBlocks(context) {
93
+ const headings = getMarkdownHeadingFacts(context);
94
+ let reqIndex = 0;
95
+ return headings.reduce((requirements, fact, index) => {
96
+ const annotation = getOpenSpecProjectionAnnotation(context.annotations, fact.id, "requirement");
97
+ if (!annotation) return requirements;
98
+ const span = getFactSpan(fact);
99
+ if (!span) return requirements;
100
+ reqIndex++;
101
+ const end = getMarkdownHeadingEnd(headings, index, context.sourceMarkdown.length);
102
+ const title = annotation.metadata?.title?.trim() || fact.text;
103
+ requirements.push({
104
+ id: `req-${reqIndex}`,
105
+ title,
106
+ factId: fact.id,
107
+ start: span.start,
108
+ end,
109
+ scenarios: collectScenarioBlocks(context, headings, fact, end)
110
+ });
111
+ return requirements;
112
+ }, []);
113
+ }
114
+ function collectScenarioBlocks(context, headings, requirementFact, requirementEnd) {
115
+ const requirementSpan = getFactSpan(requirementFact);
116
+ if (!requirementSpan) return [];
117
+ return headings.reduce((scenarios, fact, index) => {
118
+ const annotation = getOpenSpecProjectionAnnotation(context.annotations, fact.id, "scenario");
119
+ if (!annotation) return scenarios;
120
+ const span = getFactSpan(fact);
121
+ if (!span || span.start <= requirementSpan.start || span.start >= requirementEnd) return scenarios;
122
+ scenarios.push({
123
+ title: annotation.metadata?.title?.trim() || fact.text,
124
+ factId: fact.id,
125
+ start: span.start,
126
+ end: Math.min(getScenarioEnd(context, headings, index, requirementEnd), requirementEnd)
127
+ });
128
+ return scenarios;
129
+ }, []);
130
+ }
131
+ function getScenarioEnd(context, headings, scenarioIndex, requirementEnd) {
132
+ for (let i = scenarioIndex + 1; i < headings.length; i++) {
133
+ const next = headings[i];
134
+ const nextSpan = getFactSpan(next);
135
+ if (!nextSpan || nextSpan.start >= requirementEnd) return requirementEnd;
136
+ if ((next.depth ?? 6) <= 3 || getOpenSpecProjectionAnnotation(context.annotations, next.id, "scenario")) return nextSpan.start;
137
+ }
138
+ return requirementEnd;
139
+ }
140
+ function getContentStartAfterHeading(context, factId, fallback) {
141
+ const fact = context.factById.get(factId);
142
+ return fact ? getFactSpan(fact)?.end ?? fallback : fallback;
143
+ }
144
+ function projectScenario(context, scenario) {
145
+ const bodyMarkdown = trimMarkdownSlice(context.sourceMarkdown, getContentStartAfterHeading(context, scenario.factId, scenario.start), scenario.end);
146
+ const rawText = [scenario.title, bodyMarkdown].filter((part) => part.trim()).join("\n");
147
+ return {
148
+ title: scenario.title,
149
+ bodyMarkdown,
150
+ rawText,
151
+ steps: getScenarioStepsFromAnnotations(context, scenario)
152
+ };
153
+ }
154
+ function getScenarioStepsFromAnnotations(context, scenario) {
155
+ return context.annotations.reduce((steps, annotation) => {
156
+ if (annotation.kind !== "scenario-step") return steps;
157
+ const fact = context.factById.get(annotation.targetFactId);
158
+ const span = fact ? getFactSpan(fact) : void 0;
159
+ if (!span || span.start <= scenario.start || span.start >= scenario.end) return steps;
160
+ const keyword = annotation.metadata?.keyword;
161
+ const contentMarkdown = annotation.metadata?.contentMarkdown;
162
+ const rawText = annotation.metadata?.rawMarkdown;
163
+ if (!isScenarioStepKeyword(keyword) || !contentMarkdown || !rawText) return steps;
164
+ steps.push({
165
+ keyword,
166
+ contentMarkdown,
167
+ rawText
168
+ });
169
+ return steps;
170
+ }, []);
171
+ }
172
+ function isScenarioStepKeyword(value) {
173
+ return value === "GIVEN" || value === "WHEN" || value === "THEN" || value === "AND" || value === "BUT";
174
+ }
175
+ function projectRequirement(context, requirement) {
176
+ const bodyEnd = requirement.scenarios.map((scenario) => scenario.start).sort((left, right) => left - right)[0] ?? requirement.end;
177
+ const bodyMarkdown = trimMarkdownSlice(context.sourceMarkdown, getContentStartAfterHeading(context, requirement.factId, requirement.start), bodyEnd);
178
+ const scenarios = requirement.scenarios.map((scenario) => projectScenario(context, scenario));
179
+ const scenarioText = scenarios.map((scenario) => scenario.rawText).join("\n\n");
180
+ return {
181
+ id: requirement.id,
182
+ title: requirement.title,
183
+ bodyMarkdown,
184
+ text: createRequirementText(requirement.title, bodyMarkdown, scenarioText),
185
+ scenarios
186
+ };
187
+ }
188
+ function getFactSpan(fact) {
189
+ return getMarkdownFactSpan(fact);
190
+ }
191
+ function getSectionKind(annotations, factId) {
192
+ if (getOpenSpecProjectionAnnotation(annotations, factId, "purpose-section")) return "overview";
193
+ if (getOpenSpecProjectionAnnotation(annotations, factId, "requirements-section")) return "requirements";
194
+ return "other";
195
+ }
196
+ function createDetachedProjectionContext(document) {
197
+ return {
198
+ sourceMarkdown: document.sourceMarkdown,
199
+ facts: document.facts,
200
+ factById: new Map(document.facts.map((fact) => [fact.id, fact])),
201
+ annotations: document.annotations.filter(isOpenSpecAnnotation)
202
+ };
203
+ }
204
+ function toOpenSpecProjectionContext(context) {
205
+ return {
206
+ sourceMarkdown: context.sourceMarkdown,
207
+ facts: context.facts,
208
+ factById: context.factById,
209
+ annotations: context.annotations.filter(isOpenSpecAnnotation)
210
+ };
211
+ }
212
+ function toProjectedOpenSpecDocument(document) {
213
+ return {
214
+ ...document,
215
+ annotations: document.annotations.filter(isOpenSpecAnnotation)
216
+ };
217
+ }
218
+ function isOpenSpecAnnotation(annotation) {
219
+ return annotation.kind === "document-title" || annotation.kind === "purpose-section" || annotation.kind === "requirements-section" || annotation.kind === "requirement" || annotation.kind === "scenario" || annotation.kind === "scenario-step" || annotation.kind === "keyword";
220
+ }
221
+
222
+ //#endregion
223
+ export { getOpenSpecReadingSections as a, projectOpenSpecMarkdown as c, getOpenSpecProjectionAnnotation as i, OPEN_SPEC_SPEC_PROJECTION_ID as n, parseOpenSpecMarkdownToSpec as o, createOpenSpecReadingPlugin as r, projectAnnotatedOpenSpecToSpec as s, OPEN_SPEC_READING_SECTIONS_PROJECTION_ID as t };