@openspecui/core 3.5.2 → 3.6.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.
- package/dist/hosted-app.d.mts +1 -1
- package/dist/hosted-app.mjs +1 -1
- package/dist/index.d.mts +62 -620
- package/dist/index.mjs +81 -97
- package/dist/markdown-facts-BmSmZmpB.mjs +136 -0
- package/dist/markdown-facts-f3kXnqXb.d.mts +39 -0
- package/dist/markdown-facts.d.mts +2 -0
- package/dist/markdown-facts.mjs +3 -0
- package/dist/markdown-reading-CrchEfoW.mjs +104 -0
- package/dist/markdown-reading-D36W693c.d.mts +74 -0
- package/dist/markdown-reading.d.mts +3 -0
- package/dist/markdown-reading.mjs +4 -0
- package/dist/{notifications-BWvRNkRJ.d.mts → notifications-C4amULI4.d.mts} +1 -1
- package/dist/{notifications-F81mmO55.mjs → notifications-fD-V5hyP.mjs} +2 -2
- package/dist/notifications.d.mts +2 -2
- package/dist/notifications.mjs +3 -3
- package/dist/openspec-annotations-BMy9nWUe.mjs +436 -0
- package/dist/openspec-annotations-CJmYcfAu.d.mts +30 -0
- package/dist/openspec-annotations.d.mts +4 -0
- package/dist/openspec-annotations.mjs +5 -0
- package/dist/openspec-projection-DTuKPTgf.d.mts +1142 -0
- package/dist/openspec-projection-DWqBxedv.mjs +223 -0
- package/dist/openspec-projection.d.mts +5 -0
- package/dist/openspec-projection.mjs +6 -0
- package/dist/opsx-display-path.d.mts +1 -1
- package/dist/opsx-display-path.mjs +1 -1
- package/dist/sounds.d.mts +1 -1
- package/dist/sounds.mjs +1 -1
- package/dist/{terminal-audio-8E82E0AM.d.mts → terminal-audio-U9Exv9A5.d.mts} +1 -1
- package/dist/{terminal-audio-DDwxz9sJ.mjs → terminal-audio-UEv3j655.mjs} +1 -1
- package/dist/terminal-audio.d.mts +2 -2
- package/dist/terminal-audio.mjs +2 -2
- package/dist/terminal-control.d.mts +2 -2
- package/dist/terminal-control.mjs +1 -1
- package/dist/{terminal-invocation-CpdllJff.d.mts → terminal-invocation-BmwWgwgY.d.mts} +6 -6
- package/dist/terminal-invocation.d.mts +1 -1
- package/dist/terminal-invocation.mjs +1 -1
- package/dist/terminal-theme.d.mts +1 -1
- package/dist/terminal-theme.mjs +1 -1
- package/package.json +25 -3
- /package/dist/{hosted-app-CIOJpbzc.mjs → hosted-app-DFFffbJc.mjs} +0 -0
- /package/dist/{hosted-app-DaGUbBJn.d.mts → hosted-app-DZrYivji.d.mts} +0 -0
- /package/dist/{opsx-display-path-CuQyGB_A.d.mts → opsx-display-path-CkV9sq_j.d.mts} +0 -0
- /package/dist/{opsx-display-path-B6Owu17P.mjs → opsx-display-path-D4KLYRXQ.mjs} +0 -0
- /package/dist/{sounds-C0dNSFm8.mjs → sounds-BzNKMW05.mjs} +0 -0
- /package/dist/{sounds-Bw-sSyFZ.d.mts → sounds-CYxOpEdm.d.mts} +0 -0
- /package/dist/{terminal-control-DtBprY6-.mjs → terminal-control-Bxois59k.mjs} +0 -0
- /package/dist/{terminal-invocation-Cdi6_Kl6.mjs → terminal-invocation-BRCuSBjE.mjs} +0 -0
- /package/dist/{terminal-theme-CMQqJvIQ.mjs → terminal-theme-CIv3YMfi.mjs} +0 -0
- /package/dist/{terminal-theme-wbkK9vVH.d.mts → terminal-theme-lPZGfVA_.d.mts} +0 -0
package/dist/notifications.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./sounds-
|
|
2
|
-
import { n as terminalNotificationEventToPublishInput, t as TerminalControlParser } from "./terminal-control-
|
|
3
|
-
import { a as NotificationPublishInputSchema, c as NotificationSoundSchema, d as aggregateNotifications, f as getNotificationAggregateKey, h as groupNotifications, i as NotificationGroupKeySchema, l as NotificationSourceSchema, m as getNotificationGroupLabel, n as NOTIFICATION_SOUND_VALUES, o as NotificationRecordSchema, p as getNotificationGroupKey, r as NotificationActionSchema, s as NotificationSettingsSchema, t as NOTIFICATION_SOUND_OPTIONS, u as TerminalNotificationParser } from "./notifications-
|
|
1
|
+
import "./sounds-BzNKMW05.mjs";
|
|
2
|
+
import { n as terminalNotificationEventToPublishInput, t as TerminalControlParser } from "./terminal-control-Bxois59k.mjs";
|
|
3
|
+
import { a as NotificationPublishInputSchema, c as NotificationSoundSchema, d as aggregateNotifications, f as getNotificationAggregateKey, h as groupNotifications, i as NotificationGroupKeySchema, l as NotificationSourceSchema, m as getNotificationGroupLabel, n as NOTIFICATION_SOUND_VALUES, o as NotificationRecordSchema, p as getNotificationGroupKey, r as NotificationActionSchema, s as NotificationSettingsSchema, t as NOTIFICATION_SOUND_OPTIONS, u as TerminalNotificationParser } from "./notifications-fD-V5hyP.mjs";
|
|
4
4
|
|
|
5
5
|
export { NOTIFICATION_SOUND_OPTIONS, NOTIFICATION_SOUND_VALUES, NotificationActionSchema, NotificationGroupKeySchema, NotificationPublishInputSchema, NotificationRecordSchema, NotificationSettingsSchema, NotificationSoundSchema, NotificationSourceSchema, TerminalControlParser, TerminalNotificationParser, aggregateNotifications, getNotificationAggregateKey, getNotificationGroupKey, getNotificationGroupLabel, groupNotifications, terminalNotificationEventToPublishInput };
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { t as parseMarkdownFacts } from "./markdown-facts-BmSmZmpB.mjs";
|
|
2
|
+
import { c as getMarkdownHeadingFacts, o as getMarkdownFactSpan, r as createMarkdownReadingDocumentFromFacts, s as getMarkdownHeadingEnd } from "./markdown-reading-CrchEfoW.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/openspec-annotations.ts
|
|
5
|
+
const OPEN_SPEC_ANNOTATION_RULES = {
|
|
6
|
+
documentTitle: "openspec.heading.document-title.v2",
|
|
7
|
+
purposeSection: "openspec.heading.purpose-section.v2",
|
|
8
|
+
requirementsSection: "openspec.heading.requirements-section.v2",
|
|
9
|
+
requirementPrefix: "openspec.heading.requirement-prefix.v2",
|
|
10
|
+
requirementUnderSection: "openspec.heading.requirement-under-section.v2",
|
|
11
|
+
requirementCapabilityPrefix: "openspec.heading.capability-prefix.v2",
|
|
12
|
+
requirementCapabilityText: "openspec.heading.capability-text.v2",
|
|
13
|
+
scenarioPrefix: "openspec.heading.scenario-prefix.v2",
|
|
14
|
+
scenarioExamplePrefix: "openspec.heading.example-prefix.v2",
|
|
15
|
+
scenarioStepHeading: "openspec.heading.step-backed-scenario.v2",
|
|
16
|
+
scenarioStep: "openspec.list-item.scenario-step.v2",
|
|
17
|
+
keyword: "openspec.inline.keyword.v2"
|
|
18
|
+
};
|
|
19
|
+
const REQUIREMENT_PREFIX_PATTERN = /^(?:Requirement|Capability):\s*/i;
|
|
20
|
+
const SCENARIO_PREFIX_PATTERN = /^(?:Scenario|Example):\s*/i;
|
|
21
|
+
const SCENARIO_STEP_KEYWORDS = [
|
|
22
|
+
"GIVEN",
|
|
23
|
+
"WHEN",
|
|
24
|
+
"THEN",
|
|
25
|
+
"AND",
|
|
26
|
+
"BUT"
|
|
27
|
+
];
|
|
28
|
+
const REQUIREMENT_KEYWORD_PATTERN = new RegExp(`\\b(${[
|
|
29
|
+
"SHALL",
|
|
30
|
+
"MUST",
|
|
31
|
+
"SHOULD",
|
|
32
|
+
"MAY"
|
|
33
|
+
].join("|")})\\b`, "g");
|
|
34
|
+
const SCENARIO_STEP_PATTERN = new RegExp(`^\\s*(?:[-*+]\\s+)?(?:\\[[ xX]\\]\\s+)?(?:\\*\\*)?(${SCENARIO_STEP_KEYWORDS.join("|")})\\b(?:\\*\\*)?\\s*:?\\s*(.+?)\\s*$`, "i");
|
|
35
|
+
const REQUIREMENT_SECTION_TERMS = [
|
|
36
|
+
"requirement",
|
|
37
|
+
"specification",
|
|
38
|
+
"capability",
|
|
39
|
+
"capabilities"
|
|
40
|
+
];
|
|
41
|
+
const PURPOSE_SECTION_TERMS = [
|
|
42
|
+
"purpose",
|
|
43
|
+
"overview",
|
|
44
|
+
"objective",
|
|
45
|
+
"goal",
|
|
46
|
+
"goals"
|
|
47
|
+
];
|
|
48
|
+
const REQUIREMENT_BODY_SIGNAL_PATTERN = /\b(SHALL|MUST|SHOULD|MAY|CAN|WILL)\b/i;
|
|
49
|
+
const NON_SCENARIO_HEADING_PATTERN = /^(notes?|details?|rationale|reason|migration|examples?|open questions?)$/i;
|
|
50
|
+
const openSpecAnnotationRules = [
|
|
51
|
+
{
|
|
52
|
+
id: OPEN_SPEC_ANNOTATION_RULES.documentTitle,
|
|
53
|
+
annotate(context) {
|
|
54
|
+
return context.facts.flatMap((fact) => {
|
|
55
|
+
if (fact.kind !== "heading" || fact.depth !== 1) return [];
|
|
56
|
+
return [{
|
|
57
|
+
kind: "document-title",
|
|
58
|
+
targetFactId: fact.id,
|
|
59
|
+
confidence: "strong",
|
|
60
|
+
metadata: { title: fact.text }
|
|
61
|
+
}];
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: OPEN_SPEC_ANNOTATION_RULES.purposeSection,
|
|
67
|
+
annotate(context) {
|
|
68
|
+
return context.facts.flatMap((fact) => {
|
|
69
|
+
if (fact.kind !== "heading" || fact.depth !== 2) return [];
|
|
70
|
+
if (!matchesAnyTerm(fact.text, PURPOSE_SECTION_TERMS)) return [];
|
|
71
|
+
return [{
|
|
72
|
+
kind: "purpose-section",
|
|
73
|
+
targetFactId: fact.id,
|
|
74
|
+
confidence: isExactTerm(fact.text, ["Purpose", "Overview"]) ? "strong" : "weak",
|
|
75
|
+
metadata: { title: fact.text }
|
|
76
|
+
}];
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: OPEN_SPEC_ANNOTATION_RULES.requirementsSection,
|
|
82
|
+
annotate(context) {
|
|
83
|
+
return context.facts.flatMap((fact) => {
|
|
84
|
+
if (fact.kind !== "heading" || fact.depth !== 2) return [];
|
|
85
|
+
if (!matchesAnyTerm(fact.text, REQUIREMENT_SECTION_TERMS)) return [];
|
|
86
|
+
return [{
|
|
87
|
+
kind: "requirements-section",
|
|
88
|
+
targetFactId: fact.id,
|
|
89
|
+
confidence: fact.text.toLowerCase().includes("requirement") ? "strong" : "weak",
|
|
90
|
+
metadata: { title: fact.text }
|
|
91
|
+
}];
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: OPEN_SPEC_ANNOTATION_RULES.requirementPrefix,
|
|
97
|
+
annotate(context) {
|
|
98
|
+
return context.facts.flatMap((fact) => {
|
|
99
|
+
if (fact.kind !== "heading" || fact.depth !== 3) return [];
|
|
100
|
+
if (!/^Requirement:\s*/i.test(fact.text)) return [];
|
|
101
|
+
return [createRequirementAnnotation(fact, "strong")];
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: OPEN_SPEC_ANNOTATION_RULES.requirementCapabilityPrefix,
|
|
107
|
+
annotate(context) {
|
|
108
|
+
return context.facts.flatMap((fact) => {
|
|
109
|
+
if (fact.kind !== "heading" || fact.depth !== 3) return [];
|
|
110
|
+
if (!/^Capability:\s*/i.test(fact.text)) return [];
|
|
111
|
+
return [createRequirementAnnotation(fact, "weak")];
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: OPEN_SPEC_ANNOTATION_RULES.requirementUnderSection,
|
|
117
|
+
annotate(context) {
|
|
118
|
+
return getRequirementSections(context).flatMap((section) => {
|
|
119
|
+
return getChildHeadings(context, section, 3).flatMap((fact) => {
|
|
120
|
+
if (context.getAnnotation(fact.id, "requirement")) return [];
|
|
121
|
+
if (REQUIREMENT_PREFIX_PATTERN.test(fact.text)) return [];
|
|
122
|
+
if (!hasRequirementBodySignals(context, fact, section.end)) return [];
|
|
123
|
+
return [{
|
|
124
|
+
kind: "requirement",
|
|
125
|
+
targetFactId: fact.id,
|
|
126
|
+
confidence: "weak",
|
|
127
|
+
metadata: { title: fact.text }
|
|
128
|
+
}];
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: OPEN_SPEC_ANNOTATION_RULES.requirementCapabilityText,
|
|
135
|
+
annotate(context) {
|
|
136
|
+
return getRequirementSections(context).flatMap((section) => {
|
|
137
|
+
return getChildHeadings(context, section, 3).flatMap((fact) => {
|
|
138
|
+
if (context.getAnnotation(fact.id, "requirement")) return [];
|
|
139
|
+
if (!matchesAnyTerm(fact.text, [
|
|
140
|
+
"capability",
|
|
141
|
+
"feature",
|
|
142
|
+
"behavior"
|
|
143
|
+
])) return [];
|
|
144
|
+
return [{
|
|
145
|
+
kind: "requirement",
|
|
146
|
+
targetFactId: fact.id,
|
|
147
|
+
confidence: "weak",
|
|
148
|
+
metadata: { title: stripRequirementPrefix(fact.text) || fact.text }
|
|
149
|
+
}];
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: OPEN_SPEC_ANNOTATION_RULES.scenarioPrefix,
|
|
156
|
+
annotate(context) {
|
|
157
|
+
return getRequirementHeadings(context).flatMap((requirement) => {
|
|
158
|
+
return getNestedHeadings(context, requirement).flatMap((fact) => {
|
|
159
|
+
if (fact.depth !== 4 || !/^Scenario:\s*/i.test(fact.text)) return [];
|
|
160
|
+
return [createScenarioAnnotation(fact, "strong")];
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: OPEN_SPEC_ANNOTATION_RULES.scenarioExamplePrefix,
|
|
167
|
+
annotate(context) {
|
|
168
|
+
return getRequirementHeadings(context).flatMap((requirement) => {
|
|
169
|
+
return getNestedHeadings(context, requirement).flatMap((fact) => {
|
|
170
|
+
if (fact.depth !== 4 || !/^Example:\s*/i.test(fact.text)) return [];
|
|
171
|
+
return [createScenarioAnnotation(fact, "weak")];
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: OPEN_SPEC_ANNOTATION_RULES.scenarioStepHeading,
|
|
178
|
+
annotate(context) {
|
|
179
|
+
return getRequirementHeadings(context).flatMap((requirement) => {
|
|
180
|
+
return getNestedHeadings(context, requirement).flatMap((fact) => {
|
|
181
|
+
if (fact.depth !== 4) return [];
|
|
182
|
+
if (context.getAnnotation(fact.id, "scenario")) return [];
|
|
183
|
+
if (NON_SCENARIO_HEADING_PATTERN.test(fact.text)) return [];
|
|
184
|
+
if (!hasScenarioStepSignals(context, fact)) return [];
|
|
185
|
+
return [{
|
|
186
|
+
kind: "scenario",
|
|
187
|
+
targetFactId: fact.id,
|
|
188
|
+
confidence: "weak",
|
|
189
|
+
metadata: { title: stripScenarioPrefix(fact.text) || fact.text }
|
|
190
|
+
}];
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: OPEN_SPEC_ANNOTATION_RULES.scenarioStep,
|
|
197
|
+
annotate(context) {
|
|
198
|
+
const scenarioSections = getScenarioSections(context);
|
|
199
|
+
return context.facts.flatMap((fact) => {
|
|
200
|
+
if (fact.kind !== "listItem") return [];
|
|
201
|
+
if (!isWithinAnySection(fact, scenarioSections)) return [];
|
|
202
|
+
const metadata = parseScenarioStepFact(fact);
|
|
203
|
+
if (!metadata) return [];
|
|
204
|
+
return [{
|
|
205
|
+
kind: "scenario-step",
|
|
206
|
+
targetFactId: fact.id,
|
|
207
|
+
confidence: "strong",
|
|
208
|
+
metadata
|
|
209
|
+
}];
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: OPEN_SPEC_ANNOTATION_RULES.keyword,
|
|
215
|
+
annotate(context) {
|
|
216
|
+
const scenarioKeywordAnnotations = context.previousAnnotations.flatMap((annotation) => {
|
|
217
|
+
if (annotation.kind !== "scenario-step") return [];
|
|
218
|
+
const fact = context.factById.get(annotation.targetFactId);
|
|
219
|
+
if (!fact) return [];
|
|
220
|
+
return findScenarioStepKeyword(fact, readAnnotationKeyword(annotation.metadata));
|
|
221
|
+
});
|
|
222
|
+
const requirementKeywordAnnotations = context.facts.flatMap((fact) => {
|
|
223
|
+
if (!canAnnotateInlineKeywords(fact)) return [];
|
|
224
|
+
return findRequirementKeywords(fact);
|
|
225
|
+
});
|
|
226
|
+
return [...scenarioKeywordAnnotations, ...requirementKeywordAnnotations];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
];
|
|
230
|
+
const builtinOpenSpecReadingPlugin = {
|
|
231
|
+
id: "openspec.builtin-reading.v2",
|
|
232
|
+
annotationRules: openSpecAnnotationRules
|
|
233
|
+
};
|
|
234
|
+
function annotateOpenSpecMarkdown(sourceMarkdown, plugins = [builtinOpenSpecReadingPlugin]) {
|
|
235
|
+
return annotateOpenSpecFacts(parseMarkdownFacts(sourceMarkdown), plugins);
|
|
236
|
+
}
|
|
237
|
+
function annotateOpenSpecFacts(document, plugins = [builtinOpenSpecReadingPlugin]) {
|
|
238
|
+
const readingDocument = createMarkdownReadingDocumentFromFacts(document, plugins);
|
|
239
|
+
return {
|
|
240
|
+
...readingDocument,
|
|
241
|
+
annotations: readingDocument.annotations.filter(isOpenSpecAnnotation)
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function getOpenSpecAnnotationsForFact(document, factId) {
|
|
245
|
+
return document.annotations.filter((annotation) => annotation.targetFactId === factId);
|
|
246
|
+
}
|
|
247
|
+
function getOpenSpecAnnotation(document, factId, kind) {
|
|
248
|
+
return document.annotations.find((annotation) => annotation.targetFactId === factId && annotation.kind === kind);
|
|
249
|
+
}
|
|
250
|
+
function isOpenSpecAnnotation(annotation) {
|
|
251
|
+
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";
|
|
252
|
+
}
|
|
253
|
+
function createRequirementAnnotation(fact, confidence) {
|
|
254
|
+
return {
|
|
255
|
+
kind: "requirement",
|
|
256
|
+
targetFactId: fact.id,
|
|
257
|
+
confidence,
|
|
258
|
+
metadata: { title: stripRequirementPrefix(fact.text) || fact.text }
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function createScenarioAnnotation(fact, confidence) {
|
|
262
|
+
return {
|
|
263
|
+
kind: "scenario",
|
|
264
|
+
targetFactId: fact.id,
|
|
265
|
+
confidence,
|
|
266
|
+
metadata: { title: stripScenarioPrefix(fact.text) || "Scenario" }
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function matchesAnyTerm(text, terms) {
|
|
270
|
+
const normalized = text.toLowerCase();
|
|
271
|
+
return terms.some((term) => normalized.includes(term));
|
|
272
|
+
}
|
|
273
|
+
function isExactTerm(text, terms) {
|
|
274
|
+
const normalized = text.trim().toLowerCase();
|
|
275
|
+
return terms.some((term) => normalized === term.toLowerCase());
|
|
276
|
+
}
|
|
277
|
+
function stripRequirementPrefix(text) {
|
|
278
|
+
return text.replace(REQUIREMENT_PREFIX_PATTERN, "").trim();
|
|
279
|
+
}
|
|
280
|
+
function stripScenarioPrefix(text) {
|
|
281
|
+
return text.replace(SCENARIO_PREFIX_PATTERN, "").trim();
|
|
282
|
+
}
|
|
283
|
+
function getHeadingSections(context) {
|
|
284
|
+
const headings = getMarkdownHeadingFacts(context);
|
|
285
|
+
return headings.reduce((sections, fact, index) => {
|
|
286
|
+
const span = getMarkdownFactSpan(fact);
|
|
287
|
+
if (!span) return sections;
|
|
288
|
+
sections.push({
|
|
289
|
+
fact,
|
|
290
|
+
start: span.start,
|
|
291
|
+
end: getMarkdownHeadingEnd(headings, index, context.sourceMarkdown.length)
|
|
292
|
+
});
|
|
293
|
+
return sections;
|
|
294
|
+
}, []);
|
|
295
|
+
}
|
|
296
|
+
function getRequirementSections(context) {
|
|
297
|
+
return getHeadingSections(context).filter((section) => context.getAnnotation(section.fact.id, "requirements-section"));
|
|
298
|
+
}
|
|
299
|
+
function getChildHeadings(context, section, depth) {
|
|
300
|
+
return getMarkdownHeadingFacts(context).filter((fact) => {
|
|
301
|
+
if (fact.depth !== depth) return false;
|
|
302
|
+
const span = getMarkdownFactSpan(fact);
|
|
303
|
+
return !!span && span.start > section.start && span.start < section.end;
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
function getRequirementHeadings(context) {
|
|
307
|
+
return getMarkdownHeadingFacts(context).filter((fact) => context.getAnnotation(fact.id, "requirement"));
|
|
308
|
+
}
|
|
309
|
+
function getNestedHeadings(context, parentHeading) {
|
|
310
|
+
const headings = getMarkdownHeadingFacts(context);
|
|
311
|
+
const parentIndex = headings.findIndex((fact) => fact.id === parentHeading.id);
|
|
312
|
+
const parentSpan = getMarkdownFactSpan(parentHeading);
|
|
313
|
+
if (parentIndex < 0 || !parentSpan) return [];
|
|
314
|
+
const end = getMarkdownHeadingEnd(headings, parentIndex, context.sourceMarkdown.length);
|
|
315
|
+
return headings.filter((fact) => {
|
|
316
|
+
const span = getMarkdownFactSpan(fact);
|
|
317
|
+
return !!span && span.start > parentSpan.start && span.start < end;
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
function getScenarioSections(context) {
|
|
321
|
+
const headings = getMarkdownHeadingFacts(context);
|
|
322
|
+
return getHeadingSections(context).filter((section) => {
|
|
323
|
+
if (!context.getAnnotation(section.fact.id, "scenario")) return false;
|
|
324
|
+
if (NON_SCENARIO_HEADING_PATTERN.test(section.fact.text)) return false;
|
|
325
|
+
return headings.findIndex((fact) => fact.id === section.fact.id) >= 0;
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
function hasRequirementBodySignals(context, requirementHeading, sectionEnd) {
|
|
329
|
+
const span = getMarkdownFactSpan(requirementHeading);
|
|
330
|
+
if (!span) return false;
|
|
331
|
+
const headings = getMarkdownHeadingFacts(context);
|
|
332
|
+
const index = headings.findIndex((fact) => fact.id === requirementHeading.id);
|
|
333
|
+
const end = index >= 0 ? getMarkdownHeadingEnd(headings, index, sectionEnd) : sectionEnd;
|
|
334
|
+
const body = context.sourceMarkdown.slice(span.end, Math.min(end, sectionEnd));
|
|
335
|
+
return REQUIREMENT_BODY_SIGNAL_PATTERN.test(body);
|
|
336
|
+
}
|
|
337
|
+
function hasScenarioStepSignals(context, scenarioHeading) {
|
|
338
|
+
const span = getMarkdownFactSpan(scenarioHeading);
|
|
339
|
+
if (!span) return false;
|
|
340
|
+
const headings = getMarkdownHeadingFacts(context);
|
|
341
|
+
const index = headings.findIndex((fact) => fact.id === scenarioHeading.id);
|
|
342
|
+
const end = index >= 0 ? getMarkdownHeadingEnd(headings, index, context.sourceMarkdown.length) : context.sourceMarkdown.length;
|
|
343
|
+
return context.sourceMarkdown.slice(span.end, end).split("\n").some((line) => SCENARIO_STEP_PATTERN.test(line));
|
|
344
|
+
}
|
|
345
|
+
function isWithinAnySection(fact, sections) {
|
|
346
|
+
const span = getMarkdownFactSpan(fact);
|
|
347
|
+
if (!span) return false;
|
|
348
|
+
return sections.some((section) => span.start > section.start && span.start < section.end);
|
|
349
|
+
}
|
|
350
|
+
function parseScenarioStepFact(fact) {
|
|
351
|
+
const rawMarkdown = fact.range?.rawMarkdown.trim() || fact.text;
|
|
352
|
+
const match = rawMarkdown.match(SCENARIO_STEP_PATTERN) ?? fact.text.match(SCENARIO_STEP_PATTERN);
|
|
353
|
+
if (!match) return void 0;
|
|
354
|
+
return {
|
|
355
|
+
keyword: match[1].toUpperCase(),
|
|
356
|
+
contentMarkdown: match[2].trim(),
|
|
357
|
+
rawMarkdown
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function canAnnotateInlineKeywords(fact) {
|
|
361
|
+
return fact.kind === "paragraph" || fact.kind === "listItem" || fact.kind === "heading" || fact.kind === "tableCell";
|
|
362
|
+
}
|
|
363
|
+
function findScenarioStepKeyword(fact, keyword) {
|
|
364
|
+
if (!isScenarioStepKeywordValue(keyword)) return [];
|
|
365
|
+
const match = fact.text.match(new RegExp(`^\\s*(${SCENARIO_STEP_KEYWORDS.join("|")})\\b`, "i"));
|
|
366
|
+
if (!match) return [];
|
|
367
|
+
const text = match[1];
|
|
368
|
+
const textStart = match.index ?? 0;
|
|
369
|
+
const sourceSpan = findSourceSpanForFactText(fact, text);
|
|
370
|
+
return [{
|
|
371
|
+
kind: "keyword",
|
|
372
|
+
targetFactId: fact.id,
|
|
373
|
+
...sourceSpan ? { sourceSpan } : {},
|
|
374
|
+
textSpan: {
|
|
375
|
+
start: textStart,
|
|
376
|
+
end: textStart + text.length
|
|
377
|
+
},
|
|
378
|
+
confidence: "strong",
|
|
379
|
+
metadata: {
|
|
380
|
+
keyword,
|
|
381
|
+
keywordText: text,
|
|
382
|
+
keywordRole: "scenario-step"
|
|
383
|
+
}
|
|
384
|
+
}];
|
|
385
|
+
}
|
|
386
|
+
function findRequirementKeywords(fact) {
|
|
387
|
+
const span = getMarkdownFactSpan(fact);
|
|
388
|
+
const text = fact.text;
|
|
389
|
+
if (!span || !text) return [];
|
|
390
|
+
return Array.from(text.matchAll(REQUIREMENT_KEYWORD_PATTERN), (match) => {
|
|
391
|
+
const keyword = match[1].toUpperCase();
|
|
392
|
+
const textStart = match.index;
|
|
393
|
+
const textEnd = textStart + match[1].length;
|
|
394
|
+
const sourceSpan = findSourceSpanForFactText(fact, match[1], textStart);
|
|
395
|
+
return {
|
|
396
|
+
kind: "keyword",
|
|
397
|
+
targetFactId: fact.id,
|
|
398
|
+
...sourceSpan ? { sourceSpan } : {},
|
|
399
|
+
textSpan: {
|
|
400
|
+
start: textStart,
|
|
401
|
+
end: textEnd
|
|
402
|
+
},
|
|
403
|
+
confidence: "strong",
|
|
404
|
+
metadata: {
|
|
405
|
+
keyword,
|
|
406
|
+
keywordText: match[1],
|
|
407
|
+
keywordRole: isScenarioStepKeyword(keyword) ? "scenario-step" : "requirement-modal"
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
function isScenarioStepKeywordValue(value) {
|
|
413
|
+
return typeof value === "string" && SCENARIO_STEP_KEYWORDS.some((stepKeyword) => stepKeyword === value);
|
|
414
|
+
}
|
|
415
|
+
function isScenarioStepKeyword(keyword) {
|
|
416
|
+
return SCENARIO_STEP_KEYWORDS.some((stepKeyword) => stepKeyword === keyword);
|
|
417
|
+
}
|
|
418
|
+
function readAnnotationKeyword(metadata) {
|
|
419
|
+
return metadata && "keyword" in metadata ? metadata.keyword : void 0;
|
|
420
|
+
}
|
|
421
|
+
function findSourceSpanForFactText(fact, text, textStart = 0) {
|
|
422
|
+
const factSpan = getMarkdownFactSpan(fact);
|
|
423
|
+
const rawMarkdown = fact.range?.rawMarkdown;
|
|
424
|
+
if (!factSpan || !rawMarkdown) return void 0;
|
|
425
|
+
const rawStart = rawMarkdown.indexOf(text, Math.min(textStart, rawMarkdown.length));
|
|
426
|
+
const index = rawStart >= 0 ? rawStart : rawMarkdown.indexOf(text);
|
|
427
|
+
if (index < 0) return void 0;
|
|
428
|
+
const start = factSpan.start + index;
|
|
429
|
+
return {
|
|
430
|
+
start,
|
|
431
|
+
end: start + text.length
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
//#endregion
|
|
436
|
+
export { getOpenSpecAnnotationsForFact as a, getOpenSpecAnnotation as i, annotateOpenSpecMarkdown as n, openSpecAnnotationRules as o, builtinOpenSpecReadingPlugin as r, annotateOpenSpecFacts as t };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { r as MarkdownFactsDocument } from "./markdown-facts-f3kXnqXb.mjs";
|
|
2
|
+
import { a as MarkdownAnnotationRule, d as MarkdownReadingPlugin, l as MarkdownReadingDocument, n as MarkdownAnnotationConfidence, t as MarkdownAnnotation } from "./markdown-reading-D36W693c.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/openspec-annotations.d.ts
|
|
5
|
+
type OpenSpecSemanticKind = 'document-title' | 'purpose-section' | 'requirements-section' | 'requirement' | 'scenario' | 'scenario-step' | 'keyword';
|
|
6
|
+
type OpenSpecAnnotationConfidence = MarkdownAnnotationConfidence;
|
|
7
|
+
type OpenSpecScenarioStepKeyword = 'GIVEN' | 'WHEN' | 'THEN' | 'AND' | 'BUT';
|
|
8
|
+
type OpenSpecRequirementKeyword = 'SHALL' | 'MUST' | 'SHOULD' | 'MAY';
|
|
9
|
+
type OpenSpecKeyword = OpenSpecScenarioStepKeyword | OpenSpecRequirementKeyword;
|
|
10
|
+
type OpenSpecKeywordRole = 'scenario-step' | 'requirement-modal';
|
|
11
|
+
interface OpenSpecAnnotationMetadata {
|
|
12
|
+
title?: string;
|
|
13
|
+
keyword?: OpenSpecKeyword;
|
|
14
|
+
keywordText?: string;
|
|
15
|
+
keywordRole?: OpenSpecKeywordRole;
|
|
16
|
+
contentMarkdown?: string;
|
|
17
|
+
rawMarkdown?: string;
|
|
18
|
+
}
|
|
19
|
+
type OpenSpecAnnotation = MarkdownAnnotation<OpenSpecSemanticKind, OpenSpecAnnotationMetadata>;
|
|
20
|
+
interface AnnotatedOpenSpecDocument extends MarkdownReadingDocument {
|
|
21
|
+
annotations: OpenSpecAnnotation[];
|
|
22
|
+
}
|
|
23
|
+
declare const openSpecAnnotationRules: readonly MarkdownAnnotationRule[];
|
|
24
|
+
declare const builtinOpenSpecReadingPlugin: MarkdownReadingPlugin;
|
|
25
|
+
declare function annotateOpenSpecMarkdown(sourceMarkdown: string, plugins?: readonly MarkdownReadingPlugin[]): AnnotatedOpenSpecDocument;
|
|
26
|
+
declare function annotateOpenSpecFacts(document: MarkdownFactsDocument, plugins?: readonly MarkdownReadingPlugin[]): AnnotatedOpenSpecDocument;
|
|
27
|
+
declare function getOpenSpecAnnotationsForFact(document: AnnotatedOpenSpecDocument, factId: string): OpenSpecAnnotation[];
|
|
28
|
+
declare function getOpenSpecAnnotation(document: AnnotatedOpenSpecDocument, factId: string, kind: OpenSpecSemanticKind): OpenSpecAnnotation | undefined;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { OpenSpecKeyword as a, OpenSpecScenarioStepKeyword as c, annotateOpenSpecMarkdown as d, builtinOpenSpecReadingPlugin as f, openSpecAnnotationRules as h, OpenSpecAnnotationMetadata as i, OpenSpecSemanticKind as l, getOpenSpecAnnotationsForFact as m, OpenSpecAnnotation as n, OpenSpecKeywordRole as o, getOpenSpecAnnotation as p, OpenSpecAnnotationConfidence as r, OpenSpecRequirementKeyword as s, AnnotatedOpenSpecDocument as t, annotateOpenSpecFacts as u };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import "./markdown-facts-f3kXnqXb.mjs";
|
|
2
|
+
import "./markdown-reading-D36W693c.mjs";
|
|
3
|
+
import { a as OpenSpecKeyword, c as OpenSpecScenarioStepKeyword, d as annotateOpenSpecMarkdown, f as builtinOpenSpecReadingPlugin, h as openSpecAnnotationRules, i as OpenSpecAnnotationMetadata, l as OpenSpecSemanticKind, m as getOpenSpecAnnotationsForFact, n as OpenSpecAnnotation, o as OpenSpecKeywordRole, p as getOpenSpecAnnotation, r as OpenSpecAnnotationConfidence, s as OpenSpecRequirementKeyword, t as AnnotatedOpenSpecDocument, u as annotateOpenSpecFacts } from "./openspec-annotations-CJmYcfAu.mjs";
|
|
4
|
+
export { AnnotatedOpenSpecDocument, OpenSpecAnnotation, OpenSpecAnnotationConfidence, OpenSpecAnnotationMetadata, OpenSpecKeyword, OpenSpecKeywordRole, OpenSpecRequirementKeyword, OpenSpecScenarioStepKeyword, OpenSpecSemanticKind, annotateOpenSpecFacts, annotateOpenSpecMarkdown, builtinOpenSpecReadingPlugin, getOpenSpecAnnotation, getOpenSpecAnnotationsForFact, openSpecAnnotationRules };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import "./markdown-facts-BmSmZmpB.mjs";
|
|
2
|
+
import "./markdown-reading-CrchEfoW.mjs";
|
|
3
|
+
import { a as getOpenSpecAnnotationsForFact, i as getOpenSpecAnnotation, n as annotateOpenSpecMarkdown, o as openSpecAnnotationRules, r as builtinOpenSpecReadingPlugin, t as annotateOpenSpecFacts } from "./openspec-annotations-BMy9nWUe.mjs";
|
|
4
|
+
|
|
5
|
+
export { annotateOpenSpecFacts, annotateOpenSpecMarkdown, builtinOpenSpecReadingPlugin, getOpenSpecAnnotation, getOpenSpecAnnotationsForFact, openSpecAnnotationRules };
|