@farming-labs/docs 0.2.87 → 0.2.89
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/{agent-FyPQ2AZ4.mjs → agent-Jvn1a78y.mjs} +1 -1
- package/dist/{agent-export-Di1Ofstb.mjs → agent-export-B4Xos6gi.mjs} +1 -1
- package/dist/{agents-DjUz5voa.mjs → agents-DRCl1URL.mjs} +1 -1
- package/dist/cli/index.mjs +31 -29
- package/dist/{cloud-pdNC-tyj.mjs → cloud-DwhH_b_q.mjs} +1 -1
- package/dist/{codeblocks-CPA6Ae5r.mjs → codeblocks-B5lsz3sx.mjs} +1 -1
- package/dist/{config-Wcdj-D0a.mjs → config-BtxaQTPP.mjs} +26 -1
- package/dist/{dev-kjaxOOla.mjs → dev-BFBPvjnk.mjs} +7 -1
- package/dist/{doctor-DUnOjP9T.mjs → doctor-C3IG5hqb.mjs} +101 -20
- package/dist/{golden-evaluations-CNDwoUOe.mjs → golden-evaluations-DyeYD50F.mjs} +138 -22
- package/dist/{init-D0GcUKJ0.mjs → init-CuLodGjP.mjs} +10 -2
- package/dist/{mcp-7bvRe9Da.mjs → mcp-D8Hw2blN.mjs} +1 -1
- package/dist/mcp.mjs +77 -19
- package/dist/{review-DEnzotkg.mjs → review-R39cQsvi.mjs} +2 -2
- package/dist/{robots-DXy1xW3D.mjs → robots-C-Nh0xH6.mjs} +1 -1
- package/dist/{search-DznddPqw.mjs → search-3TUBKtz5.mjs} +1 -1
- package/dist/{sitemap-DCsrVSPf.mjs → sitemap-DrILEtYo.mjs} +1 -1
- package/dist/{skills-CPDwsMq4.mjs → skills-35ecRZtd.mjs} +1 -1
- package/dist/{templates-C6avM0U3.mjs → templates-Co7I_Okv.mjs} +8 -0
- package/package.json +5 -3
- package/styles/themes/shadcn.css +1576 -0
|
@@ -2,7 +2,7 @@ import { B as findDocsMarkdownPage, at as renderDocsMarkdownDocument } from "./a
|
|
|
2
2
|
import { v as normalizePageAgentFrontmatter, x as stripGeneratedPageAgentContractMarkdown } from "./markdown-sections-7OoA7ylx.mjs";
|
|
3
3
|
import { c as hashGeneratedAgentContent, d as serializeGeneratedAgentDocument, s as GENERATED_AGENT_PROVENANCE_VERSION, u as parseGeneratedAgentDocument } from "./content-change-hydration-DLBinuFR.mjs";
|
|
4
4
|
import { createFilesystemDocsMcpSource } from "./mcp.mjs";
|
|
5
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, c as loadProjectEnv, d as readNavTitle, f as readNumberProperty, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral, u as readEnvReferenceProperty } from "./config-
|
|
5
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, c as loadProjectEnv, d as readNavTitle, f as readNumberProperty, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral, u as readEnvReferenceProperty } from "./config-BtxaQTPP.mjs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import matter from "gray-matter";
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
@@ -10,7 +10,7 @@ import "./agent-evals-DCptRrdP.mjs";
|
|
|
10
10
|
import { createFilesystemDocsMcpSource, resolveDocsMcpConfig } from "./mcp.mjs";
|
|
11
11
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
12
12
|
import "./server.mjs";
|
|
13
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, m as readTopLevelBooleanProperty, p as readStringProperty, r as extractTopLevelConfigObject, t as extractNestedObjectLiteral } from "./config-
|
|
13
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, m as readTopLevelBooleanProperty, p as readStringProperty, r as extractTopLevelConfigObject, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
14
14
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
15
15
|
import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
16
16
|
import path from "node:path";
|
|
@@ -8,7 +8,7 @@ import "./agent-evals-DCptRrdP.mjs";
|
|
|
8
8
|
import { resolveDocsMcpConfig } from "./mcp.mjs";
|
|
9
9
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
10
10
|
import "./server.mjs";
|
|
11
|
-
import { a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
11
|
+
import { a as loadDocsConfigModule, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
12
12
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
13
13
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
14
|
import path from "node:path";
|
package/dist/cli/index.mjs
CHANGED
|
@@ -108,43 +108,43 @@ async function main() {
|
|
|
108
108
|
]
|
|
109
109
|
};
|
|
110
110
|
if (!parsedCommand.command || parsedCommand.command === "init") {
|
|
111
|
-
const { init } = await import("../init-
|
|
111
|
+
const { init } = await import("../init-CuLodGjP.mjs");
|
|
112
112
|
await init(initOptions);
|
|
113
113
|
} else if (parsedCommand.command === "dev") {
|
|
114
|
-
const { dev } = await import("../dev-
|
|
114
|
+
const { dev } = await import("../dev-BFBPvjnk.mjs");
|
|
115
115
|
await dev(devOptions);
|
|
116
116
|
} else if (parsedCommand.command === "deploy") {
|
|
117
|
-
const { runCloudDeploy } = await import("../cloud-
|
|
117
|
+
const { runCloudDeploy } = await import("../cloud-DwhH_b_q.mjs");
|
|
118
118
|
await runCloudDeploy(cloudOptions);
|
|
119
119
|
} else if (parsedCommand.command === "preview") {
|
|
120
|
-
const { runCloudPreview } = await import("../cloud-
|
|
120
|
+
const { runCloudPreview } = await import("../cloud-DwhH_b_q.mjs");
|
|
121
121
|
await runCloudPreview(cloudOptions);
|
|
122
122
|
} else if (parsedCommand.command === "cloud" && subcommand === "deploy") {
|
|
123
|
-
const { runCloudDeploy } = await import("../cloud-
|
|
123
|
+
const { runCloudDeploy } = await import("../cloud-DwhH_b_q.mjs");
|
|
124
124
|
await runCloudDeploy(cloudOptions);
|
|
125
125
|
} else if (parsedCommand.command === "cloud" && subcommand === "preview") {
|
|
126
|
-
const { runCloudPreview } = await import("../cloud-
|
|
126
|
+
const { runCloudPreview } = await import("../cloud-DwhH_b_q.mjs");
|
|
127
127
|
await runCloudPreview(cloudOptions);
|
|
128
128
|
} else if (parsedCommand.command === "cloud" && subcommand === "init") {
|
|
129
|
-
const { runCloudInit } = await import("../cloud-
|
|
129
|
+
const { runCloudInit } = await import("../cloud-DwhH_b_q.mjs");
|
|
130
130
|
await runCloudInit(cloudOptions);
|
|
131
131
|
} else if (parsedCommand.command === "cloud" && subcommand === "sync") {
|
|
132
|
-
const { syncCloudConfig } = await import("../cloud-
|
|
132
|
+
const { syncCloudConfig } = await import("../cloud-DwhH_b_q.mjs");
|
|
133
133
|
await syncCloudConfig(cloudOptions);
|
|
134
134
|
} else if (parsedCommand.command === "cloud" && subcommand === "check") {
|
|
135
|
-
const { runCloudCheck } = await import("../cloud-
|
|
135
|
+
const { runCloudCheck } = await import("../cloud-DwhH_b_q.mjs");
|
|
136
136
|
await runCloudCheck(cloudOptions);
|
|
137
137
|
} else if (parsedCommand.command === "cloud") {
|
|
138
138
|
console.error(pc.red(`Unknown cloud subcommand: ${subcommand ?? "(missing)"}`));
|
|
139
139
|
console.error();
|
|
140
|
-
const { printCloudHelp } = await import("../cloud-
|
|
140
|
+
const { printCloudHelp } = await import("../cloud-DwhH_b_q.mjs");
|
|
141
141
|
printCloudHelp();
|
|
142
142
|
process.exit(1);
|
|
143
143
|
} else if (parsedCommand.command === "mcp") {
|
|
144
|
-
const { runMcp } = await import("../mcp-
|
|
144
|
+
const { runMcp } = await import("../mcp-D8Hw2blN.mjs");
|
|
145
145
|
await runMcp(mcpOptions);
|
|
146
146
|
} else if (parsedCommand.command === "agent" && subcommand === "compact") {
|
|
147
|
-
const { compactAgentDocs, parseAgentCompactArgs, printAgentCompactHelp } = await import("../agent-
|
|
147
|
+
const { compactAgentDocs, parseAgentCompactArgs, printAgentCompactHelp } = await import("../agent-Jvn1a78y.mjs").then((n) => n.t);
|
|
148
148
|
const agentCompactOptions = parseAgentCompactArgs(args.slice(2));
|
|
149
149
|
if (agentCompactOptions.help) {
|
|
150
150
|
printAgentCompactHelp();
|
|
@@ -152,7 +152,7 @@ async function main() {
|
|
|
152
152
|
}
|
|
153
153
|
await compactAgentDocs(agentCompactOptions);
|
|
154
154
|
} else if (parsedCommand.command === "agent" && subcommand === "export") {
|
|
155
|
-
const { exportAgentBundle, parseAgentExportArgs, printAgentExportHelp } = await import("../agent-export-
|
|
155
|
+
const { exportAgentBundle, parseAgentExportArgs, printAgentExportHelp } = await import("../agent-export-B4Xos6gi.mjs");
|
|
156
156
|
const agentExportOptions = parseAgentExportArgs(args.slice(2));
|
|
157
157
|
if (agentExportOptions.help) {
|
|
158
158
|
printAgentExportHelp();
|
|
@@ -162,13 +162,13 @@ async function main() {
|
|
|
162
162
|
} else if (parsedCommand.command === "agent") {
|
|
163
163
|
console.error(pc.red(`Unknown agent subcommand: ${subcommand ?? "(missing)"}`));
|
|
164
164
|
console.error();
|
|
165
|
-
const { printAgentCompactHelp } = await import("../agent-
|
|
166
|
-
const { printAgentExportHelp } = await import("../agent-export-
|
|
165
|
+
const { printAgentCompactHelp } = await import("../agent-Jvn1a78y.mjs").then((n) => n.t);
|
|
166
|
+
const { printAgentExportHelp } = await import("../agent-export-B4Xos6gi.mjs");
|
|
167
167
|
printAgentCompactHelp();
|
|
168
168
|
printAgentExportHelp();
|
|
169
169
|
process.exit(1);
|
|
170
170
|
} else if (parsedCommand.command === "agents" && subcommand === "generate") {
|
|
171
|
-
const { generateAgents, parseAgentsGenerateArgs, printAgentsGenerateHelp } = await import("../agents-
|
|
171
|
+
const { generateAgents, parseAgentsGenerateArgs, printAgentsGenerateHelp } = await import("../agents-DRCl1URL.mjs");
|
|
172
172
|
const agentsOptions = parseAgentsGenerateArgs(args.slice(2));
|
|
173
173
|
if (agentsOptions.help) {
|
|
174
174
|
printAgentsGenerateHelp();
|
|
@@ -178,11 +178,11 @@ async function main() {
|
|
|
178
178
|
} else if (parsedCommand.command === "agents") {
|
|
179
179
|
console.error(pc.red(`Unknown agents subcommand: ${subcommand ?? "(missing)"}`));
|
|
180
180
|
console.error();
|
|
181
|
-
const { printAgentsGenerateHelp } = await import("../agents-
|
|
181
|
+
const { printAgentsGenerateHelp } = await import("../agents-DRCl1URL.mjs");
|
|
182
182
|
printAgentsGenerateHelp();
|
|
183
183
|
process.exit(1);
|
|
184
184
|
} else if (parsedCommand.command === "skills" && subcommand === "scaffold") {
|
|
185
|
-
const { parseSkillScaffoldArgs, printSkillScaffoldHelp, scaffoldSkillFromContracts } = await import("../skills-
|
|
185
|
+
const { parseSkillScaffoldArgs, printSkillScaffoldHelp, scaffoldSkillFromContracts } = await import("../skills-35ecRZtd.mjs");
|
|
186
186
|
const skillOptions = parseSkillScaffoldArgs(args.slice(2));
|
|
187
187
|
if (skillOptions.help) {
|
|
188
188
|
printSkillScaffoldHelp();
|
|
@@ -190,16 +190,16 @@ async function main() {
|
|
|
190
190
|
}
|
|
191
191
|
await scaffoldSkillFromContracts(skillOptions);
|
|
192
192
|
} else if (parsedCommand.command === "skills" && (subcommand === "--help" || subcommand === "-h")) {
|
|
193
|
-
const { printSkillScaffoldHelp } = await import("../skills-
|
|
193
|
+
const { printSkillScaffoldHelp } = await import("../skills-35ecRZtd.mjs");
|
|
194
194
|
printSkillScaffoldHelp();
|
|
195
195
|
} else if (parsedCommand.command === "skills") {
|
|
196
196
|
console.error(pc.red(`Unknown skills subcommand: ${subcommand ?? "(missing)"}`));
|
|
197
197
|
console.error();
|
|
198
|
-
const { printSkillScaffoldHelp } = await import("../skills-
|
|
198
|
+
const { printSkillScaffoldHelp } = await import("../skills-35ecRZtd.mjs");
|
|
199
199
|
printSkillScaffoldHelp();
|
|
200
200
|
process.exit(1);
|
|
201
201
|
} else if (parsedCommand.command === "doctor") {
|
|
202
|
-
const { parseDoctorArgs, printDoctorHelp, runDoctor } = await import("../doctor-
|
|
202
|
+
const { parseDoctorArgs, printDoctorHelp, runDoctor } = await import("../doctor-C3IG5hqb.mjs");
|
|
203
203
|
const doctorOptions = parseDoctorArgs(args.slice(1));
|
|
204
204
|
if (doctorOptions.help) {
|
|
205
205
|
printDoctorHelp();
|
|
@@ -207,7 +207,7 @@ async function main() {
|
|
|
207
207
|
}
|
|
208
208
|
await runDoctor(doctorOptions);
|
|
209
209
|
} else if (parsedCommand.command === "review") {
|
|
210
|
-
const { parseReviewArgs, printReviewHelp, runReview } = await import("../review-
|
|
210
|
+
const { parseReviewArgs, printReviewHelp, runReview } = await import("../review-R39cQsvi.mjs");
|
|
211
211
|
const reviewOptions = parseReviewArgs(args.slice(1));
|
|
212
212
|
if (reviewOptions.help) {
|
|
213
213
|
printReviewHelp();
|
|
@@ -215,7 +215,7 @@ async function main() {
|
|
|
215
215
|
}
|
|
216
216
|
await runReview(reviewOptions);
|
|
217
217
|
} else if ((parsedCommand.command === "codeblocks" || parsedCommand.command === "code-blocks") && subcommand === "validate") {
|
|
218
|
-
const { parseCodeBlocksValidateArgs, printCodeBlocksValidateHelp, runCodeBlocksValidate } = await import("../codeblocks-
|
|
218
|
+
const { parseCodeBlocksValidateArgs, printCodeBlocksValidateHelp, runCodeBlocksValidate } = await import("../codeblocks-B5lsz3sx.mjs");
|
|
219
219
|
const codeBlocksOptions = parseCodeBlocksValidateArgs(args.slice(2));
|
|
220
220
|
if (codeBlocksOptions.help) {
|
|
221
221
|
printCodeBlocksValidateHelp();
|
|
@@ -225,11 +225,11 @@ async function main() {
|
|
|
225
225
|
} else if (parsedCommand.command === "codeblocks" || parsedCommand.command === "code-blocks") {
|
|
226
226
|
console.error(pc.red(`Unknown codeblocks subcommand: ${subcommand ?? "(missing)"}`));
|
|
227
227
|
console.error();
|
|
228
|
-
const { printCodeBlocksValidateHelp } = await import("../codeblocks-
|
|
228
|
+
const { printCodeBlocksValidateHelp } = await import("../codeblocks-B5lsz3sx.mjs");
|
|
229
229
|
printCodeBlocksValidateHelp();
|
|
230
230
|
process.exit(1);
|
|
231
231
|
} else if (parsedCommand.command === "search" && subcommand === "sync") {
|
|
232
|
-
const { syncSearch } = await import("../search-
|
|
232
|
+
const { syncSearch } = await import("../search-3TUBKtz5.mjs");
|
|
233
233
|
await syncSearch(searchSyncOptions);
|
|
234
234
|
} else if (parsedCommand.command === "search") {
|
|
235
235
|
console.error(pc.red(`Unknown search subcommand: ${subcommand ?? "(missing)"}`));
|
|
@@ -237,7 +237,7 @@ async function main() {
|
|
|
237
237
|
printHelp();
|
|
238
238
|
process.exit(1);
|
|
239
239
|
} else if (parsedCommand.command === "sitemap" && subcommand === "generate") {
|
|
240
|
-
const { generateSitemap, parseSitemapGenerateArgs, printSitemapGenerateHelp } = await import("../sitemap-
|
|
240
|
+
const { generateSitemap, parseSitemapGenerateArgs, printSitemapGenerateHelp } = await import("../sitemap-DrILEtYo.mjs");
|
|
241
241
|
const sitemapOptions = parseSitemapGenerateArgs(args.slice(2));
|
|
242
242
|
if (sitemapOptions.help) {
|
|
243
243
|
printSitemapGenerateHelp();
|
|
@@ -247,11 +247,11 @@ async function main() {
|
|
|
247
247
|
} else if (parsedCommand.command === "sitemap") {
|
|
248
248
|
console.error(pc.red(`Unknown sitemap subcommand: ${subcommand ?? "(missing)"}`));
|
|
249
249
|
console.error();
|
|
250
|
-
const { printSitemapGenerateHelp } = await import("../sitemap-
|
|
250
|
+
const { printSitemapGenerateHelp } = await import("../sitemap-DrILEtYo.mjs");
|
|
251
251
|
printSitemapGenerateHelp();
|
|
252
252
|
process.exit(1);
|
|
253
253
|
} else if (parsedCommand.command === "robots" && subcommand === "generate") {
|
|
254
|
-
const { generateRobots, parseRobotsGenerateArgs, printRobotsGenerateHelp } = await import("../robots-
|
|
254
|
+
const { generateRobots, parseRobotsGenerateArgs, printRobotsGenerateHelp } = await import("../robots-C-Nh0xH6.mjs");
|
|
255
255
|
const robotsOptions = parseRobotsGenerateArgs(args.slice(2));
|
|
256
256
|
if (robotsOptions.help) {
|
|
257
257
|
printRobotsGenerateHelp();
|
|
@@ -261,7 +261,7 @@ async function main() {
|
|
|
261
261
|
} else if (parsedCommand.command === "robots") {
|
|
262
262
|
console.error(pc.red(`Unknown robots subcommand: ${subcommand ?? "(missing)"}`));
|
|
263
263
|
console.error();
|
|
264
|
-
const { printRobotsGenerateHelp } = await import("../robots-
|
|
264
|
+
const { printRobotsGenerateHelp } = await import("../robots-C-Nh0xH6.mjs");
|
|
265
265
|
printRobotsGenerateHelp();
|
|
266
266
|
process.exit(1);
|
|
267
267
|
} else if (parsedCommand.command === "downgrade") {
|
|
@@ -398,6 +398,8 @@ ${pc.dim("Options for doctor:")}
|
|
|
398
398
|
${pc.cyan("doctor --site")} Score the current docs app for reader-facing docs quality
|
|
399
399
|
${pc.cyan("doctor --human")} Alias for ${pc.cyan("doctor --site")}
|
|
400
400
|
${pc.cyan("doctor --json")} Print the report as JSON for CI, scripts, and automation
|
|
401
|
+
${pc.cyan("doctor --json-output <path>")} Write the JSON report to a file, including alongside ${pc.cyan("--ci")}
|
|
402
|
+
${pc.cyan("doctor --ci")} Emit actionable GitHub annotations in GitHub Actions
|
|
401
403
|
${pc.cyan("doctor --strict")} Exit with failure when any doctor check warns or fails
|
|
402
404
|
${pc.cyan("doctor --agent --fix")} Refresh stale generated ${pc.dim("agent.md")} files and token-budget missing outputs
|
|
403
405
|
${pc.cyan("doctor --agent --fix --dry-run")} Report the fix command without writing generated ${pc.dim("agent.md")} files
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as markCliErrorReported } from "./errors-DbOhkE1h.mjs";
|
|
2
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, c as loadProjectEnv, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, m as readTopLevelBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
2
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, c as loadProjectEnv, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, m as readTopLevelBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
3
3
|
import { i as detectPackageManagerFromProject, t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as validateCodeBlocks, r as resolveDocsCodeBlocksValidateConfig } from "./code-blocks-0wjOsqdJ.mjs";
|
|
2
|
-
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, f as readNumberProperty, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-
|
|
2
|
+
import { _ as resolveDocsContentDir, a as loadDocsConfigModule, f as readNumberProperty, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, p as readStringProperty, t as extractNestedObjectLiteral } from "./config-BtxaQTPP.mjs";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
|
|
@@ -82,6 +82,31 @@ function resolveDocsConfigPath(rootDir, explicitPath) {
|
|
|
82
82
|
}
|
|
83
83
|
throw new Error("Could not find docs.config.ts or docs.config.tsx in the current project. Use --config to point at a custom path.");
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the application root that owns a docs config selected from another
|
|
87
|
+
* working directory. This keeps config-relative paths anchored to a nested
|
|
88
|
+
* workspace package without changing the behavior of configs stored below a
|
|
89
|
+
* project's root (for example, src/lib/docs.config.ts).
|
|
90
|
+
*/
|
|
91
|
+
function resolveDocsProjectRoot(rootDir, configPath) {
|
|
92
|
+
const invocationRoot = resolve(rootDir);
|
|
93
|
+
const configDir = dirname(resolve(configPath));
|
|
94
|
+
const relativeConfigDir = relative(invocationRoot, configDir);
|
|
95
|
+
const configIsInsideInvocationRoot = relativeConfigDir === "" || relativeConfigDir !== ".." && !relativeConfigDir.startsWith(`..${sep}`);
|
|
96
|
+
const fallbackRoot = configIsInsideInvocationRoot ? invocationRoot : configDir;
|
|
97
|
+
let currentDir = configDir;
|
|
98
|
+
while (true) {
|
|
99
|
+
if (existsSync(join(currentDir, "package.json"))) return currentDir;
|
|
100
|
+
if (configIsInsideInvocationRoot && currentDir === invocationRoot) return invocationRoot;
|
|
101
|
+
const parentDir = dirname(currentDir);
|
|
102
|
+
if (parentDir === currentDir) return fallbackRoot;
|
|
103
|
+
if (configIsInsideInvocationRoot) {
|
|
104
|
+
const relativeParent = relative(invocationRoot, parentDir);
|
|
105
|
+
if (relativeParent === ".." || relativeParent.startsWith(`..${sep}`)) return invocationRoot;
|
|
106
|
+
}
|
|
107
|
+
currentDir = parentDir;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
85
110
|
function readStringProperty(content, key) {
|
|
86
111
|
return content.match(createPropertyPattern(key, `["']([^"']+)["']`))?.[1];
|
|
87
112
|
}
|
|
@@ -366,4 +391,4 @@ async function loadDocsConfigModuleResultWithProjectEnv(rootDir, explicitPath, o
|
|
|
366
391
|
}
|
|
367
392
|
|
|
368
393
|
//#endregion
|
|
369
|
-
export { resolveDocsContentDir as _, loadDocsConfigModule as a, loadProjectEnv as c, readNavTitle as d, readNumberProperty as f, resolveDocsConfigPath as g, readTopLevelStringProperty as h, hasTopLevelProperty as i, readBooleanProperty as l, readTopLevelBooleanProperty as m, extractObjectLiteral as n, loadDocsConfigModuleResult as o, readStringProperty as p, extractTopLevelConfigObject as r, loadDocsConfigModuleResultWithProjectEnv as s, extractNestedObjectLiteral as t, readEnvReferenceProperty as u };
|
|
394
|
+
export { resolveDocsContentDir as _, loadDocsConfigModule as a, loadProjectEnv as c, readNavTitle as d, readNumberProperty as f, resolveDocsConfigPath as g, readTopLevelStringProperty as h, hasTopLevelProperty as i, readBooleanProperty as l, readTopLevelBooleanProperty as m, extractObjectLiteral as n, loadDocsConfigModuleResult as o, readStringProperty as p, extractTopLevelConfigObject as r, loadDocsConfigModuleResultWithProjectEnv as s, extractNestedObjectLiteral as t, readEnvReferenceProperty as u, resolveDocsProjectRoot as v };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as detectPackageManagerFromProject } from "./utils-DpiIioYb.mjs";
|
|
2
|
-
import { Ct as tsconfigTemplate, Y as rootLayoutTemplate, g as docsLayoutTemplate, q as postcssConfigTemplate, v as globalCssTemplate } from "./templates-
|
|
2
|
+
import { Ct as tsconfigTemplate, Y as rootLayoutTemplate, g as docsLayoutTemplate, q as postcssConfigTemplate, v as globalCssTemplate } from "./templates-Co7I_Okv.mjs";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
@@ -141,6 +141,12 @@ const THEME_PRESETS = {
|
|
|
141
141
|
importPath: "@farming-labs/theme/ledger",
|
|
142
142
|
factory: "ledger"
|
|
143
143
|
},
|
|
144
|
+
shadcn: {
|
|
145
|
+
configName: "shadcn",
|
|
146
|
+
templateTheme: "shadcn",
|
|
147
|
+
importPath: "@farming-labs/theme/shadcn",
|
|
148
|
+
factory: "shadcn"
|
|
149
|
+
},
|
|
144
150
|
greentree: {
|
|
145
151
|
configName: "greentree",
|
|
146
152
|
templateTheme: "greentree",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as scanDocsPageTargets, n as compactAgentDocs, r as inspectAgentCompactionState } from "./agent-
|
|
1
|
+
import { i as scanDocsPageTargets, n as compactAgentDocs, r as inspectAgentCompactionState } from "./agent-Jvn1a78y.mjs";
|
|
2
2
|
import { d as httpLinkHeaderHasTargetRelation, f as AGENT_SKILL_ARCHIVE_MAX_UNCOMPRESSED_BYTES, p as readAgentSkillDocumentFromTar } from "./prompt-references-B6gxePm8.mjs";
|
|
3
3
|
import { A as buildDocsAgentDiscoverySpec, At as DEFAULT_SITEMAP_XML_ROUTE, F as buildDocsMcpEndpointCandidates, Gn as getDocsMcpProtectedResourceMetadataRoutes, It as resolveDocsSitemapConfig, Jn as isDocsMcpOAuthScopeToken, M as buildDocsConfigMap, Ot as DEFAULT_SITEMAP_MD_ROUTE, Qn as normalizeDocsMcpAuthorizationServerUrls, S as DEFAULT_SKILL_MD_WELL_KNOWN_ROUTE, T as DOCS_CONFIG_MAP_TOP_LEVEL_KEYS, Un as DEFAULT_MCP_WELL_KNOWN_ROUTE, Vn as DEFAULT_MCP_PUBLIC_ROUTE, c as DEFAULT_AGENT_SPEC_WELL_KNOWN_JSON_ROUTE, h as DEFAULT_LLMS_FULL_TXT_ROUTE, i as DEFAULT_AGENT_FEEDBACK_ROUTE, kt as DEFAULT_SITEMAP_MD_WELL_KNOWN_ROUTE, l as DEFAULT_AGENT_SPEC_WELL_KNOWN_ROUTE, n as DEFAULT_AGENTS_MD_WELL_KNOWN_ROUTE, pn as resolveAskAISearchRequestConfig, t as DEFAULT_AGENTS_MD_ROUTE, v as DEFAULT_LLMS_TXT_ROUTE, x as DEFAULT_SKILL_MD_ROUTE } from "./agent-CTOUI2BK.mjs";
|
|
4
4
|
import { f as PAGE_AGENT_CONTRACT_FIELDS } from "./markdown-sections-7OoA7ylx.mjs";
|
|
@@ -13,11 +13,11 @@ import { t as runDocsGoldenTasks } from "./agent-evals-DCptRrdP.mjs";
|
|
|
13
13
|
import { createFilesystemDocsMcpSource, getDocsConfigSchema, resolveDocsMcpConfig } from "./mcp.mjs";
|
|
14
14
|
import "./code-blocks-0wjOsqdJ.mjs";
|
|
15
15
|
import "./server.mjs";
|
|
16
|
-
import { _ as resolveDocsContentDir, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, r as extractTopLevelConfigObject, s as loadDocsConfigModuleResultWithProjectEnv, t as extractNestedObjectLiteral } from "./config-
|
|
16
|
+
import { _ as resolveDocsContentDir, d as readNavTitle, g as resolveDocsConfigPath, h as readTopLevelStringProperty, l as readBooleanProperty, r as extractTopLevelConfigObject, s as loadDocsConfigModuleResultWithProjectEnv, t as extractNestedObjectLiteral, v as resolveDocsProjectRoot } from "./config-BtxaQTPP.mjs";
|
|
17
17
|
import { t as detectFramework } from "./utils-DpiIioYb.mjs";
|
|
18
|
-
import { i as createAgentUsefulnessPagesFromMcp, n as analyzeAgentSurfaceDrift, r as analyzeAgentUsefulness, t as resolveGoldenEvaluationInput } from "./golden-evaluations-
|
|
18
|
+
import { i as createAgentUsefulnessPagesFromMcp, n as analyzeAgentSurfaceDrift, r as analyzeAgentUsefulness, t as resolveGoldenEvaluationInput } from "./golden-evaluations-DyeYD50F.mjs";
|
|
19
19
|
import { t as analyzeConfiguredAgentSkillsProgressiveDisclosure } from "./agent-skills-progressive-disclosure-BVvj7nM8.mjs";
|
|
20
|
-
import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
|
|
20
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
21
21
|
import path from "node:path";
|
|
22
22
|
import { createHash } from "node:crypto";
|
|
23
23
|
import { gunzipSync } from "node:zlib";
|
|
@@ -73,6 +73,23 @@ function parseDoctorArgs(argv) {
|
|
|
73
73
|
parsed.json = true;
|
|
74
74
|
continue;
|
|
75
75
|
}
|
|
76
|
+
if (arg.startsWith("--json-output=")) {
|
|
77
|
+
const value = parseInlineFlag(arg).value;
|
|
78
|
+
if (!value) throw new Error("Missing value for --json-output.");
|
|
79
|
+
parsed.jsonOutputPath = value;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (arg === "--json-output") {
|
|
83
|
+
const value = argv[index + 1];
|
|
84
|
+
if (!value || value.startsWith("--")) throw new Error("Missing value for --json-output.");
|
|
85
|
+
parsed.jsonOutputPath = value;
|
|
86
|
+
index += 1;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (arg === "--ci") {
|
|
90
|
+
parsed.ci = true;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
76
93
|
if (arg === "--strict") {
|
|
77
94
|
parsed.strict = true;
|
|
78
95
|
continue;
|
|
@@ -170,6 +187,8 @@ ${pc.dim("Options:")}
|
|
|
170
187
|
${pc.cyan("--human")} Alias for ${pc.cyan("--site")}
|
|
171
188
|
${pc.cyan("--only <mode>")} Run only one doctor suite: ${pc.cyan("agent")} or ${pc.cyan("site")}
|
|
172
189
|
${pc.cyan("--json")} Print the report as JSON for CI, scripts, and other agents
|
|
190
|
+
${pc.cyan("--json-output <path>")} Write the JSON report to a file; use with ${pc.cyan("--ci")} to keep annotation stdout valid
|
|
191
|
+
${pc.cyan("--ci")} Emit actionable GitHub annotations when running in GitHub Actions
|
|
173
192
|
${pc.cyan("--strict")} Exit with failure when any check warns or fails
|
|
174
193
|
${pc.cyan("--fix")} Refresh stale generated agent.md files and token-budget missing outputs
|
|
175
194
|
${pc.cyan("--dry-run")} With ${pc.cyan("--fix")}, report the compaction command without writing files
|
|
@@ -1631,7 +1650,7 @@ async function buildHostedAgentChecks(url, pages) {
|
|
|
1631
1650
|
checks
|
|
1632
1651
|
};
|
|
1633
1652
|
}
|
|
1634
|
-
function makeCheck(id, title, status, score, maxScore, detail, recommendation) {
|
|
1653
|
+
function makeCheck(id, title, status, score, maxScore, detail, recommendation, findings) {
|
|
1635
1654
|
return {
|
|
1636
1655
|
id,
|
|
1637
1656
|
title,
|
|
@@ -1639,19 +1658,38 @@ function makeCheck(id, title, status, score, maxScore, detail, recommendation) {
|
|
|
1639
1658
|
score,
|
|
1640
1659
|
maxScore,
|
|
1641
1660
|
detail,
|
|
1642
|
-
recommendation
|
|
1643
|
-
|
|
1661
|
+
recommendation,
|
|
1662
|
+
findings
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
function toDoctorCommandFindings(findings) {
|
|
1666
|
+
return findings.filter((finding) => finding.category === "command" && Boolean(finding.command) && Boolean(finding.proposedCorrection)).map((finding) => ({
|
|
1667
|
+
code: finding.code,
|
|
1668
|
+
severity: finding.severity,
|
|
1669
|
+
file: finding.file,
|
|
1670
|
+
line: finding.line,
|
|
1671
|
+
command: finding.command,
|
|
1672
|
+
reason: finding.message,
|
|
1673
|
+
proposedCorrection: finding.proposedCorrection
|
|
1674
|
+
}));
|
|
1644
1675
|
}
|
|
1645
1676
|
async function inspectAgentReadiness(options = {}) {
|
|
1646
|
-
const
|
|
1647
|
-
|
|
1648
|
-
|
|
1677
|
+
const invocationRoot = process.cwd();
|
|
1678
|
+
let rootDir = invocationRoot;
|
|
1679
|
+
let files = [];
|
|
1680
|
+
let framework = "unknown";
|
|
1649
1681
|
const configCheckMax = 10;
|
|
1650
1682
|
let configPath;
|
|
1651
1683
|
try {
|
|
1652
|
-
configPath = resolveDocsConfigPath(
|
|
1684
|
+
configPath = resolveDocsConfigPath(invocationRoot, options.configPath);
|
|
1685
|
+
rootDir = resolveDocsProjectRoot(invocationRoot, configPath);
|
|
1686
|
+
files = listProjectFiles(rootDir);
|
|
1687
|
+
framework = detectFramework(rootDir) ?? detectFrameworkFromFiles(files) ?? "unknown";
|
|
1653
1688
|
} catch (error) {
|
|
1654
|
-
const
|
|
1689
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1690
|
+
const invocationFiles = listProjectFiles(invocationRoot);
|
|
1691
|
+
framework = detectFramework(invocationRoot) ?? detectFrameworkFromFiles(invocationFiles) ?? "unknown";
|
|
1692
|
+
const checks = [makeCheck("config", "Docs config", "fail", 0, configCheckMax, message, "Add docs.config.ts[x] or pass --config so the doctor can inspect the docs app.")];
|
|
1655
1693
|
return {
|
|
1656
1694
|
mode: "agent",
|
|
1657
1695
|
framework,
|
|
@@ -1678,7 +1716,7 @@ async function inspectAgentReadiness(options = {}) {
|
|
|
1678
1716
|
};
|
|
1679
1717
|
}
|
|
1680
1718
|
const configContent = readFileSync(configPath, "utf-8");
|
|
1681
|
-
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir,
|
|
1719
|
+
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir, configPath);
|
|
1682
1720
|
const config = configLoad.status === "evaluated" ? configLoad.config : void 0;
|
|
1683
1721
|
let configuredAgentSkillNames;
|
|
1684
1722
|
let configuredAgentSkillsError;
|
|
@@ -1727,6 +1765,7 @@ async function inspectAgentReadiness(options = {}) {
|
|
|
1727
1765
|
pages: createAgentUsefulnessPagesFromMcp(rootDir, pages),
|
|
1728
1766
|
projectFramework: framework === "unknown" ? void 0 : framework
|
|
1729
1767
|
});
|
|
1768
|
+
const commandFindings = toDoctorCommandFindings(usefulness.findings);
|
|
1730
1769
|
const evaluationInput = config?.agent?.evaluations;
|
|
1731
1770
|
const evaluation = resolveGoldenEvaluationInput(evaluationInput);
|
|
1732
1771
|
const evaluationBaseUrl = config ? resolveDocsMetadataBaseUrl(config) : void 0;
|
|
@@ -1874,7 +1913,7 @@ async function inspectAgentReadiness(options = {}) {
|
|
|
1874
1913
|
checks.push(makeCheck("agent-context-quality", "Agent context usefulness", contextQualityResult.status, contextQualityResult.score, 15, usefulness.metrics.agentBlocks.total > 0 ? `${usefulness.metrics.agentBlocks.useful}/${usefulness.metrics.agentBlocks.total} agent-only blocks are specific and non-repetitive (${usefulness.metrics.agentBlocks.duplicate} duplicate, ${usefulness.metrics.agentBlocks.boilerplate} boilerplate, ${usefulness.metrics.agentBlocks.generic} generic).` : "No embedded agent-only blocks were present; page contracts and sibling agent.md files remain available as alternatives.", usefulness.metrics.agentBlocks.total > 0 && usefulness.metrics.agentBlocks.useful === usefulness.metrics.agentBlocks.total ? void 0 : "Replace repeated agent-only boilerplate with page-specific constraints, commands, files, expected results, and recovery guidance."));
|
|
1875
1914
|
checks.push(makeCheck("agent-task-completeness", "Agent task completeness", taskCompletenessResult.status, taskCompletenessResult.score, 15, `${usefulness.metrics.taskCompleteness.completePages}/${usefulness.metrics.actionablePages} actionable pages include prerequisites, an expected result, and recovery guidance (${usefulness.metrics.taskCompleteness.coverage}% complete).`, usefulness.metrics.actionablePages > 0 && usefulness.metrics.taskCompleteness.coverage >= 80 ? void 0 : "Add prerequisites, observable outcomes or verification expectations, and rollback or resolved failure modes to actionable pages."));
|
|
1876
1915
|
checks.push(makeCheck("agent-applicability", "Framework and version applicability", applicabilityResult.status, applicabilityResult.score, 10, `${usefulness.metrics.applicability.conflictingPages} conflicting, ${usefulness.metrics.applicability.ambiguousPages} ambiguous, and ${usefulness.metrics.applicability.mismatchedPages} project-mismatched actionable pages.`, usefulness.metrics.actionablePages > 0 && applicabilityIssueCount === 0 ? void 0 : "Declare consistent framework/version metadata in page frontmatter and agent.appliesTo so retrieval can select the right variant."));
|
|
1877
|
-
checks.push(makeCheck("command-health", "Documented command health", commandHealthResult.status, commandHealthResult.score, 10, `${usefulness.metrics.commands.healthy}/${usefulness.metrics.commands.total} statically inspected commands are healthy; ${usefulness.metrics.commands.unhealthy} are unhealthy and ${usefulness.metrics.commands.unverified} could not be verified safely.`, usefulness.metrics.commands.total > 0 && usefulness.metrics.commands.unhealthy === 0 && usefulness.metrics.commands.unverified === 0 ? void 0 : "Update broken or stale commands and make workspace selectors resolvable so scripts, working directories, package managers, and docs CLI subcommands can be verified."));
|
|
1916
|
+
checks.push(makeCheck("command-health", "Documented command health", commandHealthResult.status, commandHealthResult.score, 10, `${usefulness.metrics.commands.healthy}/${usefulness.metrics.commands.total} statically inspected commands are healthy; ${usefulness.metrics.commands.unhealthy} are unhealthy and ${usefulness.metrics.commands.unverified} could not be verified safely.`, usefulness.metrics.commands.total > 0 && usefulness.metrics.commands.unhealthy === 0 && usefulness.metrics.commands.unverified === 0 ? void 0 : "Update broken or stale commands and make workspace selectors resolvable so scripts, working directories, package managers, and docs CLI subcommands can be verified.", commandFindings));
|
|
1878
1917
|
checks.push(makeCheck("related-coverage", "Related-page task coverage", relatedCoverageResult.status, relatedCoverageResult.score, 5, `${usefulness.metrics.related.coveredActionablePages}/${usefulness.metrics.actionablePages} actionable pages link to a valid related docs route; ${usefulness.metrics.related.brokenLinks} related links are broken.`, usefulness.metrics.actionablePages > 0 && usefulness.metrics.related.coverage >= 80 && usefulness.metrics.related.brokenLinks === 0 ? void 0 : "Add and validate related routes on actionable pages so agents can expand context without guessing."));
|
|
1879
1918
|
checks.push(makeCheck("compact", "Agent compaction freshness", compactionResult.status, compactionResult.score, 5, `${compactionCoverage.freshGeneratedPages} fresh, ${compactionCoverage.staleGeneratedPages} stale, ${compactionCoverage.modifiedGeneratedPages} modified, ${compactionCoverage.unknownGeneratedPages} unknown, ${compactionCoverage.tokenBudgetMissingPages} token-budget missing, and ${compactionCoverage.otherMissingPages} other missing page${compactionCoverage.otherMissingPages === 1 ? "" : "s"} across compactable docs pages.` + (compactConfigured ? " agent.compact defaults are configured." : " No agent.compact defaults were found in docs config."), compactionResult.recommendation));
|
|
1880
1919
|
const averageMetric = (values) => values.length === 0 ? 0 : Math.round(values.reduce((total, value) => total + value, 0) / values.length * 100) / 100;
|
|
@@ -1902,15 +1941,22 @@ async function inspectAgentReadiness(options = {}) {
|
|
|
1902
1941
|
};
|
|
1903
1942
|
}
|
|
1904
1943
|
async function inspectHumanReadiness(options = {}) {
|
|
1905
|
-
const
|
|
1906
|
-
|
|
1907
|
-
|
|
1944
|
+
const invocationRoot = process.cwd();
|
|
1945
|
+
let rootDir = invocationRoot;
|
|
1946
|
+
let files = [];
|
|
1947
|
+
let framework = "unknown";
|
|
1908
1948
|
const configCheckMax = 10;
|
|
1909
1949
|
let configPath;
|
|
1910
1950
|
try {
|
|
1911
|
-
configPath = resolveDocsConfigPath(
|
|
1951
|
+
configPath = resolveDocsConfigPath(invocationRoot, options.configPath);
|
|
1952
|
+
rootDir = resolveDocsProjectRoot(invocationRoot, configPath);
|
|
1953
|
+
files = listProjectFiles(rootDir);
|
|
1954
|
+
framework = detectFramework(rootDir) ?? detectFrameworkFromFiles(files) ?? "unknown";
|
|
1912
1955
|
} catch (error) {
|
|
1913
|
-
const
|
|
1956
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1957
|
+
const invocationFiles = listProjectFiles(invocationRoot);
|
|
1958
|
+
framework = detectFramework(invocationRoot) ?? detectFrameworkFromFiles(invocationFiles) ?? "unknown";
|
|
1959
|
+
const checks = [makeCheck("config", "Docs config", "fail", 0, configCheckMax, message, "Add docs.config.ts[x] or pass --config so the doctor can inspect the docs app.")];
|
|
1914
1960
|
return {
|
|
1915
1961
|
mode: "human",
|
|
1916
1962
|
framework,
|
|
@@ -1931,7 +1977,7 @@ async function inspectHumanReadiness(options = {}) {
|
|
|
1931
1977
|
};
|
|
1932
1978
|
}
|
|
1933
1979
|
const configContent = readFileSync(configPath, "utf-8");
|
|
1934
|
-
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir,
|
|
1980
|
+
const configLoad = await loadDocsConfigModuleResultWithProjectEnv(rootDir, configPath);
|
|
1935
1981
|
const config = configLoad.status === "evaluated" ? configLoad.config : void 0;
|
|
1936
1982
|
const entry = config?.entry ?? readTopLevelStringProperty(configContent, "entry") ?? "docs";
|
|
1937
1983
|
const contentDir = config?.contentDir ?? resolveDocsContentDir(rootDir, configContent, entry);
|
|
@@ -1996,6 +2042,12 @@ function printAgentDoctorReport(report) {
|
|
|
1996
2042
|
for (const check of report.checks) {
|
|
1997
2043
|
console.log(`${formatStatus(check.status)} ${check.title} ${pc.dim(`(${check.score}/${check.maxScore})`)}`);
|
|
1998
2044
|
console.log(` ${check.detail}`);
|
|
2045
|
+
for (const finding of check.findings ?? []) {
|
|
2046
|
+
const location = `${finding.file}${finding.line ? `:${finding.line}` : ""}`;
|
|
2047
|
+
console.log(` ${pc.dim(location)} ${pc.bold("Command:")} ${finding.command}`);
|
|
2048
|
+
console.log(` ${pc.bold("Reason:")} ${finding.reason}`);
|
|
2049
|
+
console.log(` ${pc.bold("Proposed correction:")} ${finding.proposedCorrection}`);
|
|
2050
|
+
}
|
|
1999
2051
|
}
|
|
2000
2052
|
if (report.recommendations.length > 0) {
|
|
2001
2053
|
console.log();
|
|
@@ -2032,6 +2084,30 @@ function serializeDoctorJsonReport(report) {
|
|
|
2032
2084
|
function printDoctorJsonReport(report) {
|
|
2033
2085
|
console.log(JSON.stringify(serializeDoctorJsonReport(report), null, 2));
|
|
2034
2086
|
}
|
|
2087
|
+
function writeDoctorJsonReport(report, outputPath) {
|
|
2088
|
+
const resolvedPath = path.resolve(process.cwd(), outputPath);
|
|
2089
|
+
mkdirSync(path.dirname(resolvedPath), { recursive: true });
|
|
2090
|
+
writeFileSync(resolvedPath, `${JSON.stringify(serializeDoctorJsonReport(report), null, 2)}\n`, "utf-8");
|
|
2091
|
+
}
|
|
2092
|
+
function escapeGitHubAnnotationData(value) {
|
|
2093
|
+
return value.replaceAll("%", "%25").replaceAll("\r", "%0D").replaceAll("\n", "%0A");
|
|
2094
|
+
}
|
|
2095
|
+
function escapeGitHubAnnotationProperty(value) {
|
|
2096
|
+
return escapeGitHubAnnotationData(value).replaceAll(":", "%3A").replaceAll(",", "%2C");
|
|
2097
|
+
}
|
|
2098
|
+
function emitDoctorGitHubAnnotations(report) {
|
|
2099
|
+
if (process.env.GITHUB_ACTIONS !== "true" || report.mode !== "agent") return;
|
|
2100
|
+
for (const check of report.checks) for (const finding of check.findings ?? []) {
|
|
2101
|
+
const command = finding.severity === "error" ? "error" : finding.severity === "warning" ? "warning" : "notice";
|
|
2102
|
+
const location = [
|
|
2103
|
+
`file=${escapeGitHubAnnotationProperty(finding.file)}`,
|
|
2104
|
+
finding.line ? `line=${finding.line}` : void 0,
|
|
2105
|
+
`title=${escapeGitHubAnnotationProperty(check.title)}`
|
|
2106
|
+
].filter(Boolean).join(",");
|
|
2107
|
+
const message = `Command: ${finding.command} Reason: ${finding.reason} Proposed correction: ${finding.proposedCorrection}`;
|
|
2108
|
+
console.log(`::${command} ${location}::${escapeGitHubAnnotationData(message)}`);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2035
2111
|
function hasNonPassingDoctorCheck(report) {
|
|
2036
2112
|
return report.checks.some((check) => check.status !== "pass");
|
|
2037
2113
|
}
|
|
@@ -2093,15 +2169,18 @@ async function runAgentDoctorFixes(report, options) {
|
|
|
2093
2169
|
return fixes;
|
|
2094
2170
|
}
|
|
2095
2171
|
async function runDoctor(options = {}) {
|
|
2172
|
+
if (options.ci && options.json) throw new Error("doctor --ci and --json cannot share stdout. Use --ci --json-output <path> to emit GitHub annotations and persist the JSON report in one run.");
|
|
2096
2173
|
if (options.mode === "human") {
|
|
2097
2174
|
if (options.fix) throw new Error("doctor --fix is currently only supported with --agent.");
|
|
2098
2175
|
const report = await inspectHumanReadiness(options);
|
|
2099
2176
|
applyDoctorExitCode(report, options);
|
|
2177
|
+
if (options.jsonOutputPath) writeDoctorJsonReport(report, options.jsonOutputPath);
|
|
2100
2178
|
if (options.json) {
|
|
2101
2179
|
printDoctorJsonReport(report);
|
|
2102
2180
|
return report;
|
|
2103
2181
|
}
|
|
2104
2182
|
printHumanDoctorReport(report);
|
|
2183
|
+
if (options.ci) emitDoctorGitHubAnnotations(report);
|
|
2105
2184
|
return report;
|
|
2106
2185
|
}
|
|
2107
2186
|
let report = await inspectAgentReadiness(options);
|
|
@@ -2117,11 +2196,13 @@ async function runDoctor(options = {}) {
|
|
|
2117
2196
|
};
|
|
2118
2197
|
}
|
|
2119
2198
|
applyDoctorExitCode(report, options);
|
|
2199
|
+
if (options.jsonOutputPath) writeDoctorJsonReport(report, options.jsonOutputPath);
|
|
2120
2200
|
if (options.json) {
|
|
2121
2201
|
printDoctorJsonReport(report);
|
|
2122
2202
|
return report;
|
|
2123
2203
|
}
|
|
2124
2204
|
printAgentDoctorReport(report);
|
|
2205
|
+
if (options.ci) emitDoctorGitHubAnnotations(report);
|
|
2125
2206
|
return report;
|
|
2126
2207
|
}
|
|
2127
2208
|
|