@topogram/cli 0.3.42 → 0.3.43

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topogram/cli",
3
- "version": "0.3.42",
3
+ "version": "0.3.43",
4
4
  "description": "Topogram CLI for checking Topogram workspaces and generating app bundles.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
package/src/cli.js CHANGED
@@ -219,6 +219,7 @@ function printUsage(options = {}) {
219
219
  console.log(" or: topogram generator show <id-or-package> [--json]");
220
220
  console.log(" or: topogram generator check <path-or-package> [--json]");
221
221
  console.log(" or: topogram generator policy init [path] [--json]");
222
+ console.log(" or: topogram generator policy status [path] [--json]");
222
223
  console.log(" or: topogram generator policy check [path] [--json]");
223
224
  console.log(" or: topogram generator policy explain [path] [--json]");
224
225
  console.log(" or: topogram generator policy pin [package@version] [path] [--json]");
@@ -586,6 +587,7 @@ function printGeneratorHelp() {
586
587
  console.log(" or: topogram generator show <id-or-package> [--json]");
587
588
  console.log(" or: topogram generator check <path-or-package> [--json]");
588
589
  console.log(" or: topogram generator policy init [path] [--json]");
590
+ console.log(" or: topogram generator policy status [path] [--json]");
589
591
  console.log(" or: topogram generator policy check [path] [--json]");
590
592
  console.log(" or: topogram generator policy explain [path] [--json]");
591
593
  console.log(" or: topogram generator policy pin [package@version] [path] [--json]");
@@ -607,6 +609,7 @@ function printGeneratorHelp() {
607
609
  console.log(" topogram generator check ./generator-package");
608
610
  console.log(" topogram generator check @scope/topogram-generator-web --json");
609
611
  console.log(" topogram generator policy init");
612
+ console.log(" topogram generator policy status --json");
610
613
  console.log(" topogram generator policy check --json");
611
614
  console.log(" topogram generator policy pin @topogram/generator-react-web@1");
612
615
  }
@@ -1586,9 +1589,149 @@ function effectiveGeneratorPolicy(policyInfo) {
1586
1589
  };
1587
1590
  }
1588
1591
 
1592
+ /**
1593
+ * @param {string} filePath
1594
+ * @returns {any|null}
1595
+ */
1596
+ function readJsonIfPresent(filePath) {
1597
+ if (!fs.existsSync(filePath)) {
1598
+ return null;
1599
+ }
1600
+ try {
1601
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
1602
+ } catch {
1603
+ return null;
1604
+ }
1605
+ }
1606
+
1607
+ /**
1608
+ * @param {Record<string, any>|null} projectPackage
1609
+ * @param {string} packageName
1610
+ * @returns {{ field: string|null, spec: string|null }}
1611
+ */
1612
+ function dependencySpecForPackage(projectPackage, packageName) {
1613
+ const dependencyFields = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"];
1614
+ for (const field of dependencyFields) {
1615
+ const dependencies = projectPackage?.[field];
1616
+ if (dependencies && typeof dependencies === "object" && typeof dependencies[packageName] === "string") {
1617
+ return {
1618
+ field,
1619
+ spec: dependencies[packageName]
1620
+ };
1621
+ }
1622
+ }
1623
+ return {
1624
+ field: null,
1625
+ spec: null
1626
+ };
1627
+ }
1628
+
1629
+ /**
1630
+ * @param {Record<string, any>|null} lockfile
1631
+ * @param {string} packageName
1632
+ * @returns {{ version: string|null, resolved: string|null, integrity: string|null, entryPath: string|null }}
1633
+ */
1634
+ function lockfileInfoForPackage(lockfile, packageName) {
1635
+ const packageEntryPath = `node_modules/${packageName}`;
1636
+ const packageEntry = lockfile?.packages?.[packageEntryPath];
1637
+ if (packageEntry && typeof packageEntry === "object") {
1638
+ return {
1639
+ version: typeof packageEntry.version === "string" ? packageEntry.version : null,
1640
+ resolved: typeof packageEntry.resolved === "string" ? packageEntry.resolved : null,
1641
+ integrity: typeof packageEntry.integrity === "string" ? packageEntry.integrity : null,
1642
+ entryPath: packageEntryPath
1643
+ };
1644
+ }
1645
+ const dependencyEntry = lockfile?.dependencies?.[packageName];
1646
+ if (dependencyEntry && typeof dependencyEntry === "object") {
1647
+ return {
1648
+ version: typeof dependencyEntry.version === "string" ? dependencyEntry.version : null,
1649
+ resolved: typeof dependencyEntry.resolved === "string" ? dependencyEntry.resolved : null,
1650
+ integrity: typeof dependencyEntry.integrity === "string" ? dependencyEntry.integrity : null,
1651
+ entryPath: packageName
1652
+ };
1653
+ }
1654
+ return {
1655
+ version: null,
1656
+ resolved: null,
1657
+ integrity: null,
1658
+ entryPath: null
1659
+ };
1660
+ }
1661
+
1662
+ /**
1663
+ * @param {string} projectRoot
1664
+ * @param {string} packageName
1665
+ * @returns {{ dependencyField: string|null, dependencySpec: string|null, installedVersion: string|null, installedPackageJsonPath: string|null, lockfileVersion: string|null, lockfileResolved: string|null, lockfileIntegrity: string|null, lockfileEntryPath: string|null }}
1666
+ */
1667
+ function packageInfoForGenerator(projectRoot, packageName) {
1668
+ const projectPackage = readJsonIfPresent(path.join(projectRoot, "package.json"));
1669
+ const dependency = dependencySpecForPackage(projectPackage, packageName);
1670
+ const lockfile = readJsonIfPresent(path.join(projectRoot, "package-lock.json"));
1671
+ const lockfileInfo = lockfileInfoForPackage(lockfile, packageName);
1672
+ const installedPackageJsonPath = path.join(projectRoot, "node_modules", ...packageName.split("/"), "package.json");
1673
+ const installedPackage = readJsonIfPresent(installedPackageJsonPath);
1674
+ return {
1675
+ dependencyField: dependency.field,
1676
+ dependencySpec: dependency.spec,
1677
+ installedVersion: typeof installedPackage?.version === "string" ? installedPackage.version : null,
1678
+ installedPackageJsonPath: installedPackage ? installedPackageJsonPath : null,
1679
+ lockfileVersion: lockfileInfo.version,
1680
+ lockfileResolved: lockfileInfo.resolved,
1681
+ lockfileIntegrity: lockfileInfo.integrity,
1682
+ lockfileEntryPath: lockfileInfo.entryPath
1683
+ };
1684
+ }
1685
+
1686
+ /**
1687
+ * @param {string} projectRoot
1688
+ * @param {import("./generator-policy.js").GeneratorPolicy} policy
1689
+ * @param {ReturnType<typeof packageBackedGeneratorBindings>[number]} binding
1690
+ * @returns {ReturnType<typeof packageBackedGeneratorBindings>[number] & { allowed: boolean, packageInfo: ReturnType<typeof packageInfoForGenerator>, pin: { key: string|null, version: string|null, matches: boolean|null } }}
1691
+ */
1692
+ function generatorPolicyBindingStatus(projectRoot, policy, binding) {
1693
+ const packagePin = policy.pinnedVersions[binding.packageName] || null;
1694
+ const generatorPin = policy.pinnedVersions[binding.generatorId] || null;
1695
+ const pinnedVersion = packagePin || generatorPin;
1696
+ return {
1697
+ ...binding,
1698
+ allowed: generatorPackageAllowed(policy, binding.packageName),
1699
+ packageInfo: packageInfoForGenerator(projectRoot, binding.packageName),
1700
+ pin: {
1701
+ key: packagePin ? binding.packageName : generatorPin ? binding.generatorId : null,
1702
+ version: pinnedVersion,
1703
+ matches: pinnedVersion ? pinnedVersion === binding.version : null
1704
+ }
1705
+ };
1706
+ }
1707
+
1708
+ /**
1709
+ * @param {any[]} diagnostics
1710
+ * @param {Array<ReturnType<typeof generatorPolicyBindingStatus>>} bindings
1711
+ * @returns {any[]}
1712
+ */
1713
+ function annotateGeneratorPolicyDiagnostics(diagnostics, bindings) {
1714
+ return diagnostics.map((diagnostic) => {
1715
+ const binding = bindings.find((item) => (
1716
+ item.packageName === diagnostic.packageName &&
1717
+ (!diagnostic.componentId || item.componentId === diagnostic.componentId)
1718
+ ));
1719
+ if (!binding) {
1720
+ return diagnostic;
1721
+ }
1722
+ return {
1723
+ ...diagnostic,
1724
+ packageVersion: binding.packageInfo.installedVersion || binding.packageInfo.lockfileVersion || null,
1725
+ packageDependencyField: binding.packageInfo.dependencyField,
1726
+ packageDependencySpec: binding.packageInfo.dependencySpec,
1727
+ packageLockVersion: binding.packageInfo.lockfileVersion
1728
+ };
1729
+ });
1730
+ }
1731
+
1589
1732
  /**
1590
1733
  * @param {string} projectPath
1591
- * @returns {{ ok: boolean, path: string, exists: boolean, policy: any, defaulted: boolean, bindings: ReturnType<typeof packageBackedGeneratorBindings>, diagnostics: any[], errors: string[] }}
1734
+ * @returns {{ ok: boolean, path: string, exists: boolean, policy: any, defaulted: boolean, bindings: Array<ReturnType<typeof generatorPolicyBindingStatus>>, diagnostics: any[], errors: string[] }}
1592
1735
  */
1593
1736
  function buildGeneratorPolicyCheckPayload(projectPath) {
1594
1737
  const projectConfigInfo = loadProjectConfig(projectPath);
@@ -1613,7 +1756,9 @@ function buildGeneratorPolicyCheckPayload(projectPath) {
1613
1756
  };
1614
1757
  }
1615
1758
  const policyInfo = loadGeneratorPolicy(projectConfigInfo.configDir);
1616
- const bindings = packageBackedGeneratorBindings(projectConfigInfo.config);
1759
+ const rawBindings = packageBackedGeneratorBindings(projectConfigInfo.config);
1760
+ const policy = policyInfo.policy || effectiveGeneratorPolicy(policyInfo);
1761
+ const bindings = rawBindings.map((binding) => generatorPolicyBindingStatus(projectConfigInfo.configDir, policy, binding));
1617
1762
  const diagnostics = [];
1618
1763
  if (!policyInfo.exists) {
1619
1764
  diagnostics.push({
@@ -1625,16 +1770,17 @@ function buildGeneratorPolicyCheckPayload(projectPath) {
1625
1770
  step: "generator-policy"
1626
1771
  });
1627
1772
  }
1628
- diagnostics.push(...generatorPolicyDiagnosticsForBindings(policyInfo, bindings, "generator-policy"));
1629
- const errors = diagnostics.filter((diagnostic) => diagnostic.severity === "error").map((diagnostic) => diagnostic.message);
1773
+ diagnostics.push(...generatorPolicyDiagnosticsForBindings(policyInfo, rawBindings, "generator-policy"));
1774
+ const annotatedDiagnostics = annotateGeneratorPolicyDiagnostics(diagnostics, bindings);
1775
+ const errors = annotatedDiagnostics.filter((diagnostic) => diagnostic.severity === "error").map((diagnostic) => diagnostic.message);
1630
1776
  return {
1631
1777
  ok: errors.length === 0,
1632
1778
  path: policyInfo.path,
1633
1779
  exists: policyInfo.exists,
1634
- policy: policyInfo.policy || effectiveGeneratorPolicy(policyInfo),
1780
+ policy,
1635
1781
  defaulted: !policyInfo.exists,
1636
1782
  bindings,
1637
- diagnostics,
1783
+ diagnostics: annotatedDiagnostics,
1638
1784
  errors
1639
1785
  };
1640
1786
  }
@@ -1686,6 +1832,25 @@ function buildGeneratorPolicyExplainPayload(projectPath) {
1686
1832
  };
1687
1833
  }
1688
1834
 
1835
+ /**
1836
+ * @param {string} projectPath
1837
+ * @returns {ReturnType<typeof buildGeneratorPolicyExplainPayload> & { summary: { packageBackedGenerators: number, allowed: number, denied: number, pinned: number, unpinned: number, pinMismatches: number } }}
1838
+ */
1839
+ function buildGeneratorPolicyStatusPayload(projectPath) {
1840
+ const explain = buildGeneratorPolicyExplainPayload(projectPath);
1841
+ return {
1842
+ ...explain,
1843
+ summary: {
1844
+ packageBackedGenerators: explain.bindings.length,
1845
+ allowed: explain.bindings.filter((binding) => binding.allowed).length,
1846
+ denied: explain.bindings.filter((binding) => !binding.allowed).length,
1847
+ pinned: explain.bindings.filter((binding) => Boolean(binding.pin.version)).length,
1848
+ unpinned: explain.bindings.filter((binding) => !binding.pin.version).length,
1849
+ pinMismatches: explain.bindings.filter((binding) => binding.pin.matches === false).length
1850
+ }
1851
+ };
1852
+ }
1853
+
1689
1854
  /**
1690
1855
  * @param {ReturnType<typeof buildGeneratorPolicyCheckPayload>} payload
1691
1856
  * @returns {void}
@@ -1698,6 +1863,13 @@ function printGeneratorPolicyCheckPayload(payload) {
1698
1863
  console.log(`Package-backed generators: ${payload.bindings.length}`);
1699
1864
  for (const binding of payload.bindings) {
1700
1865
  console.log(`- ${binding.componentId}: ${binding.generatorId}@${binding.version} via ${binding.packageName}`);
1866
+ console.log(` npm package: ${binding.packageInfo.installedVersion || "(not installed)"}`);
1867
+ if (binding.packageInfo.dependencySpec) {
1868
+ console.log(` dependency: ${binding.packageInfo.dependencyField} ${binding.packageInfo.dependencySpec}`);
1869
+ }
1870
+ if (binding.packageInfo.lockfileVersion) {
1871
+ console.log(` lockfile: ${binding.packageInfo.lockfileVersion}`);
1872
+ }
1701
1873
  }
1702
1874
  for (const diagnostic of payload.diagnostics) {
1703
1875
  console.log(`[${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`);
@@ -1710,6 +1882,48 @@ function printGeneratorPolicyCheckPayload(payload) {
1710
1882
  }
1711
1883
  }
1712
1884
 
1885
+ /**
1886
+ * @param {ReturnType<typeof buildGeneratorPolicyStatusPayload>} payload
1887
+ * @returns {void}
1888
+ */
1889
+ function printGeneratorPolicyStatusPayload(payload) {
1890
+ console.log(payload.ok ? "Generator policy status: allowed" : "Generator policy status: denied");
1891
+ console.log(`Policy file: ${payload.path}`);
1892
+ console.log(`Policy file exists: ${payload.exists ? "yes" : "no"}`);
1893
+ console.log(`Default policy active: ${payload.defaulted ? "yes" : "no"}`);
1894
+ console.log(`Package-backed generators: ${payload.summary.packageBackedGenerators}`);
1895
+ console.log(`Allowed packages: ${payload.summary.allowed}`);
1896
+ console.log(`Denied packages: ${payload.summary.denied}`);
1897
+ console.log(`Pinned generators: ${payload.summary.pinned}`);
1898
+ console.log(`Unpinned generators: ${payload.summary.unpinned}`);
1899
+ console.log(`Pin mismatches: ${payload.summary.pinMismatches}`);
1900
+ if (payload.bindings.length > 0) {
1901
+ console.log("");
1902
+ console.log("Generator packages:");
1903
+ }
1904
+ for (const binding of payload.bindings) {
1905
+ console.log(`- ${binding.componentId}: ${binding.generatorId}@${binding.version} via ${binding.packageName}`);
1906
+ console.log(` allowed: ${binding.allowed ? "yes" : "no"}`);
1907
+ console.log(` npm package: ${binding.packageInfo.installedVersion || "(not installed)"}`);
1908
+ console.log(` dependency: ${binding.packageInfo.dependencyField && binding.packageInfo.dependencySpec ? `${binding.packageInfo.dependencyField} ${binding.packageInfo.dependencySpec}` : "(not declared)"}`);
1909
+ console.log(` lockfile: ${binding.packageInfo.lockfileVersion || "(not locked)"}`);
1910
+ console.log(` policy pin: ${binding.pin.version ? `${binding.pin.key}@${binding.pin.version}` : "(none)"}`);
1911
+ }
1912
+ for (const diagnostic of payload.diagnostics) {
1913
+ const label = diagnostic.severity === "warning" ? "Warning" : "Error";
1914
+ console.log(`${label}: ${diagnostic.code}: ${diagnostic.message}`);
1915
+ if (diagnostic.packageVersion) {
1916
+ console.log(` package version: ${diagnostic.packageVersion}`);
1917
+ }
1918
+ if (diagnostic.packageDependencySpec) {
1919
+ console.log(` dependency: ${diagnostic.packageDependencyField} ${diagnostic.packageDependencySpec}`);
1920
+ }
1921
+ if (diagnostic.suggestedFix) {
1922
+ console.log(` fix: ${diagnostic.suggestedFix}`);
1923
+ }
1924
+ }
1925
+ }
1926
+
1713
1927
  /**
1714
1928
  * @param {ReturnType<typeof buildGeneratorPolicyExplainPayload>} payload
1715
1929
  * @returns {void}
@@ -1727,6 +1941,10 @@ function printGeneratorPolicyExplainPayload(payload) {
1727
1941
  console.log("Package-backed generators:");
1728
1942
  for (const binding of payload.bindings) {
1729
1943
  console.log(`- ${binding.componentId}: ${binding.generatorId}@${binding.version} via ${binding.packageName}`);
1944
+ console.log(` npm package: ${binding.packageInfo.installedVersion || "(not installed)"}`);
1945
+ if (binding.packageInfo.dependencySpec) {
1946
+ console.log(` dependency: ${binding.packageInfo.dependencyField} ${binding.packageInfo.dependencySpec}`);
1947
+ }
1730
1948
  }
1731
1949
  }
1732
1950
  if (payload.rules.length > 0) {
@@ -3715,6 +3933,7 @@ function printNewProjectResult(result, cwd) {
3715
3933
  console.log(" npm run source:status");
3716
3934
  console.log(" npm run template:explain");
3717
3935
  console.log(" npm run check");
3936
+ console.log(" npm run generator:policy:status");
3718
3937
  console.log(" npm run generator:policy:check");
3719
3938
  if (template.includesExecutableImplementation) {
3720
3939
  console.log(" npm run template:policy:explain");
@@ -7219,6 +7438,8 @@ if (args[0] === "version" || args[0] === "--version") {
7219
7438
  commandArgs = { generatorCheck: true, inputPath: args[2] };
7220
7439
  } else if (args[0] === "generator" && args[1] === "policy" && args[2] === "init") {
7221
7440
  commandArgs = { generatorPolicyInit: true, inputPath: commandPath(3) };
7441
+ } else if (args[0] === "generator" && args[1] === "policy" && args[2] === "status") {
7442
+ commandArgs = { generatorPolicyStatus: true, inputPath: commandPath(3) };
7222
7443
  } else if (args[0] === "generator" && args[1] === "policy" && args[2] === "check") {
7223
7444
  commandArgs = { generatorPolicyCheck: true, inputPath: commandPath(3) };
7224
7445
  } else if (args[0] === "generator" && args[1] === "policy" && args[2] === "explain") {
@@ -7422,6 +7643,7 @@ const shouldGeneratorList = Boolean(commandArgs?.generatorList);
7422
7643
  const shouldGeneratorShow = Boolean(commandArgs?.generatorShow);
7423
7644
  const shouldGeneratorCheck = Boolean(commandArgs?.generatorCheck);
7424
7645
  const shouldGeneratorPolicyInit = Boolean(commandArgs?.generatorPolicyInit);
7646
+ const shouldGeneratorPolicyStatus = Boolean(commandArgs?.generatorPolicyStatus);
7425
7647
  const shouldGeneratorPolicyCheck = Boolean(commandArgs?.generatorPolicyCheck);
7426
7648
  const shouldGeneratorPolicyExplain = Boolean(commandArgs?.generatorPolicyExplain);
7427
7649
  const shouldGeneratorPolicyPin = Boolean(commandArgs?.generatorPolicyPin);
@@ -7558,7 +7780,7 @@ const outIndex = args.indexOf("--out");
7558
7780
  const outPath = outIndex >= 0 ? args[outIndex + 1] : null;
7559
7781
  const effectiveOutDir = outDir || outPath || commandArgs?.defaultOutDir || null;
7560
7782
 
7561
- if ((shouldCheck || shouldComponentCheck || shouldComponentBehavior || shouldGeneratorCheck || shouldGeneratorPolicyInit || shouldGeneratorPolicyCheck || shouldGeneratorPolicyExplain || shouldGeneratorPolicyPin || shouldValidate || shouldTrustTemplate || shouldTrustStatus || shouldTrustDiff || shouldSourceStatus || shouldTemplateExplain || shouldTemplateStatus || shouldTemplateDetach || shouldTemplatePolicyInit || shouldTemplatePolicyCheck || shouldTemplatePolicyExplain || shouldTemplatePolicyPin || shouldTemplateCheck || shouldTemplateUpdate || generateTarget === "app-bundle") && !inputPath) {
7783
+ if ((shouldCheck || shouldComponentCheck || shouldComponentBehavior || shouldGeneratorCheck || shouldGeneratorPolicyInit || shouldGeneratorPolicyStatus || shouldGeneratorPolicyCheck || shouldGeneratorPolicyExplain || shouldGeneratorPolicyPin || shouldValidate || shouldTrustTemplate || shouldTrustStatus || shouldTrustDiff || shouldSourceStatus || shouldTemplateExplain || shouldTemplateStatus || shouldTemplateDetach || shouldTemplatePolicyInit || shouldTemplatePolicyCheck || shouldTemplatePolicyExplain || shouldTemplatePolicyPin || shouldTemplateCheck || shouldTemplateUpdate || generateTarget === "app-bundle") && !inputPath) {
7562
7784
  console.error("Missing required <path>.");
7563
7785
  printUsage();
7564
7786
  process.exit(1);
@@ -7612,7 +7834,7 @@ if (shouldQueryShow && !commandArgs?.queryShowName) {
7612
7834
  process.exit(1);
7613
7835
  }
7614
7836
 
7615
- if ((shouldCheck || shouldComponentCheck || shouldComponentBehavior || shouldValidate || shouldGeneratorPolicyInit || shouldGeneratorPolicyCheck || shouldGeneratorPolicyExplain || shouldGeneratorPolicyPin || shouldTrustTemplate || shouldTrustStatus || shouldTrustDiff || shouldTemplateExplain || shouldTemplateStatus || shouldTemplatePolicyInit || shouldTemplatePolicyCheck || shouldTemplatePolicyExplain || shouldTemplatePolicyPin || shouldTemplateUpdate || generateTarget === "app-bundle") && inputPath) {
7837
+ if ((shouldCheck || shouldComponentCheck || shouldComponentBehavior || shouldValidate || shouldGeneratorPolicyInit || shouldGeneratorPolicyStatus || shouldGeneratorPolicyCheck || shouldGeneratorPolicyExplain || shouldGeneratorPolicyPin || shouldTrustTemplate || shouldTrustStatus || shouldTrustDiff || shouldTemplateExplain || shouldTemplateStatus || shouldTemplatePolicyInit || shouldTemplatePolicyCheck || shouldTemplatePolicyExplain || shouldTemplatePolicyPin || shouldTemplateUpdate || generateTarget === "app-bundle") && inputPath) {
7616
7838
  inputPath = normalizeTopogramPath(inputPath);
7617
7839
  }
7618
7840
 
@@ -7762,6 +7984,16 @@ try {
7762
7984
  process.exit(0);
7763
7985
  }
7764
7986
 
7987
+ if (shouldGeneratorPolicyStatus) {
7988
+ const payload = buildGeneratorPolicyStatusPayload(inputPath);
7989
+ if (emitJson) {
7990
+ console.log(stableStringify(payload));
7991
+ } else {
7992
+ printGeneratorPolicyStatusPayload(payload);
7993
+ }
7994
+ process.exit(payload.ok ? 0 : 1);
7995
+ }
7996
+
7765
7997
  if (shouldGeneratorPolicyCheck) {
7766
7998
  const payload = buildGeneratorPolicyCheckPayload(inputPath);
7767
7999
  if (emitJson) {
@@ -1975,6 +1975,7 @@ function writeProjectPackage(projectRoot, engineRoot, template) {
1975
1975
  "template:detach:dry-run": "topogram template detach --dry-run",
1976
1976
  "template:policy:check": "topogram template policy check",
1977
1977
  "template:policy:explain": "topogram template policy explain",
1978
+ "generator:policy:status": "topogram generator policy status",
1978
1979
  "generator:policy:check": "topogram generator policy check",
1979
1980
  "generator:policy:explain": "topogram generator policy explain",
1980
1981
  "template:update:status": "topogram template update --status",
@@ -2052,6 +2053,7 @@ Useful inspection:
2052
2053
  npm run template:detach:dry-run
2053
2054
  npm run template:policy:check
2054
2055
  npm run template:policy:explain
2056
+ npm run generator:policy:status
2055
2057
  npm run generator:policy:check
2056
2058
  npm run generator:policy:explain
2057
2059
  npm run template:update:status
@@ -2084,6 +2086,7 @@ function writeProjectReadme(projectRoot, projectConfig) {
2084
2086
  "npm run template:explain",
2085
2087
  "npm run check",
2086
2088
  "npm run template:policy:check",
2089
+ "npm run generator:policy:status",
2087
2090
  "npm run generator:policy:check",
2088
2091
  ...(template.includesExecutableImplementation ? [
2089
2092
  "npm run template:policy:explain",