@ogygie/core 0.13.0 → 0.13.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.
- package/package.json +1 -1
- package/src/manifest-owners.test.ts +29 -1
- package/src/manifest-owners.ts +22 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ogygie/core",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.1",
|
|
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
|
"type": "module",
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* confirm, and that neither shadows the other.
|
|
6
6
|
*/
|
|
7
7
|
import { describe, expect, it } from "vitest";
|
|
8
|
-
import { declaredEntries, findSpecOwner } from "./manifest-owners.js";
|
|
8
|
+
import { declaredEntries, findSpecOwner, hasImplementation } from "./manifest-owners.js";
|
|
9
|
+
import type { SpecOwner, SpecOwnerKind } from "./manifest-owners.js";
|
|
9
10
|
import { OgygieManifestSchema } from "./manifest.schema.js";
|
|
10
11
|
|
|
11
12
|
function manifestWith(extra: Record<string, unknown>) {
|
|
@@ -250,3 +251,30 @@ describe("declaredEntries — tout ce que la carte déclare, à un seul endroit"
|
|
|
250
251
|
expect(declaredEntries(withApps({}))).toEqual([]);
|
|
251
252
|
});
|
|
252
253
|
});
|
|
254
|
+
|
|
255
|
+
describe("hasImplementation — ce qui prouve qu'une spec draft a déjà du code", () => {
|
|
256
|
+
const owner = (
|
|
257
|
+
kind: SpecOwnerKind,
|
|
258
|
+
status: "skeleton" | "in-progress" | "delivered",
|
|
259
|
+
): SpecOwner => ({ kind, name: "peu-importe", status, folder: "un/chemin" });
|
|
260
|
+
|
|
261
|
+
it("ÉTANT DONNÉ un statut au-delà de skeleton ALORS l'implémentation existe, dossier ou pas", () => {
|
|
262
|
+
for (const kind of ["feature", "package", "framework-package"] as SpecOwnerKind[]) {
|
|
263
|
+
expect(hasImplementation(owner(kind, "in-progress"), false)).toBe(true);
|
|
264
|
+
expect(hasImplementation(owner(kind, "delivered"), false)).toBe(true);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it("une FEATURE skeleton dont le dossier existe a bien du code — c'est la preuve historique", () => {
|
|
269
|
+
expect(hasImplementation(owner("feature", "skeleton"), true)).toBe(true);
|
|
270
|
+
expect(hasImplementation(owner("feature", "skeleton"), false)).toBe(false);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("MUTATION : un PACKAGE skeleton dont le dossier existe n'a PAS de code — le manifeste EXIGE ce dossier", () => {
|
|
274
|
+
// Sans cette règle, une spec draft et un package skeleton ne peuvent pas
|
|
275
|
+
// coexister : verify-manifest réclame le dossier, verify-specs y lit du
|
|
276
|
+
// code, et le projet est coincé entre deux fichiers gouvernés.
|
|
277
|
+
expect(hasImplementation(owner("package", "skeleton"), true)).toBe(false);
|
|
278
|
+
expect(hasImplementation(owner("framework-package", "skeleton"), true)).toBe(false);
|
|
279
|
+
});
|
|
280
|
+
});
|
package/src/manifest-owners.ts
CHANGED
|
@@ -158,6 +158,28 @@ export function findSpecOwner(
|
|
|
158
158
|
return { kind: owner.kind, name: owner.name, status: owner.status, folder: owner.folder };
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Does an implementation of this spec exist? The question the `draft` rule of
|
|
163
|
+
* the spec lifecycle rests on ("draft = no code yet").
|
|
164
|
+
*
|
|
165
|
+
* A declared status above `skeleton` always answers yes. A FOLDER on disk only
|
|
166
|
+
* answers yes for a FEATURE, whose folder is born with its code and is
|
|
167
|
+
* therefore evidence of it. A package's folder is NOT evidence: the manifest
|
|
168
|
+
* gate REQUIRES it to exist (MANIFEST_PACKAGE_NOT_FOUND), so a package
|
|
169
|
+
* declared `skeleton` whose spec is still `draft` could satisfy neither gate —
|
|
170
|
+
* one demands the folder, the other reads it as code, and the project is stuck
|
|
171
|
+
* between two governed files it may not edit. Observed on a consumer project
|
|
172
|
+
* the day it declared its first package before writing it.
|
|
173
|
+
*
|
|
174
|
+
* Lives here rather than in the gate script for the reason the whole module
|
|
175
|
+
* exists: the rule travels with the versioned package, not with a copy each
|
|
176
|
+
* project keeps.
|
|
177
|
+
*/
|
|
178
|
+
export function hasImplementation(owner: SpecOwner, folderExists: boolean): boolean {
|
|
179
|
+
if (owner.status !== "skeleton") return true;
|
|
180
|
+
return owner.kind === "feature" && folderExists;
|
|
181
|
+
}
|
|
182
|
+
|
|
161
183
|
/** What a refusal should suggest — both natures, never one that cannot exist. */
|
|
162
184
|
export const SPEC_OWNER_FIX =
|
|
163
185
|
"Set the owning entry to delivered in the manifest — a feature under `features`, a library under `packages`, or a published package under `framework.packages` (which names its spec explicitly) — or keep the spec in validated.";
|