@codyswann/lisa 2.235.0 → 2.237.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.
Files changed (120) hide show
  1. package/dist/cli/check-learnings-budget-cmd.d.ts +20 -0
  2. package/dist/cli/check-learnings-budget-cmd.d.ts.map +1 -0
  3. package/dist/cli/check-learnings-budget-cmd.js +59 -0
  4. package/dist/cli/check-learnings-budget-cmd.js.map +1 -0
  5. package/dist/cli/index.d.ts +3 -0
  6. package/dist/cli/index.d.ts.map +1 -1
  7. package/dist/cli/index.js +29 -1
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/cli/ui-automations-adapters.d.ts +50 -0
  10. package/dist/cli/ui-automations-adapters.d.ts.map +1 -0
  11. package/dist/cli/ui-automations-adapters.js +162 -0
  12. package/dist/cli/ui-automations-adapters.js.map +1 -0
  13. package/dist/cli/ui-automations.d.ts +89 -0
  14. package/dist/cli/ui-automations.d.ts.map +1 -0
  15. package/dist/cli/ui-automations.js +148 -0
  16. package/dist/cli/ui-automations.js.map +1 -0
  17. package/dist/cli/ui-cmd.d.ts +5 -0
  18. package/dist/cli/ui-cmd.d.ts.map +1 -1
  19. package/dist/cli/ui-cmd.js +17 -0
  20. package/dist/cli/ui-cmd.js.map +1 -1
  21. package/dist/cli/ui-deploy-pipeline-model.d.ts +70 -0
  22. package/dist/cli/ui-deploy-pipeline-model.d.ts.map +1 -0
  23. package/dist/cli/ui-deploy-pipeline-model.js +127 -0
  24. package/dist/cli/ui-deploy-pipeline-model.js.map +1 -0
  25. package/dist/cli/ui-deploy-pipeline.d.ts +25 -0
  26. package/dist/cli/ui-deploy-pipeline.d.ts.map +1 -0
  27. package/dist/cli/ui-deploy-pipeline.js +192 -0
  28. package/dist/cli/ui-deploy-pipeline.js.map +1 -0
  29. package/dist/cli/ui-detected-stacks.d.ts +20 -0
  30. package/dist/cli/ui-detected-stacks.d.ts.map +1 -0
  31. package/dist/cli/ui-detected-stacks.js +28 -0
  32. package/dist/cli/ui-detected-stacks.js.map +1 -0
  33. package/dist/cli/ui-enabled-plugins.d.ts +52 -0
  34. package/dist/cli/ui-enabled-plugins.d.ts.map +1 -0
  35. package/dist/cli/ui-enabled-plugins.js +253 -0
  36. package/dist/cli/ui-enabled-plugins.js.map +1 -0
  37. package/dist/cli/ui-github-repo-expected.d.ts +36 -0
  38. package/dist/cli/ui-github-repo-expected.d.ts.map +1 -0
  39. package/dist/cli/ui-github-repo-expected.js +118 -0
  40. package/dist/cli/ui-github-repo-expected.js.map +1 -0
  41. package/dist/cli/ui-github-repo-gh.d.ts +36 -0
  42. package/dist/cli/ui-github-repo-gh.d.ts.map +1 -0
  43. package/dist/cli/ui-github-repo-gh.js +112 -0
  44. package/dist/cli/ui-github-repo-gh.js.map +1 -0
  45. package/dist/cli/ui-github-repo-map.d.ts +25 -0
  46. package/dist/cli/ui-github-repo-map.d.ts.map +1 -0
  47. package/dist/cli/ui-github-repo-map.js +150 -0
  48. package/dist/cli/ui-github-repo-map.js.map +1 -0
  49. package/dist/cli/ui-github-repo.d.ts +51 -0
  50. package/dist/cli/ui-github-repo.d.ts.map +1 -0
  51. package/dist/cli/ui-github-repo.js +117 -0
  52. package/dist/cli/ui-github-repo.js.map +1 -0
  53. package/dist/cli/ui-observability-checks.d.ts +23 -0
  54. package/dist/cli/ui-observability-checks.d.ts.map +1 -0
  55. package/dist/cli/ui-observability-checks.js +156 -0
  56. package/dist/cli/ui-observability-checks.js.map +1 -0
  57. package/dist/cli/ui-observability-providers.d.ts +69 -0
  58. package/dist/cli/ui-observability-providers.d.ts.map +1 -0
  59. package/dist/cli/ui-observability-providers.js +99 -0
  60. package/dist/cli/ui-observability-providers.js.map +1 -0
  61. package/dist/core/learnings-budget-check.d.ts +42 -0
  62. package/dist/core/learnings-budget-check.d.ts.map +1 -0
  63. package/dist/core/learnings-budget-check.js +210 -0
  64. package/dist/core/learnings-budget-check.js.map +1 -0
  65. package/dist/core/learnings-document.js +6 -1
  66. package/dist/core/learnings-document.js.map +1 -1
  67. package/package.json +1 -1
  68. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  70. package/plugins/lisa-agy/plugin.json +1 -1
  71. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  74. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  80. package/plugins/lisa-expo-agy/plugin.json +1 -1
  81. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  86. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  90. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  91. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  95. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  96. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  98. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  99. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  100. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  101. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  103. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  104. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  105. package/plugins/lisa-rails-agy/plugin.json +1 -1
  106. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  107. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  108. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  109. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  110. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  111. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  112. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  113. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  114. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  115. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  116. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  117. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  118. package/scripts/check-learnings-budget.ts +29 -163
  119. package/ui/README.md +5 -3
  120. package/ui/index.html +1097 -432
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Live-status probe for Deploy pipeline stages in `lisa ui`.
3
+ *
4
+ * Combines the project's `.github/workflows/deploy.yml` job sequence with
5
+ * live GitHub environment protection rules for each `github.environments`
6
+ * entry. READ-ONLY — never fabricates a hold/no-hold claim.
7
+ * @module cli/ui-deploy-pipeline
8
+ */
9
+ import { execFile } from "node:child_process";
10
+ import { access, readFile } from "node:fs/promises";
11
+ import * as path from "node:path";
12
+ import { isJsonObject } from "../sync/json-path.js";
13
+ import { deepMerge, readJsonOrNull } from "../utils/index.js";
14
+ import { buildDeployPipelineResult, DEPLOY_PIPELINE_PROBE_ID, } from "./ui-deploy-pipeline-model.js";
15
+ export { assembleDeployPipelineStages, buildDeployPipelineResult, DEPLOY_PIPELINE_PROBE_ID, mapEnvironmentHoldStage, parseDeployWorkflowStages, } from "./ui-deploy-pipeline-model.js";
16
+ const DEPLOY_YML_RELATIVE = path.join(".github", "workflows", "deploy.yml");
17
+ const DEFAULT_TIMEOUT_MS = 8_000;
18
+ /**
19
+ * Read deploy.yml when present; null when the project has no deploy workflow.
20
+ * @param cwd - Project root
21
+ * @returns File contents or null
22
+ */
23
+ async function readDeployWorkflowDefault(cwd) {
24
+ const filePath = path.join(cwd, DEPLOY_YML_RELATIVE);
25
+ try {
26
+ await access(filePath);
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ return await readFile(filePath, "utf8");
32
+ }
33
+ /**
34
+ * Read configured environment names from merged Lisa config.
35
+ * @param cwd - Project root
36
+ * @returns Stable key order from the merged `github.environments` map
37
+ */
38
+ async function readConfiguredEnvironmentsDefault(cwd) {
39
+ const committed = await readJsonOrNull(path.join(cwd, ".lisa.config.json"));
40
+ const local = await readJsonOrNull(path.join(cwd, ".lisa.config.local.json"));
41
+ const merged = deepMerge(isJsonObject(committed) ? committed : {}, isJsonObject(local) ? local : {});
42
+ const github = merged.github;
43
+ if (!isJsonObject(github)) {
44
+ return [];
45
+ }
46
+ const environments = github.environments;
47
+ if (!isJsonObject(environments)) {
48
+ return [];
49
+ }
50
+ return Object.keys(environments);
51
+ }
52
+ /**
53
+ * Detect whether a gh failure means the CLI is not authenticated.
54
+ * @param stderr - Combined stderr/stdout from the failed command
55
+ * @returns Whether the failure is an authentication problem
56
+ */
57
+ function isNotAuthenticatedFailure(stderr) {
58
+ const text = stderr.toLowerCase();
59
+ return (text.includes("not logged into") ||
60
+ text.includes("not authenticated") ||
61
+ text.includes("gh auth login") ||
62
+ text.includes("http 401") ||
63
+ text.includes("401 unauthorized") ||
64
+ text.includes("to re-authenticate") ||
65
+ text.includes("authentication required"));
66
+ }
67
+ /**
68
+ * Parse a required-reviewers protection rule into a boolean hold signal.
69
+ * @param rules - Protection rules from one environment payload
70
+ * @returns True when at least one required reviewer is configured
71
+ */
72
+ function protectionHasRequiredReviewers(rules) {
73
+ if (!Array.isArray(rules)) {
74
+ return false;
75
+ }
76
+ return rules.some(rule => {
77
+ if (!isJsonObject(rule) || rule.type !== "required_reviewers") {
78
+ return false;
79
+ }
80
+ const reviewers = rule.reviewers;
81
+ return Array.isArray(reviewers) && reviewers.length > 0;
82
+ });
83
+ }
84
+ /**
85
+ * Classify a failed `gh api` invocation without fabricating hold state.
86
+ * @param stderr - Command stderr
87
+ * @param errorMessage - Error message from execFile
88
+ * @returns not-authenticated or generic error lookup
89
+ */
90
+ function classifyGithubEnvironmentsFailure(stderr, errorMessage) {
91
+ const detail = `${stderr}\n${errorMessage}`.trim();
92
+ if (isNotAuthenticatedFailure(detail)) {
93
+ return {
94
+ status: "not-authenticated",
95
+ message: detail.length > 0 ? detail : "GitHub CLI is not authenticated",
96
+ };
97
+ }
98
+ return {
99
+ status: "error",
100
+ message: detail.length > 0 ? detail : "Failed to list GitHub environments",
101
+ };
102
+ }
103
+ /**
104
+ * Parse the jq-shaped environments array from `gh api`.
105
+ * @param stdout - Command stdout
106
+ * @returns ok lookup or parse error
107
+ */
108
+ function parseGithubEnvironmentsStdout(stdout) {
109
+ try {
110
+ const parsed = JSON.parse(stdout);
111
+ if (!Array.isArray(parsed)) {
112
+ return {
113
+ status: "error",
114
+ message: "GitHub environments response was not an array",
115
+ };
116
+ }
117
+ const environments = parsed.flatMap((entry) => {
118
+ if (!isJsonObject(entry) || typeof entry.name !== "string") {
119
+ return [];
120
+ }
121
+ return [
122
+ {
123
+ name: entry.name,
124
+ hasRequiredReviewers: protectionHasRequiredReviewers(entry.protection_rules),
125
+ },
126
+ ];
127
+ });
128
+ return { status: "ok", environments };
129
+ }
130
+ catch (parseError) {
131
+ return {
132
+ status: "error",
133
+ message: parseError instanceof Error
134
+ ? parseError.message
135
+ : "Failed to parse GitHub environments response",
136
+ };
137
+ }
138
+ }
139
+ /**
140
+ * List GitHub Environments for the project's origin repo via `gh api`.
141
+ * @param cwd - Project root
142
+ * @param signal - Probe cancellation signal
143
+ * @param timeoutMs - Child-process timeout
144
+ * @returns Authenticated list, not-authenticated, or error
145
+ */
146
+ export async function listGithubEnvironmentsViaGh(cwd, signal, timeoutMs) {
147
+ return await new Promise(resolve => {
148
+ const ghExecutable = "gh";
149
+ execFile(
150
+ // eslint-disable-next-line sonarjs/no-os-command-from-path -- fixed user-installed gh executable
151
+ ghExecutable, [
152
+ "api",
153
+ "repos/{owner}/{repo}/environments",
154
+ "--paginate",
155
+ "--jq",
156
+ "[.environments[]? | {name, protection_rules}]",
157
+ ], { cwd, signal, timeout: timeoutMs, encoding: "utf8" }, (error, stdout, stderr) => {
158
+ if (error !== null) {
159
+ resolve(classifyGithubEnvironmentsFailure(stderr, error.message));
160
+ return;
161
+ }
162
+ resolve(parseGithubEnvironmentsStdout(stdout));
163
+ });
164
+ });
165
+ }
166
+ /**
167
+ * Create the probe that reports Deploy pipeline stages for `lisa ui`.
168
+ * @param cwd - Project root the console is serving
169
+ * @param dependencies - Injectable IO for focused tests
170
+ * @returns Status probe registered as `deploy-pipeline-stages`
171
+ */
172
+ export function createDeployPipelineProbe(cwd, dependencies = {}) {
173
+ const readDeployWorkflow = dependencies.readDeployWorkflow ?? readDeployWorkflowDefault;
174
+ const readConfiguredEnvironments = dependencies.readConfiguredEnvironments ??
175
+ readConfiguredEnvironmentsDefault;
176
+ const listGithubEnvironments = dependencies.listGithubEnvironments ?? listGithubEnvironmentsViaGh;
177
+ return {
178
+ id: DEPLOY_PIPELINE_PROBE_ID,
179
+ timeoutMs: DEFAULT_TIMEOUT_MS,
180
+ run: async (signal) => {
181
+ const [workflow, configuredEnvironments] = await Promise.all([
182
+ readDeployWorkflow(cwd),
183
+ readConfiguredEnvironments(cwd),
184
+ ]);
185
+ const lookup = configuredEnvironments.length === 0
186
+ ? { status: "ok", environments: [] }
187
+ : await listGithubEnvironments(cwd, signal, DEFAULT_TIMEOUT_MS + 250);
188
+ return buildDeployPipelineResult(workflow, configuredEnvironments, lookup);
189
+ },
190
+ };
191
+ }
192
+ //# sourceMappingURL=ui-deploy-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-deploy-pipeline.js","sourceRoot":"","sources":["../../src/cli/ui-deploy-pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Live-status probe for the console Stacks section.
3
+ *
4
+ * Mirrors doctor's detection chain exactly so the console and `lisa doctor`
5
+ * can never disagree. An empty match is the honest empty value (`[]`), never
6
+ * unknown; the runner maps a thrown detector error to unknown.
7
+ * @module cli/ui-detected-stacks
8
+ */
9
+ import { type DetectorRegistry } from "../detection/index.js";
10
+ import type { StatusProbe } from "./ui-status.js";
11
+ /** Probe id for the detected-stacks live-status entry. */
12
+ export declare const DETECTED_STACKS_PROBE_ID = "detected-stacks";
13
+ /**
14
+ * Create the probe that reports the project's detected stacks.
15
+ * @param destDir - Project root scanned by the detector registry
16
+ * @param registry - Injectable detector registry used by focused tests
17
+ * @returns Probe emitting the expanded, ordered project types
18
+ */
19
+ export declare function createDetectedStacksProbe(destDir: string, registry?: DetectorRegistry): StatusProbe<string[]>;
20
+ //# sourceMappingURL=ui-detected-stacks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-detected-stacks.d.ts","sourceRoot":"","sources":["../../src/cli/ui-detected-stacks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,0DAA0D;AAC1D,eAAO,MAAM,wBAAwB,oBAAoB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,gBAA2C,GACpD,WAAW,CAAC,MAAM,EAAE,CAAC,CAWvB"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Live-status probe for the console Stacks section.
3
+ *
4
+ * Mirrors doctor's detection chain exactly so the console and `lisa doctor`
5
+ * can never disagree. An empty match is the honest empty value (`[]`), never
6
+ * unknown; the runner maps a thrown detector error to unknown.
7
+ * @module cli/ui-detected-stacks
8
+ */
9
+ import { createDetectorRegistry, } from "../detection/index.js";
10
+ /** Probe id for the detected-stacks live-status entry. */
11
+ export const DETECTED_STACKS_PROBE_ID = "detected-stacks";
12
+ /**
13
+ * Create the probe that reports the project's detected stacks.
14
+ * @param destDir - Project root scanned by the detector registry
15
+ * @param registry - Injectable detector registry used by focused tests
16
+ * @returns Probe emitting the expanded, ordered project types
17
+ */
18
+ export function createDetectedStacksProbe(destDir, registry = createDetectorRegistry()) {
19
+ return {
20
+ id: DETECTED_STACKS_PROBE_ID,
21
+ timeoutMs: 5_000,
22
+ run: async () => {
23
+ const types = registry.expandAndOrderTypes(await registry.detectAll(destDir));
24
+ return { state: "value", value: [...types] };
25
+ },
26
+ };
27
+ }
28
+ //# sourceMappingURL=ui-detected-stacks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-detected-stacks.js","sourceRoot":"","sources":["../../src/cli/ui-detected-stacks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,sBAAsB,GAEvB,MAAM,uBAAuB,CAAC;AAG/B,0DAA0D;AAC1D,MAAM,CAAC,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAe,EACf,WAA6B,sBAAsB,EAAE;IAErD,OAAO;QACL,EAAE,EAAE,wBAAwB;QAC5B,SAAS,EAAE,KAAK;QAChB,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,KAAK,GAAG,QAAQ,CAAC,mBAAmB,CACxC,MAAM,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAClC,CAAC;YACF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC;QAC/C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,52 @@
1
+ import type { JsonValue } from "../sync/json-path.js";
2
+ import type { StatusProbe } from "./ui-status.js";
3
+ /** One plugin entry from a marketplace.json catalog. */
4
+ export type MarketplacePlugin = {
5
+ readonly name: string;
6
+ readonly description?: string;
7
+ };
8
+ /** One plugin row emitted by the enabled-plugins probe. */
9
+ export type EnabledPluginRow = {
10
+ readonly [key: string]: JsonValue;
11
+ readonly id: string;
12
+ readonly status: "enabled" | "available";
13
+ readonly description: string;
14
+ };
15
+ /** Structured value emitted by the enabled-plugins live-status probe. */
16
+ export type EnabledPluginsValue = {
17
+ readonly [key: string]: JsonValue;
18
+ /** False when `.claude/settings.json` is absent (empty-state trigger). */
19
+ readonly settingsPresent: boolean;
20
+ /** Enabled and available-not-enabled plugins; never demo data. */
21
+ readonly plugins: EnabledPluginRow[];
22
+ };
23
+ /** Injectable collaborators for focused tests. */
24
+ export type EnabledPluginsProbeDependencies = {
25
+ /** Home directory used to locate `~/.claude/plugins/known_marketplaces.json`. */
26
+ readonly homedir?: () => string;
27
+ /** Override marketplace discovery for unit tests. */
28
+ readonly listMarketplacePlugins?: (cwd: string, home: string) => Promise<ReadonlyMap<string, string>>;
29
+ };
30
+ /**
31
+ * Collect plugin id → description from known Claude marketplaces on disk.
32
+ * @param cwd - Project root (checked for a local `.claude-plugin/marketplace.json`)
33
+ * @param home - Home directory containing `~/.claude/plugins`
34
+ * @returns Map of `plugin@marketplace` ids to descriptions
35
+ */
36
+ export declare function listMarketplacePluginsFromDisk(cwd: string, home: string): Promise<ReadonlyMap<string, string>>;
37
+ /**
38
+ * Build the probe value from settings + marketplace catalog.
39
+ * @param settingsPresent - Whether settings.json existed
40
+ * @param enabledPlugins - Parsed enabledPlugins map (true = enabled)
41
+ * @param marketplace - Plugin id → description catalog
42
+ * @returns Structured probe value
43
+ */
44
+ export declare function buildEnabledPluginsValue(settingsPresent: boolean, enabledPlugins: Readonly<Record<string, boolean>>, marketplace: ReadonlyMap<string, string>): EnabledPluginsValue;
45
+ /**
46
+ * Create the probe that reports project plugin enablement vs marketplace availability.
47
+ * @param cwd - Project root containing `.claude/settings.json`
48
+ * @param dependencies - Injectable collaborators for focused tests
49
+ * @returns Probe emitting enabled / available-not-enabled rows, or unknown
50
+ */
51
+ export declare function createEnabledPluginsProbe(cwd: string, dependencies?: EnabledPluginsProbeDependencies): StatusProbe<EnabledPluginsValue>;
52
+ //# sourceMappingURL=ui-enabled-plugins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-enabled-plugins.d.ts","sourceRoot":"","sources":["../../src/cli/ui-enabled-plugins.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE/D,wDAAwD;AACxD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,2DAA2D;AAC3D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,0EAA0E;IAC1E,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,CAAC;CACtC,CAAC;AAEF,kDAAkD;AAClD,MAAM,MAAM,+BAA+B,GAAG;IAC5C,iFAAiF;IACjF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IAChC,qDAAqD;IACrD,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAChC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,KACT,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC3C,CAAC;AA8FF;;;;;GAKG;AACH,wBAAsB,8BAA8B,CAClD,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkBtC;AAkBD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,OAAO,EACxB,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACjD,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACvC,mBAAmB,CA+BrB;AAsFD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,EACX,YAAY,GAAE,+BAAoC,GACjD,WAAW,CAAC,mBAAmB,CAAC,CA2ClC"}
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Live-status probe for the console Plugins & MCP section.
3
+ *
4
+ * Reads project `.claude/settings.json` `enabledPlugins` and joins against
5
+ * marketplace catalogs on disk. READ-ONLY — never fabricates enablement.
6
+ * @module cli/ui-enabled-plugins
7
+ */
8
+ import { readFile } from "node:fs/promises";
9
+ import { homedir as defaultHomedir } from "node:os";
10
+ import * as path from "node:path";
11
+ const ENABLED_PLUGINS_PROBE_ID = "enabled-plugins";
12
+ const SETTINGS_RELATIVE = path.join(".claude", "settings.json");
13
+ const MARKETPLACE_JSON = path.join(".claude-plugin", "marketplace.json");
14
+ /**
15
+ * Read and parse JSON with a real parser; never hand-roll.
16
+ * @param filePath - Absolute path to a JSON file
17
+ * @returns Parsed value
18
+ */
19
+ async function readJsonFile(filePath) {
20
+ const content = await readFile(filePath, "utf8");
21
+ return JSON.parse(content);
22
+ }
23
+ /**
24
+ * Extract `plugin@marketplace` → description pairs from one marketplace.json.
25
+ * @param marketplacePath - Absolute path to marketplace.json
26
+ * @param fallbackName - Name used when the file omits `name`
27
+ * @returns Catalog entries (may be empty on read/parse failure)
28
+ */
29
+ async function readMarketplaceEntries(marketplacePath, fallbackName) {
30
+ try {
31
+ const parsed = await readJsonFile(marketplacePath);
32
+ if (typeof parsed !== "object" || parsed === null) {
33
+ return [];
34
+ }
35
+ const nameRaw = Reflect.get(parsed, "name");
36
+ const marketplaceName = typeof nameRaw === "string" && nameRaw.trim().length > 0
37
+ ? nameRaw.trim()
38
+ : fallbackName;
39
+ const plugins = Reflect.get(parsed, "plugins");
40
+ if (!Array.isArray(plugins)) {
41
+ return [];
42
+ }
43
+ return plugins.flatMap(entry => {
44
+ if (typeof entry !== "object" || entry === null) {
45
+ return [];
46
+ }
47
+ const pluginName = Reflect.get(entry, "name");
48
+ if (typeof pluginName !== "string" || pluginName.trim().length === 0) {
49
+ return [];
50
+ }
51
+ const descriptionRaw = Reflect.get(entry, "description");
52
+ const description = typeof descriptionRaw === "string" ? descriptionRaw : "";
53
+ return [
54
+ [`${pluginName.trim()}@${marketplaceName}`, description],
55
+ ];
56
+ });
57
+ }
58
+ catch {
59
+ return [];
60
+ }
61
+ }
62
+ /**
63
+ * Read install locations from `~/.claude/plugins/known_marketplaces.json`.
64
+ * @param home - Home directory
65
+ * @returns Marketplace name → installLocation pairs
66
+ */
67
+ async function readKnownMarketplaceInstalls(home) {
68
+ const knownPath = path.join(home, ".claude", "plugins", "known_marketplaces.json");
69
+ try {
70
+ const known = await readJsonFile(knownPath);
71
+ if (typeof known !== "object" || known === null || Array.isArray(known)) {
72
+ return [];
73
+ }
74
+ return Object.entries(known).flatMap(([marketplaceName, entry]) => {
75
+ if (typeof entry !== "object" || entry === null) {
76
+ return [];
77
+ }
78
+ const installLocation = Reflect.get(entry, "installLocation");
79
+ if (typeof installLocation !== "string" || installLocation.length === 0) {
80
+ return [];
81
+ }
82
+ return [[marketplaceName, installLocation]];
83
+ });
84
+ }
85
+ catch {
86
+ return [];
87
+ }
88
+ }
89
+ /**
90
+ * Collect plugin id → description from known Claude marketplaces on disk.
91
+ * @param cwd - Project root (checked for a local `.claude-plugin/marketplace.json`)
92
+ * @param home - Home directory containing `~/.claude/plugins`
93
+ * @returns Map of `plugin@marketplace` ids to descriptions
94
+ */
95
+ export async function listMarketplacePluginsFromDisk(cwd, home) {
96
+ const localEntries = await readMarketplaceEntries(path.join(cwd, MARKETPLACE_JSON), "lisa");
97
+ const installs = await readKnownMarketplaceInstalls(home);
98
+ const knownEntries = (await Promise.all(installs.map(async ([marketplaceName, installLocation]) => readMarketplaceEntries(path.join(installLocation, MARKETPLACE_JSON), marketplaceName)))).flat();
99
+ // Later entries win so the project's local marketplace takes precedence.
100
+ return new Map([...knownEntries, ...localEntries]);
101
+ }
102
+ /**
103
+ * Sort enabled rows before available, then by id.
104
+ * @param left - First row
105
+ * @param right - Second row
106
+ * @returns Comparator result
107
+ */
108
+ function comparePluginRows(left, right) {
109
+ if (left.status !== right.status) {
110
+ return left.status === "enabled" ? -1 : 1;
111
+ }
112
+ return left.id.localeCompare(right.id);
113
+ }
114
+ /**
115
+ * Build the probe value from settings + marketplace catalog.
116
+ * @param settingsPresent - Whether settings.json existed
117
+ * @param enabledPlugins - Parsed enabledPlugins map (true = enabled)
118
+ * @param marketplace - Plugin id → description catalog
119
+ * @returns Structured probe value
120
+ */
121
+ export function buildEnabledPluginsValue(settingsPresent, enabledPlugins, marketplace) {
122
+ if (!settingsPresent) {
123
+ return { settingsPresent: false, plugins: [] };
124
+ }
125
+ const enabledRows = Object.entries(enabledPlugins)
126
+ .filter((entry) => typeof entry[0] === "string" &&
127
+ entry[0].trim().length > 0 &&
128
+ entry[1] === true)
129
+ .map(([id]) => ({
130
+ id,
131
+ status: "enabled",
132
+ description: marketplace.get(id) ?? "",
133
+ }));
134
+ const enabledIds = new Set(enabledRows.map(row => row.id));
135
+ const availableRows = [...marketplace.entries()]
136
+ .filter(([id]) => !enabledIds.has(id))
137
+ .map(([id, description]) => ({
138
+ id,
139
+ status: "available",
140
+ description,
141
+ }));
142
+ return {
143
+ settingsPresent: true,
144
+ plugins: [...enabledRows, ...availableRows].sort(comparePluginRows),
145
+ };
146
+ }
147
+ /**
148
+ * Parse `enabledPlugins` from a settings document.
149
+ * @param settings - Parsed settings.json root
150
+ * @returns Map of plugin id → enabled, or an error reason
151
+ */
152
+ function parseEnabledPluginsMap(settings) {
153
+ if (typeof settings !== "object" ||
154
+ settings === null ||
155
+ Array.isArray(settings)) {
156
+ return {
157
+ ok: false,
158
+ reason: "invalid-settings",
159
+ message: ".claude/settings.json did not contain a JSON object",
160
+ };
161
+ }
162
+ if (!Object.hasOwn(settings, "enabledPlugins")) {
163
+ return { ok: true, map: {} };
164
+ }
165
+ const enabledPlugins = Reflect.get(settings, "enabledPlugins");
166
+ if (typeof enabledPlugins !== "object" ||
167
+ enabledPlugins === null ||
168
+ Array.isArray(enabledPlugins)) {
169
+ return {
170
+ ok: false,
171
+ reason: "invalid-enabled-plugins",
172
+ message: "enabledPlugins must be a JSON object map of plugin id → boolean",
173
+ };
174
+ }
175
+ const map = Object.fromEntries(Object.entries(enabledPlugins).filter((entry) => typeof entry[1] === "boolean"));
176
+ return { ok: true, map };
177
+ }
178
+ /**
179
+ * Classify a settings.json read failure into empty vs unknown.
180
+ * @param error - Thrown value from read/parse
181
+ * @returns Probe outcome when the file cannot be used
182
+ */
183
+ function classifySettingsReadError(error) {
184
+ const code = typeof error === "object" &&
185
+ error !== null &&
186
+ "code" in error &&
187
+ typeof Reflect.get(error, "code") === "string"
188
+ ? Reflect.get(error, "code")
189
+ : undefined;
190
+ if (code === "ENOENT") {
191
+ return { missing: true };
192
+ }
193
+ if (error instanceof SyntaxError) {
194
+ return {
195
+ state: "unknown",
196
+ reason: "unparseable-settings",
197
+ message: error.message.trim().length > 0
198
+ ? error.message
199
+ : ".claude/settings.json could not be parsed as JSON",
200
+ };
201
+ }
202
+ const message = error instanceof Error && error.message.trim().length > 0
203
+ ? error.message
204
+ : "Failed to read .claude/settings.json";
205
+ return {
206
+ state: "unknown",
207
+ reason: "settings-read-failed",
208
+ message,
209
+ };
210
+ }
211
+ /**
212
+ * Create the probe that reports project plugin enablement vs marketplace availability.
213
+ * @param cwd - Project root containing `.claude/settings.json`
214
+ * @param dependencies - Injectable collaborators for focused tests
215
+ * @returns Probe emitting enabled / available-not-enabled rows, or unknown
216
+ */
217
+ export function createEnabledPluginsProbe(cwd, dependencies = {}) {
218
+ const resolveHome = dependencies.homedir ?? defaultHomedir;
219
+ const listMarketplace = dependencies.listMarketplacePlugins ?? listMarketplacePluginsFromDisk;
220
+ return {
221
+ id: ENABLED_PLUGINS_PROBE_ID,
222
+ timeoutMs: 5_000,
223
+ run: async () => {
224
+ const settingsPath = path.join(cwd, SETTINGS_RELATIVE);
225
+ const loaded = await readJsonFile(settingsPath).then(settings => ({ ok: true, settings }), (error) => ({ ok: false, error }));
226
+ if (!loaded.ok) {
227
+ const classified = classifySettingsReadError(loaded.error);
228
+ if (!("missing" in classified)) {
229
+ return classified;
230
+ }
231
+ const marketplace = await listMarketplace(cwd, resolveHome());
232
+ return {
233
+ state: "value",
234
+ value: buildEnabledPluginsValue(false, {}, marketplace),
235
+ };
236
+ }
237
+ const parsed = parseEnabledPluginsMap(loaded.settings);
238
+ if (!parsed.ok) {
239
+ return {
240
+ state: "unknown",
241
+ reason: parsed.reason,
242
+ message: parsed.message,
243
+ };
244
+ }
245
+ const marketplace = await listMarketplace(cwd, resolveHome());
246
+ return {
247
+ state: "value",
248
+ value: buildEnabledPluginsValue(true, parsed.map, marketplace),
249
+ };
250
+ },
251
+ };
252
+ }
253
+ //# sourceMappingURL=ui-enabled-plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-enabled-plugins.js","sourceRoot":"","sources":["../../src/cli/ui-enabled-plugins.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Expected labels and secrets for the GitHub repository live-status panel.
3
+ * @module cli/ui-github-repo-expected
4
+ */
5
+ import type { JsonObject } from "../sync/json-path.js";
6
+ /** One config-expected lifecycle label. */
7
+ export interface ExpectedLabel {
8
+ readonly name: string;
9
+ readonly role: string;
10
+ }
11
+ /** One workflow-expected repository secret (presence only). */
12
+ export interface ExpectedSecret {
13
+ readonly name: string;
14
+ readonly purpose: string;
15
+ }
16
+ /**
17
+ * Secrets Lisa creates or expects workflows to consume.
18
+ * Presence is checked via `gh secret list`; values are never read.
19
+ */
20
+ export declare const EXPECTED_GITHUB_SECRETS: readonly ExpectedSecret[];
21
+ /**
22
+ * Flatten `github.labels` from merged config into expected label rows.
23
+ * @param config - Merged Lisa project config
24
+ * @returns Expected labels with human-readable role paths
25
+ */
26
+ export declare function expectedLabelsFromConfig(config: JsonObject): readonly ExpectedLabel[];
27
+ /**
28
+ * Read configured github.org / github.repo when both are non-empty strings.
29
+ * @param config - Merged Lisa project config
30
+ * @returns Owner and repo, or undefined when either is missing
31
+ */
32
+ export declare function configuredGithubRepo(config: JsonObject): {
33
+ readonly owner: string;
34
+ readonly repo: string;
35
+ } | undefined;
36
+ //# sourceMappingURL=ui-github-repo-expected.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-github-repo-expected.d.ts","sourceRoot":"","sources":["../../src/cli/ui-github-repo-expected.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,sBAAsB,CAAC;AAElE,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,cAAc,EAgE5D,CAAC;AAuBF;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,UAAU,GACjB,SAAS,aAAa,EAAE,CAU1B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,UAAU,GACjB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAgB/D"}