@ogygie/core 0.26.0 → 0.28.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/package.json +1 -1
- package/src/spec.schema.test.ts +11 -1
- package/src/spec.schema.ts +24 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ogygie/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Ogygie framework core: manifest/spec/error schemas, generic tenancy and gate tooling. Ships TypeScript sources — Ogygie products run tsx/vitest by construction (D1).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/src/spec.schema.test.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* rejection of a non-kebab-case blockedBy target.
|
|
8
8
|
*/
|
|
9
9
|
import { describe, expect, it } from "vitest";
|
|
10
|
-
import { SpecFrontmatterSchema, compositionOfSpec, parseSpecDocument, parseSpecFrontmatter } from "./spec.schema.js";
|
|
10
|
+
import { SpecFrontmatterSchema, assumptionsOfSpec, compositionOfSpec, parseSpecDocument, parseSpecFrontmatter } from "./spec.schema.js";
|
|
11
11
|
|
|
12
12
|
const NOMINAL_FRONTMATTER = `
|
|
13
13
|
id: order-flow
|
|
@@ -179,3 +179,13 @@ describe("compositionOfSpec — la composition déclarée sous # Design (D53)",
|
|
|
179
179
|
expect(compositionOfSpec("# Design\nRien.\n")).toBeNull();
|
|
180
180
|
});
|
|
181
181
|
});
|
|
182
|
+
|
|
183
|
+
describe("assumptionsOfSpec — les hypothèses déclarées sous # Hypothèses (D57)", () => {
|
|
184
|
+
it("lit une puce par hypothèse dans la section seulement ; sans section, aucune ; une section vide, aucune", () => {
|
|
185
|
+
const spec = "# @intent\nx\n\n# Budget\n- P95.\n\n# Hypothèses\n- Dix questions, choisies par le modèle.\n* Les réponses sont en anglais.\nUne ligne sans puce.\n\n# Design\n- Composition : liste\n";
|
|
186
|
+
expect(assumptionsOfSpec(spec)).toEqual(["Dix questions, choisies par le modèle.", "Les réponses sont en anglais."]);
|
|
187
|
+
expect(assumptionsOfSpec("# @intent\n- Hypothèses : aucune\n")).toEqual([]);
|
|
188
|
+
expect(assumptionsOfSpec("# Hypothèses\n\n# Design\n- a\n")).toEqual([]);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
package/src/spec.schema.ts
CHANGED
|
@@ -245,3 +245,27 @@ export function compositionOfSpec(content: string): string | null {
|
|
|
245
245
|
const section = next === null ? rest : rest.slice(0, next.index);
|
|
246
246
|
return COMPOSITION_LINE.exec(section)?.[1] ?? null;
|
|
247
247
|
}
|
|
248
|
+
|
|
249
|
+
// ------------------------------------------------------------- # Hypothèses (D57)
|
|
250
|
+
export const ASSUMPTIONS_SECTION_TITLE = "Hypothèses";
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* The assumptions a draft declares under `# Hypothèses` (spec
|
|
254
|
+
* ogygie-hosted-mode B3, D57): one bullet per point the model decided that
|
|
255
|
+
* the brief did not say. The section sits after `# Budget` and is admitted
|
|
256
|
+
* like `# Design`: the six canonical sections are read in order, anything
|
|
257
|
+
* after them is the spec's own. Empty when the spec declares none.
|
|
258
|
+
*/
|
|
259
|
+
export function assumptionsOfSpec(content: string): string[] {
|
|
260
|
+
const heading = new RegExp(`^# ${ASSUMPTIONS_SECTION_TITLE}\\s*$`, "mu").exec(content);
|
|
261
|
+
if (heading === null) return [];
|
|
262
|
+
const rest = content.slice(heading.index + heading[0].length);
|
|
263
|
+
const next = /^# /mu.exec(rest);
|
|
264
|
+
const section = next === null ? rest : rest.slice(0, next.index);
|
|
265
|
+
return section
|
|
266
|
+
.split("\n")
|
|
267
|
+
.map((line) => line.trim())
|
|
268
|
+
.filter((line) => /^[-*]\s+\S/u.test(line))
|
|
269
|
+
.map((line) => line.replace(/^[-*]\s+/u, "").trim());
|
|
270
|
+
}
|
|
271
|
+
|