@pieai/pro-gov 0.5.3 → 0.5.4

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
@@ -3585,25 +3585,35 @@ import {
3585
3585
  statSync as statSync4,
3586
3586
  writeFileSync as writeFileSync7
3587
3587
  } from "node:fs";
3588
+ import { homedir } from "node:os";
3588
3589
  import { dirname as dirname12, join as join20, relative as relative8, resolve as resolve4, sep } from "node:path";
3589
3590
  import { fileURLToPath as fileURLToPath4 } from "node:url";
3590
3591
  function inspectPortfolioAiHealth(options) {
3591
3592
  const endpoints = collectEndpoints(options.manifest);
3592
3593
  const secretsRoot = options.secretsRoot ?? join20(dirname12(options.manifest.controlPlane?.path ?? endpoints[0]?.endpoint.path ?? process.cwd()), ".secrets");
3593
- const homeDir = options.homeDir ?? process.env.HOME ?? "";
3594
+ const homeDir = options.homeDir ?? process.env.HOME ?? homedir();
3595
+ const grokVersion = commandVersion("grok");
3594
3596
  const executionEngineRoot = options.manifest.executionEngine?.path;
3595
3597
  const skillRegistry = inspectSkillRegistry(executionEngineRoot);
3596
3598
  const expectedPackageVersion = packageVersion(join20(executionEngineRoot ?? "", "packages/pro-gov/package.json"));
3597
- const repositories = endpoints.map(({ endpoint, role }) => inspectRepository(endpoint, role, secretsRoot, expectedPackageVersion, options.manifest.technologyGovernance));
3599
+ const repositories = endpoints.map(({ endpoint, role }) => inspectRepository(
3600
+ endpoint,
3601
+ role,
3602
+ secretsRoot,
3603
+ homeDir,
3604
+ expectedPackageVersion,
3605
+ options.manifest.technologyGovernance,
3606
+ grokVersion
3607
+ ));
3598
3608
  const summary = { healthy: 0, attention: 0, unhealthy: 0 };
3599
3609
  for (const repository of repositories) summary[repository.status] += 1;
3600
3610
  return {
3601
- schemaVersion: 1,
3611
+ schemaVersion: 2,
3602
3612
  portfolioId: options.manifest.portfolioId,
3603
3613
  generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
3604
- privacy: "Names, paths, counts, and configuration structure only. Secret values, environment values, MCP commands, arguments, and MCP environment maps are never collected.",
3614
+ privacy: "Names, paths, counts, scopes, and configuration origins only. Secret values, environment values, MCP commands, arguments, URLs, headers, and MCP environment maps are never retained or rendered.",
3605
3615
  secretsRoot: inspectSecretsRoot(secretsRoot),
3606
- userMcp: inspectUserMcp(homeDir),
3616
+ hostEnvironment: inspectHostEnvironment(homeDir, grokVersion),
3607
3617
  skillRegistry,
3608
3618
  technologyGovernance: {
3609
3619
  strategySource: options.manifest.technologyGovernance?.strategySource,
@@ -3643,17 +3653,21 @@ function collectEndpoints(manifest) {
3643
3653
  return true;
3644
3654
  });
3645
3655
  }
3646
- function inspectRepository(endpoint, role, secretsRoot, expectedPackageVersion, technologyGovernance) {
3656
+ function inspectRepository(endpoint, role, secretsRoot, homeDir, expectedPackageVersion, technologyGovernance, grokVersion) {
3647
3657
  const root = endpoint.path;
3648
3658
  const git = inspectGit2(root);
3649
3659
  const entries = inspectEntries(root);
3650
- const skills = inspectSkills(root);
3660
+ const grokInspection = inspectGrokProject(root, homeDir, grokVersion);
3661
+ const skills = inspectSkills(root, grokInspection);
3651
3662
  const hooks = inspectHooks(root);
3652
3663
  const docs = inspectDocs(root, role === "execution-engine" ? void 0 : expectedPackageVersion);
3653
3664
  const mcp = {
3654
- root: jsonObjectKeys(join20(root, ".mcp.json"), "mcpServers"),
3655
- claudeCode: jsonObjectKeys(join20(root, ".claude/settings.json"), "mcpServers"),
3656
- codex: tomlMcpNames(join20(root, ".codex/config.toml"))
3665
+ codexProject: tomlMcpNames(join20(root, ".codex/config.toml")),
3666
+ claudeCodeProjectShared: jsonObjectKeys(join20(root, ".mcp.json"), "mcpServers"),
3667
+ claudeCodeProjectLocal: claudeProjectLocalMcpNames(homeDir, root),
3668
+ grokProject: tomlMcpNames(join20(root, ".grok/config.toml")),
3669
+ grokEffective: grokInspection.effectiveMcp,
3670
+ grokInspection: grokInspection.inspection
3657
3671
  };
3658
3672
  const secrets = inspectRepositorySecrets(root, endpoint.id, secretsRoot, git.isRepository, endpoint.environmentPolicy);
3659
3673
  const projectModel = inspectProjectModel(root, endpoint, technologyGovernance);
@@ -3821,7 +3835,7 @@ function inspectOptionalEntry(root, filename, agentsPath) {
3821
3835
  const content = safeRead(path);
3822
3836
  return /AGENTS\.md/.test(content) && content.length < 2e3 ? "thin-adapter" : "custom";
3823
3837
  }
3824
- function inspectSkills(root) {
3838
+ function inspectSkills(root, grokInspection) {
3825
3839
  const lock = readJson3(join20(root, ".pro-gov/assets.lock.json"));
3826
3840
  const managed = /* @__PURE__ */ new Set();
3827
3841
  const bundleIds = stringArray(isRecord3(lock) ? lock.bundleIds : void 0);
@@ -3857,6 +3871,12 @@ function inspectSkills(root) {
3857
3871
  installed: canonical.filter((item) => item.managed && item.kind !== "dangling-symlink").length,
3858
3872
  discoverable: canonical.filter((item) => item.kind !== "dangling-symlink").length,
3859
3873
  runtime: "unobservable"
3874
+ },
3875
+ hosts: {
3876
+ codexProject: canonical.filter((item) => item.kind !== "dangling-symlink").length,
3877
+ claudeCodeProject: inspectSkillRoot(join20(root, ".claude/skills")).names.length,
3878
+ grokNativeProject: inspectSkillRoot(join20(root, ".grok/skills")).names.length,
3879
+ grokEffective: grokInspection.skills
3860
3880
  }
3861
3881
  };
3862
3882
  }
@@ -3967,13 +3987,147 @@ function hasUnsafeCentralSecretPermissions(secrets) {
3967
3987
  function inspectSecretsRoot(path) {
3968
3988
  return existsSync21(path) ? { path, exists: true, mode: modeString(statSync4(path).mode) } : { path, exists: false };
3969
3989
  }
3970
- function inspectUserMcp(homeDir) {
3971
- if (!homeDir) return { codex: [], claudeCode: [] };
3990
+ function inspectHostEnvironment(homeDir, grokVersion) {
3991
+ const codexConfig = join20(homeDir, ".codex/config.toml");
3992
+ const claudeConfig = join20(homeDir, ".claude.json");
3993
+ const grokConfig = join20(homeDir, ".grok/config.toml");
3972
3994
  return {
3973
- codex: tomlMcpNames(join20(homeDir, ".codex/config.toml")),
3974
- claudeCode: jsonObjectKeys(join20(homeDir, ".claude/settings.json"), "mcpServers")
3995
+ mcp: {
3996
+ codexUser: { path: codexConfig, names: tomlMcpNames(codexConfig) },
3997
+ claudeCodeUser: { path: claudeConfig, names: jsonObjectKeys(claudeConfig, "mcpServers") },
3998
+ grokUser: { path: grokConfig, names: tomlMcpNames(grokConfig) }
3999
+ },
4000
+ skills: {
4001
+ codexUser: inspectSkillRoot(join20(homeDir, ".agents/skills")),
4002
+ claudeCodeUser: inspectSkillRoot(join20(homeDir, ".claude/skills")),
4003
+ grokUser: inspectSkillRoot(join20(homeDir, ".grok/skills")),
4004
+ grokAgentsCompatibility: inspectSkillRoot(join20(homeDir, ".agents/skills")),
4005
+ grokClaudeCompatibility: inspectSkillRoot(join20(homeDir, ".claude/skills"))
4006
+ },
4007
+ grok: {
4008
+ available: grokVersion !== void 0,
4009
+ ...grokVersion ? { version: grokVersion } : {},
4010
+ inspectionCommand: "grok inspect --json"
4011
+ }
3975
4012
  };
3976
4013
  }
4014
+ function inspectSkillRoot(path) {
4015
+ const exists = pathLexists(path) && safeIsDirectory(path);
4016
+ const names = exists ? safeReadDir(path).filter((name) => !name.startsWith(".") && existsSync21(join20(path, name, "SKILL.md"))) : [];
4017
+ return { path, exists, names };
4018
+ }
4019
+ function claudeProjectLocalMcpNames(homeDir, root) {
4020
+ if (!homeDir) return [];
4021
+ const value = readJson3(join20(homeDir, ".claude.json"));
4022
+ if (!isRecord3(value) || !isRecord3(value.projects)) return [];
4023
+ const candidates = new Set([resolve4(root), safeRealpath(root)].filter((path) => Boolean(path)));
4024
+ const names = /* @__PURE__ */ new Set();
4025
+ for (const [path, project] of Object.entries(value.projects)) {
4026
+ const projectPaths = [resolve4(path), safeRealpath(path)].filter((candidate) => Boolean(candidate));
4027
+ if (!projectPaths.some((candidate) => candidates.has(candidate)) || !isRecord3(project) || !isRecord3(project.mcpServers)) continue;
4028
+ for (const name of Object.keys(project.mcpServers)) names.add(name);
4029
+ }
4030
+ return [...names].sort();
4031
+ }
4032
+ function commandVersion(command2) {
4033
+ try {
4034
+ const output = execFileSync(command2, ["version"], {
4035
+ encoding: "utf8",
4036
+ stdio: ["ignore", "pipe", "ignore"],
4037
+ timeout: 3e3
4038
+ });
4039
+ return output.match(/\b\d+\.\d+\.\d+\b/)?.[0];
4040
+ } catch {
4041
+ return void 0;
4042
+ }
4043
+ }
4044
+ function inspectGrokProject(root, homeDir, grokVersion) {
4045
+ const empty = (inspection) => ({
4046
+ inspection,
4047
+ effectiveMcp: [],
4048
+ skills: { inspection, total: 0, project: 0, userOrCompatible: 0, plugin: 0, bundled: 0 },
4049
+ claudeCompatibility: "unknown",
4050
+ cursorCompatibility: "unknown"
4051
+ });
4052
+ if (!grokVersion) return empty("unavailable");
4053
+ try {
4054
+ const value = JSON.parse(execFileSync("grok", ["inspect", "--json"], {
4055
+ cwd: root,
4056
+ encoding: "utf8",
4057
+ env: { ...process.env, HOME: homeDir, GROK_HOME: join20(homeDir, ".grok") },
4058
+ maxBuffer: 10 * 1024 * 1024,
4059
+ stdio: ["ignore", "pipe", "ignore"],
4060
+ timeout: 8e3
4061
+ }));
4062
+ if (!isRecord3(value)) return empty("failed");
4063
+ const userClaudeNames = new Set(jsonObjectKeys(join20(homeDir, ".claude.json"), "mcpServers"));
4064
+ const localClaudeNames = new Set(claudeProjectLocalMcpNames(homeDir, root));
4065
+ const effectiveMcp = Array.isArray(value.mcpServers) ? value.mcpServers.flatMap((item) => {
4066
+ if (!isRecord3(item) || typeof item.name !== "string") return [];
4067
+ const source = isRecord3(item.source) ? item.source : {};
4068
+ const sourceType = typeof source.type === "string" ? source.type : "unknown";
4069
+ const sourcePath = typeof source.path === "string" ? source.path : void 0;
4070
+ const vendor = typeof item.vendor === "string" ? item.vendor : sourceType;
4071
+ return [{
4072
+ name: item.name,
4073
+ vendor,
4074
+ scope: inferGrokMcpScope(item.name, sourceType, sourcePath, root, homeDir, userClaudeNames, localClaudeNames),
4075
+ sourceType,
4076
+ ...sourcePath ? { sourcePath } : {}
4077
+ }];
4078
+ }) : [];
4079
+ const skillCounts = { project: 0, userOrCompatible: 0, plugin: 0, bundled: 0 };
4080
+ if (Array.isArray(value.skills)) {
4081
+ for (const item of value.skills) {
4082
+ if (!isRecord3(item) || !isRecord3(item.source)) continue;
4083
+ const type = item.source.type;
4084
+ const path = item.source.path;
4085
+ if (typeof path === "string" && path.includes(sep + ".grok" + sep + "bundled" + sep)) skillCounts.bundled += 1;
4086
+ else if (type === "project") skillCounts.project += 1;
4087
+ else if (type === "plugin") skillCounts.plugin += 1;
4088
+ else skillCounts.userOrCompatible += 1;
4089
+ }
4090
+ }
4091
+ const cells = isRecord3(value.externalCompat) && Array.isArray(value.externalCompat.cells) ? value.externalCompat.cells : [];
4092
+ return {
4093
+ inspection: "ok",
4094
+ effectiveMcp,
4095
+ skills: {
4096
+ inspection: "ok",
4097
+ total: skillCounts.project + skillCounts.userOrCompatible + skillCounts.plugin + skillCounts.bundled,
4098
+ ...skillCounts
4099
+ },
4100
+ claudeCompatibility: compatibilityEnabled(cells, "claude"),
4101
+ cursorCompatibility: compatibilityEnabled(cells, "cursor")
4102
+ };
4103
+ } catch {
4104
+ return empty("failed");
4105
+ }
4106
+ }
4107
+ function compatibilityEnabled(cells, vendor) {
4108
+ const matching = cells.filter((cell) => isRecord3(cell) && cell.vendor === vendor);
4109
+ if (matching.length === 0) return "unknown";
4110
+ return matching.some((cell) => isRecord3(cell) && cell.enabled === true);
4111
+ }
4112
+ function inferGrokMcpScope(name, sourceType, sourcePath, root, homeDir, userClaudeNames, localClaudeNames) {
4113
+ if (!sourcePath) {
4114
+ if (sourceType === "project") return "project";
4115
+ if (localClaudeNames.has(name)) return "project-local";
4116
+ if (userClaudeNames.has(name)) return "user";
4117
+ return "unknown";
4118
+ }
4119
+ const resolvedSource = safeRealpath(sourcePath) ?? resolve4(sourcePath);
4120
+ const resolvedRoot = safeRealpath(root) ?? resolve4(root);
4121
+ if (resolvedSource === join20(resolvedRoot, ".mcp.json")) return "project-shared";
4122
+ if (resolvedSource.startsWith(resolvedRoot + sep)) return "project";
4123
+ if (homeDir && resolvedSource === join20(resolve4(homeDir), ".claude.json")) {
4124
+ if (localClaudeNames.has(name)) return "project-local";
4125
+ if (userClaudeNames.has(name)) return "user";
4126
+ }
4127
+ if (homeDir && resolvedSource.startsWith(resolve4(homeDir) + sep)) return "user";
4128
+ if (sourceType === "project") return "project";
4129
+ return "unknown";
4130
+ }
3977
4131
  var HOOK_EVENT_NAMES = /* @__PURE__ */ new Set([
3978
4132
  "PreToolUse",
3979
4133
  "PostToolUse",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pieai/pro-gov",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Project-level distribution kit for Project Governance System.",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -35,7 +35,7 @@
35
35
  "access": "public"
36
36
  },
37
37
  "dependencies": {
38
- "@pieai/doc-gov": "^0.5.3"
38
+ "@pieai/doc-gov": "^0.5.4"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@pieai/swimmer-ui-kit": "1.0.1",