@ogygie/cli 0.13.0 → 0.14.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/cli.js CHANGED
@@ -15616,9 +15616,21 @@ function auditProductVocabulary(input) {
15616
15616
  return violations;
15617
15617
  }
15618
15618
 
15619
+ // ../ogygie-core/src/scan.ts
15620
+ var NEVER_SCANNED_DIRECTORIES = [
15621
+ "node_modules",
15622
+ "dist",
15623
+ "dist-ui",
15624
+ "build",
15625
+ "coverage"
15626
+ ];
15627
+ function isScannableDirectory(name) {
15628
+ if (name.startsWith(".")) return false;
15629
+ return !NEVER_SCANNED_DIRECTORIES.includes(name);
15630
+ }
15631
+
15619
15632
  // src/commands/verify-vocabulary.ts
15620
15633
  var CODE_EXTENSIONS = [".ts", ".tsx", ".mts", ".mjs", ".js", ".jsx"];
15621
- var IGNORED_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "build", ".git", "coverage"]);
15622
15634
  function readManifest(projectRoot) {
15623
15635
  const manifestPath = join9(projectRoot, MANIFEST_FILE_NAME);
15624
15636
  if (!existsSync7(manifestPath)) {
@@ -15650,7 +15662,7 @@ function collectCodeFiles(projectRoot, folder) {
15650
15662
  const files = [];
15651
15663
  const walk = (directory) => {
15652
15664
  for (const entry of readdirSync2(directory)) {
15653
- if (IGNORED_DIRS.has(entry)) continue;
15665
+ if (!isScannableDirectory(entry)) continue;
15654
15666
  const entryPath = join9(directory, entry);
15655
15667
  if (statSync2(entryPath).isDirectory()) {
15656
15668
  walk(entryPath);
@@ -15836,6 +15848,30 @@ var governedChecksumsByVersion = {
15836
15848
  "scripts/verify-specs.ts": "04289dbeeb029703779757a2d8b58852c6b16414ab7503bf3223cfe4e9a4d45e",
15837
15849
  "tsconfig.base.json": "0f8919e9ed8bbc88e0308fa2fa91471dabb18d1df721bd78c04076597eba89a2"
15838
15850
  },
15851
+ "0.13.1": {
15852
+ ".github/workflows/ogygie-gates.yml": "48c40efe9fe66dd0f9c3b94287026d80eae9afd6782b5833fdf8846d8662babf",
15853
+ "AGENTS.md": "74725a71e531502d4d4898518bad68e610a370bd410058b58e11220532dc327f",
15854
+ "CLAUDE.md": "785ee8d90e368806d8cf0b4d84a15f29d1dc961168bda86cf1a6c60a923c8c9b",
15855
+ "scripts/lint-interdits.ts": "20c32a6f3af4aa68b24fe37b25a2989f58e77fd96808c3853dc6fd98f4c9af84",
15856
+ "scripts/ogygie-design-brief.ts": "aba1585717b30808dd0bc8930a37a1ad2d83ee6869f969dbd06ca595e37a4a89",
15857
+ "scripts/ogygie-impact.ts": "f06cc8b4a46ddfbcfb32ba747c2454548ca49918123d04ab13d210b4a89c1fb9",
15858
+ "scripts/verify-contracts.ts": "9cd64c88dcc3b54b65bf1e1b7a68eb00353ee16f2a9ce8bca3c49ba063c2a08b",
15859
+ "scripts/verify-manifest.ts": "4e9caa31323442f7a5429e9cc2ae0a4d6407db6261b5744f51415c291236fb97",
15860
+ "scripts/verify-specs.ts": "03d58baa11822ad7ae67080f990f7a82f4f94d223b12777728b8b9ddd7ebd843",
15861
+ "tsconfig.base.json": "0f8919e9ed8bbc88e0308fa2fa91471dabb18d1df721bd78c04076597eba89a2"
15862
+ },
15863
+ "0.14.0": {
15864
+ ".github/workflows/ogygie-gates.yml": "48c40efe9fe66dd0f9c3b94287026d80eae9afd6782b5833fdf8846d8662babf",
15865
+ "AGENTS.md": "74725a71e531502d4d4898518bad68e610a370bd410058b58e11220532dc327f",
15866
+ "CLAUDE.md": "785ee8d90e368806d8cf0b4d84a15f29d1dc961168bda86cf1a6c60a923c8c9b",
15867
+ "scripts/lint-interdits.ts": "4644e1aaabc1d19ed42a0bdf8e2e55b9451f789d87d59754bce3432de7c357e7",
15868
+ "scripts/ogygie-design-brief.ts": "aba1585717b30808dd0bc8930a37a1ad2d83ee6869f969dbd06ca595e37a4a89",
15869
+ "scripts/ogygie-impact.ts": "f06cc8b4a46ddfbcfb32ba747c2454548ca49918123d04ab13d210b4a89c1fb9",
15870
+ "scripts/verify-contracts.ts": "9cd64c88dcc3b54b65bf1e1b7a68eb00353ee16f2a9ce8bca3c49ba063c2a08b",
15871
+ "scripts/verify-manifest.ts": "4e9caa31323442f7a5429e9cc2ae0a4d6407db6261b5744f51415c291236fb97",
15872
+ "scripts/verify-specs.ts": "03d58baa11822ad7ae67080f990f7a82f4f94d223b12777728b8b9ddd7ebd843",
15873
+ "tsconfig.base.json": "0f8919e9ed8bbc88e0308fa2fa91471dabb18d1df721bd78c04076597eba89a2"
15874
+ },
15839
15875
  "0.2.0": {
15840
15876
  ".github/workflows/ogygie-gates.yml": "48c40efe9fe66dd0f9c3b94287026d80eae9afd6782b5833fdf8846d8662babf",
15841
15877
  "AGENTS.md": "ca73ab619d8c55fac11858d815bf5fbab6537ecebe7ae4123cbdeb3e3e36bf1a",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ogygie/cli",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Ogygie framework CLI: deterministic scaffolding (init), governed-file upgrades (upgrade) and lockstep verification (check) for Ogygie products.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -17,7 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "devDependencies": {
20
- "@ogygie/core": "0.13.0",
20
+ "@ogygie/core": "0.14.0",
21
21
  "@types/node": "^24.0.0",
22
22
  "esbuild": "^0.28.0",
23
23
  "tsx": "^4.20.0",
@@ -18,11 +18,12 @@ import { join, relative } from "node:path";
18
18
  import { fileURLToPath } from "node:url";
19
19
  import { OgygieManifestSchema } from "@ogygie/core/manifest";
20
20
  import { mayUseRawDb } from "@ogygie/core/shared-tables";
21
+ import { isScannableDirectory } from "@ogygie/core/scan";
21
22
 
22
23
  const ROOT = fileURLToPath(new URL("..", import.meta.url));
23
24
  const SELF = fileURLToPath(import.meta.url);
24
25
  const SCANNED_DIRS = ["apps", "packages", "scripts"];
25
- const IGNORED_DIRS = new Set(["node_modules", "dist", ".git"]);
26
+
26
27
  // Build artifacts of a FRAMEWORK repo: a published package may embed a copy of
27
28
  // templates/ before publishing (generated and gitignored, like dist/). Derived
28
29
  // from the manifest rather than hard-coded, so this file stays identical in
@@ -79,7 +80,7 @@ function stripComments(line: string): string {
79
80
 
80
81
  function scan(dir: string): void {
81
82
  for (const entry of readdirSync(dir)) {
82
- if (IGNORED_DIRS.has(entry)) continue;
83
+ if (!isScannableDirectory(entry)) continue;
83
84
  const entryPath = join(dir, entry);
84
85
  const stats = statSync(entryPath);
85
86
  if (stats.isDirectory()) {
@@ -162,6 +162,13 @@ for (const feature of manifest.features) {
162
162
  }
163
163
 
164
164
  for (const dependency of feature.dependsOn) {
165
+ // A `package:<name>` dependency is resolved by the SCHEMA itself
166
+ // (superRefine, with its mutation test): by the time this loop runs the
167
+ // manifest has parsed, so such a dependency is known to name a declared
168
+ // package. Comparing it to FEATURE names instead would refuse a perfectly
169
+ // legal map — what a consumer project hit the day its first feature
170
+ // depended on a package.
171
+ if (dependency.startsWith("package:")) continue;
165
172
  if (!featureNames.has(dependency)) {
166
173
  report({
167
174
  code: "MANIFEST_UNKNOWN_DEPENDENCY",
@@ -29,7 +29,7 @@ import {
29
29
  parseKnownDecisionIds,
30
30
  } from "@ogygie/core/decision-refs";
31
31
  import { OgygieManifestSchema } from "@ogygie/core/manifest";
32
- import { findSpecOwner, SPEC_OWNER_FIX } from "@ogygie/core/manifest-owners";
32
+ import { findSpecOwner, hasImplementation, SPEC_OWNER_FIX } from "@ogygie/core/manifest-owners";
33
33
  import { ogygieError, type OgygieError } from "@ogygie/core/errors";
34
34
 
35
35
  const ROOT = new URL("..", import.meta.url).pathname;
@@ -130,9 +130,11 @@ for (const fileName of specFiles) {
130
130
  const ownerDir = owner?.folder === null || owner === undefined ? null : join(ROOT, owner.folder);
131
131
 
132
132
  if (frontmatter.status === "draft") {
133
+ // What counts as an implementation is the core's rule, not this script's:
134
+ // a package's folder is REQUIRED by the manifest gate, so its existence
135
+ // proves nothing (see hasImplementation).
133
136
  const implemented =
134
- (owner !== undefined && owner.status !== "skeleton") ||
135
- (ownerDir !== null && existsSync(ownerDir));
137
+ owner !== undefined && hasImplementation(owner, ownerDir !== null && existsSync(ownerDir));
136
138
  if (implemented) {
137
139
  report({
138
140
  code: "SPEC_DRAFT_ALREADY_IMPLEMENTED",