delivery-friction-analyzer 0.21.2 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/docs/reference/run-presets.md +3 -3
- package/package.json +1 -1
- package/release-log.md +8 -0
- package/src/cli/analyze-github.js +127 -22
package/README.md
CHANGED
|
@@ -131,7 +131,7 @@ Each ranked bottleneck example includes source references, workflow-run conclusi
|
|
|
131
131
|
|
|
132
132
|
Use `--source sample` for the bundled synthetic tutorial data. Use `--source github` for live repository analysis. Existing live commands that pass `--repo`, `--profile`, or `--limit` without `--source` still run as GitHub analysis, but new users should prefer the explicit source flag.
|
|
133
133
|
|
|
134
|
-
Use `--dry-run` or `--metadata-only` to
|
|
134
|
+
Use `--dry-run` or `--metadata-only` with `--source github` to run a live GitHub coverage probe that validates repository access, profile JSON, output directory writability, and sampled API coverage without writing full report artifacts. The output directory may be created during this check, and a temporary probe file may be written and removed.
|
|
135
135
|
|
|
136
136
|
Use `--no-csv` when you want the Markdown, JSON, source, normalized, metrics, and methodology artifacts without spreadsheet-friendly CSV exports.
|
|
137
137
|
|
|
@@ -139,7 +139,7 @@ Use `--exclude-pr-class <class>` to remove a configured PR class from downstream
|
|
|
139
139
|
|
|
140
140
|
Use `--json` when automation needs the full machine-readable completion receipt on stdout.
|
|
141
141
|
|
|
142
|
-
Use `--interactive` only in a terminal when you want prompts. When combined with `--json`, prompts and progress stay off stdout so the final completion receipt remains parseable JSON.
|
|
142
|
+
Use `--interactive` only in a terminal when you want prompts for live GitHub setup. Enter `?` at supported prompts for contextual help without restarting the flow. When combined with `--json`, prompts and progress stay off stdout so the final completion receipt remains parseable JSON.
|
|
143
143
|
|
|
144
144
|
## How To Read A Report
|
|
145
145
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Run Presets
|
|
2
2
|
|
|
3
|
-
Run presets are optional local JSON files for reusing CLI run settings. They are intended for rerunning the same analysis without re-answering interactive prompts.
|
|
3
|
+
Run presets are optional local JSON files for reusing live GitHub CLI run settings. They are intended for rerunning the same live analysis without re-answering interactive prompts. The bundled `--source sample` tutorial path does not save or load presets.
|
|
4
4
|
|
|
5
|
-
Repository meaning stays in repository profiles. Put file rules, PR class rules, workflow context, branch or release strategy, and contributor-source declarations in a repository profile. A run preset may only point at a profile and store run inputs or preferences such as the target repository,
|
|
5
|
+
Repository meaning stays in repository profiles. Put file rules, PR class rules, workflow context, branch or release strategy, and contributor-source declarations in a repository profile. A run preset may only point at a profile and store live run inputs or preferences such as the target repository, pull request limit, output directory, dry-run coverage-probe mode, CSV preference, JSON completion preference, validation-target mode, and requested PR class exclusions.
|
|
6
6
|
|
|
7
7
|
When a preset supplies `profilePath`, the CLI validates that referenced profile exactly as if it had been passed with `--profile`. Presets do not copy, freeze, or override profile rules; fixing profile validation failures means editing the referenced profile or choosing a different profile path.
|
|
8
8
|
|
|
9
9
|
## Save A Preset
|
|
10
10
|
|
|
11
|
-
Interactive setup asks whether to save a local run preset near the end of the prompt flow. If you answer yes, you choose the preset path explicitly. The CLI does not invent a global or cloud-synced preset location.
|
|
11
|
+
Interactive live GitHub setup asks whether to save a local run preset near the end of the prompt flow. If you answer yes, you choose the preset path explicitly. The CLI does not invent a global or cloud-synced preset location.
|
|
12
12
|
|
|
13
13
|
Saving a preset may overwrite an existing regular file at that path, but the path must not be a directory, symbolic link, or other special file.
|
|
14
14
|
|
package/package.json
CHANGED
package/release-log.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
### 2026-06-28 — CLI Command Help Clarity
|
|
6
|
+
|
|
7
|
+
- What changed: CLI help now separates the bundled sample, live GitHub analysis, live coverage probes, output controls, interactive setup, and reusable live-run presets, with mode-specific help for `--source sample --help` and `--source github --help`.
|
|
8
|
+
- Why it matters: First-time users and maintainers can choose the right workflow before running into rejected flag combinations, and interactive setup can explain supported prompts without restarting the flow.
|
|
9
|
+
- Who is affected: Users trying the bundled sample, maintainers running live GitHub analysis or dry-run coverage probes, and contributors reviewing CLI setup behavior.
|
|
10
|
+
- Action needed: None.
|
|
11
|
+
- PR: https://github.com/hannasdev/delivery-friction-analyzer/pull/67
|
|
12
|
+
|
|
5
13
|
### 2026-06-27 — First-Run Profile Prompt Clarity
|
|
6
14
|
|
|
7
15
|
- What changed: Interactive GitHub setup now explains starter-profile limitations, gives clearer guidance before adding Conventional Commit PR class rules, and only prints the starter-profile completion reminder when a new profile was created.
|
|
@@ -135,30 +135,84 @@ const CSV_ARTIFACT_KEYS = new Set([
|
|
|
135
135
|
export const USAGE = `Usage:
|
|
136
136
|
delivery-friction-analyzer --source sample --out <directory>
|
|
137
137
|
delivery-friction-analyzer --source github --repo <owner/name> --limit <1-100> --profile <path> --out <directory>
|
|
138
|
-
delivery-friction-analyzer --repo <owner/name> --limit <1-100> --profile <path> --out <directory>
|
|
139
|
-
delivery-friction-analyzer --repo <owner/name> --limit <1-100> --profile <path> --out <directory> --dry-run
|
|
140
138
|
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
Workflows:
|
|
140
|
+
Sample tutorial:
|
|
141
|
+
Uses bundled synthetic data. Accepts output controls only.
|
|
142
|
+
delivery-friction-analyzer --source sample --out reports/tutorial
|
|
143
|
+
|
|
144
|
+
Live GitHub analysis:
|
|
145
|
+
Collects repository data from GitHub using a repository profile.
|
|
146
|
+
delivery-friction-analyzer --source github --repo owner/name --limit 30 --profile path/to/profile.json --out reports/owner-name
|
|
147
|
+
|
|
148
|
+
Live GitHub coverage probe:
|
|
149
|
+
--dry-run and --metadata-only validate live GitHub access, profile JSON, output writability, and sampled API coverage without report artifacts.
|
|
150
|
+
delivery-friction-analyzer --source github --repo owner/name --limit 30 --profile path/to/profile.json --out reports/owner-name --dry-run
|
|
151
|
+
|
|
152
|
+
Output controls:
|
|
153
|
+
--out <directory> Output directory for generated artifacts.
|
|
154
|
+
--json Print the machine-readable completion receipt to stdout.
|
|
155
|
+
--no-json Disable JSON completion output.
|
|
156
|
+
--csv Enable curated CSV evidence exports when a preset disabled them.
|
|
157
|
+
--no-csv Suppress curated CSV evidence exports.
|
|
158
|
+
|
|
159
|
+
Help:
|
|
160
|
+
--source sample --help Show sample-mode options.
|
|
161
|
+
--source github --help Show live GitHub, dry-run, interactive, and preset options.
|
|
162
|
+
`;
|
|
163
|
+
|
|
164
|
+
export const SAMPLE_USAGE = `Usage:
|
|
165
|
+
delivery-friction-analyzer --source sample --out <directory>
|
|
166
|
+
|
|
167
|
+
Sample tutorial:
|
|
168
|
+
Uses bundled synthetic data and never calls GitHub.
|
|
169
|
+
Sample mode writes the same report bundle shape as a live analysis for tutorial use.
|
|
170
|
+
|
|
171
|
+
Sample output controls:
|
|
172
|
+
--out <directory> Required output directory for generated sample artifacts.
|
|
173
|
+
--json Print the machine-readable completion receipt to stdout.
|
|
174
|
+
--no-json Disable JSON completion output.
|
|
175
|
+
--csv Enable curated CSV evidence exports.
|
|
176
|
+
--no-csv Suppress curated CSV evidence exports.
|
|
177
|
+
|
|
178
|
+
Live-only flags are not supported with --source sample:
|
|
179
|
+
--repo, --limit, --profile, --dry-run, --metadata-only, --validation-target,
|
|
180
|
+
--interactive, --preset, --save-preset, --exclude-pr-class, --allow-product-repository
|
|
181
|
+
`;
|
|
182
|
+
|
|
183
|
+
export const GITHUB_USAGE = `Usage:
|
|
184
|
+
delivery-friction-analyzer --source github --repo <owner/name> --limit <1-100> --profile <path> --out <directory>
|
|
185
|
+
delivery-friction-analyzer --source github --repo <owner/name> --limit <1-100> --profile <path> --out <directory> --dry-run
|
|
186
|
+
delivery-friction-analyzer --interactive --source github
|
|
187
|
+
|
|
188
|
+
Live GitHub analysis:
|
|
143
189
|
--repo <owner/name> Target GitHub repository to analyze.
|
|
144
190
|
--limit <1-100> Latest merged pull request count.
|
|
145
191
|
--profile <path> Repository profile JSON used for file role classification.
|
|
146
192
|
--out <directory> Output directory for generated artifacts.
|
|
147
|
-
|
|
148
|
-
|
|
193
|
+
|
|
194
|
+
Live GitHub coverage probes:
|
|
195
|
+
--dry-run Validate live GitHub access, profile JSON, output writability, and sampled API coverage without writing report artifacts.
|
|
149
196
|
--metadata-only Alias for --dry-run.
|
|
197
|
+
--no-dry-run Disable dry-run mode when a preset enabled it.
|
|
198
|
+
|
|
199
|
+
Live filters and metadata:
|
|
150
200
|
--validation-target Mark output metadata as an internal validation run; does not bypass target validation.
|
|
151
201
|
--no-validation-target Disable validation-target mode when a preset enabled it.
|
|
152
202
|
--allow-product-repository
|
|
153
203
|
Explicit live-analysis override for intentional self-analysis of this product repository.
|
|
154
|
-
--exclude-pr-class <cls> Exclude a PR class from normalized, metrics, report, methodology, and CSV artifacts. Repeat or comma-separate values.
|
|
155
|
-
|
|
156
|
-
|
|
204
|
+
--exclude-pr-class <cls> Exclude a configured PR class from downstream normalized, metrics, report, methodology, and CSV artifacts. Repeat or comma-separate values.
|
|
205
|
+
|
|
206
|
+
Output controls:
|
|
157
207
|
--json Print the machine-readable completion receipt to stdout.
|
|
158
208
|
--no-json Disable JSON completion output when a preset enabled it.
|
|
159
|
-
--
|
|
160
|
-
--
|
|
161
|
-
|
|
209
|
+
--csv Enable curated CSV evidence exports when a preset disabled them.
|
|
210
|
+
--no-csv Suppress curated CSV evidence exports.
|
|
211
|
+
|
|
212
|
+
Interactive setup and presets:
|
|
213
|
+
--interactive Prompt for missing live GitHub run options in a terminal; enter ? at supported prompts for contextual help.
|
|
214
|
+
--preset <path> Load reusable live GitHub run settings from a saved preset. Explicit CLI flags override preset values.
|
|
215
|
+
--save-preset <path> Save reusable live GitHub run settings for non-interactive reruns.
|
|
162
216
|
`;
|
|
163
217
|
|
|
164
218
|
export const SOURCE_SELECTION_GUIDANCE = `Choose what to analyze.
|
|
@@ -199,6 +253,13 @@ function explicitCliOptionKeys(argv) {
|
|
|
199
253
|
}
|
|
200
254
|
|
|
201
255
|
export function parseAnalyzeGithubArgs(argv) {
|
|
256
|
+
if (hasHelpOption(argv)) {
|
|
257
|
+
const parsed = { help: true };
|
|
258
|
+
const source = sourceForHelp(argv);
|
|
259
|
+
if (source !== undefined) parsed.source = source;
|
|
260
|
+
return attachOptionSource(parsed, "explicitCliOptions", new Set(source === undefined ? [] : ["source"]));
|
|
261
|
+
}
|
|
262
|
+
|
|
202
263
|
const options = {
|
|
203
264
|
dryRun: false,
|
|
204
265
|
isValidationTarget: false,
|
|
@@ -209,9 +270,6 @@ export function parseAnalyzeGithubArgs(argv) {
|
|
|
209
270
|
const explicitOptions = explicitCliOptionKeys(argv);
|
|
210
271
|
for (let index = 0; index < argv.length; index += 1) {
|
|
211
272
|
const arg = argv[index];
|
|
212
|
-
if (arg === "--help" || arg === "-h") {
|
|
213
|
-
return { help: true };
|
|
214
|
-
}
|
|
215
273
|
if (!arg.startsWith("--")) {
|
|
216
274
|
throw new Error(`Unexpected argument: ${arg}`);
|
|
217
275
|
}
|
|
@@ -268,6 +326,25 @@ export function parseAnalyzeGithubArgs(argv) {
|
|
|
268
326
|
return attachOptionSource(parsed, "explicitCliOptions", explicitOptions);
|
|
269
327
|
}
|
|
270
328
|
|
|
329
|
+
function hasHelpOption(argv) {
|
|
330
|
+
return argv.includes("--help") || argv.includes("-h");
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function sourceForHelp(argv) {
|
|
334
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
335
|
+
if (argv[index] !== "--source") continue;
|
|
336
|
+
const source = argv[index + 1];
|
|
337
|
+
if (source === "sample" || source === "github") return source;
|
|
338
|
+
}
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function usageForOptions(options) {
|
|
343
|
+
if (options?.source === "sample") return SAMPLE_USAGE;
|
|
344
|
+
if (options?.source === "github") return GITHUB_USAGE;
|
|
345
|
+
return USAGE;
|
|
346
|
+
}
|
|
347
|
+
|
|
271
348
|
function normalizeExcludedPrClasses(values) {
|
|
272
349
|
return [...new Set(values
|
|
273
350
|
.flatMap(value => String(value).split(","))
|
|
@@ -537,7 +614,7 @@ function rejectSampleLiveOptions(options) {
|
|
|
537
614
|
incompatible.push("--exclude-pr-class");
|
|
538
615
|
}
|
|
539
616
|
if (!incompatible.length) return;
|
|
540
|
-
throw new Error(`--source sample cannot be combined with live GitHub option(s): ${incompatible.join(", ")}.
|
|
617
|
+
throw new Error(`--source sample cannot be combined with live GitHub option(s): ${incompatible.join(", ")}. Allowed sample output controls are --out, --json, --no-json, --csv, and --no-csv. Use --source github for live repository, dry-run, interactive, preset, validation, and PR-class filtering options.`);
|
|
541
618
|
}
|
|
542
619
|
|
|
543
620
|
function targetInputFromRepositorySlug(repository) {
|
|
@@ -590,21 +667,22 @@ function formatChoiceList(choices) {
|
|
|
590
667
|
}
|
|
591
668
|
|
|
592
669
|
function formatInteractivePrompt(prompt) {
|
|
670
|
+
const helpSuffix = prompt.help ? " Enter ? for help" : "";
|
|
593
671
|
const suffix = prompt.defaultValue === undefined
|
|
594
672
|
? ""
|
|
595
673
|
: Array.isArray(prompt.defaultValue)
|
|
596
674
|
? (prompt.defaultValue.length ? ` [${prompt.defaultValue.join(",")}]` : "")
|
|
597
675
|
: ` [${prompt.defaultValue}]`;
|
|
598
676
|
if (prompt.type === "confirm") {
|
|
599
|
-
return `${prompt.message}${prompt.defaultValue ? " [Y/n]" : " [y/N]"} `;
|
|
677
|
+
return `${prompt.message}${helpSuffix}${prompt.defaultValue ? " [Y/n]" : " [y/N]"} `;
|
|
600
678
|
}
|
|
601
679
|
if (prompt.type === "multi-select" && prompt.choices?.length) {
|
|
602
|
-
return `${prompt.message} (${prompt.choices.map(choiceValue).join(",")})${suffix}: `;
|
|
680
|
+
return `${prompt.message}${helpSuffix} (${prompt.choices.map(choiceValue).join(",")})${suffix}: `;
|
|
603
681
|
}
|
|
604
682
|
if (prompt.type === "select" && prompt.choices?.length) {
|
|
605
|
-
return `${prompt.message}\n${formatChoiceList(prompt.choices)}\nChoose a number or identifier${suffix}: `;
|
|
683
|
+
return `${prompt.message}${helpSuffix}\n${formatChoiceList(prompt.choices)}\nChoose a number or identifier${suffix}: `;
|
|
606
684
|
}
|
|
607
|
-
return `${prompt.message}${suffix}: `;
|
|
685
|
+
return `${prompt.message}${helpSuffix}${suffix}: `;
|
|
608
686
|
}
|
|
609
687
|
|
|
610
688
|
function createTerminalPromptAdapter({ input, output }) {
|
|
@@ -632,6 +710,16 @@ async function callPromptAdapter(promptAdapter, prompt) {
|
|
|
632
710
|
async function askUntilValid(promptAdapter, prompt, { normalize, validate, output }) {
|
|
633
711
|
for (;;) {
|
|
634
712
|
const raw = await callPromptAdapter(promptAdapter, prompt);
|
|
713
|
+
if (String(raw ?? "").trim() === "?" && prompt.help) {
|
|
714
|
+
if (typeof promptAdapter.writeHelp === "function") {
|
|
715
|
+
promptAdapter.writeHelp(prompt.help);
|
|
716
|
+
} else if (typeof promptAdapter.writeError === "function") {
|
|
717
|
+
promptAdapter.writeError(prompt.help);
|
|
718
|
+
} else if (output?.write) {
|
|
719
|
+
output.write(`${prompt.help}\n`);
|
|
720
|
+
}
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
635
723
|
try {
|
|
636
724
|
const value = normalize(raw, prompt);
|
|
637
725
|
await validate(value);
|
|
@@ -950,6 +1038,7 @@ async function promptConventionalCommitPrClassPreset(promptAdapter, output, prof
|
|
|
950
1038
|
id: "addConventionalCommitPrClasses",
|
|
951
1039
|
type: "confirm",
|
|
952
1040
|
message,
|
|
1041
|
+
help: "Optional profile setup: add reusable title rules when Conventional Commit prefixes match this repository. This changes profile classification only, not scoring or GitHub collection.",
|
|
953
1042
|
defaultValue: false,
|
|
954
1043
|
}, {
|
|
955
1044
|
output,
|
|
@@ -991,6 +1080,7 @@ async function promptWorkflowField(promptAdapter, output, { id, message, choices
|
|
|
991
1080
|
id,
|
|
992
1081
|
type: "select",
|
|
993
1082
|
message,
|
|
1083
|
+
help: "Workflow context is configured profile metadata. Choose the closest stable repository practice; it helps report interpretation but is not observed GitHub evidence.",
|
|
994
1084
|
choices: workflowChoices(choices),
|
|
995
1085
|
defaultValue,
|
|
996
1086
|
}, {
|
|
@@ -1030,6 +1120,7 @@ async function promptWorkflowProfileUpdate(promptAdapter, output, profile, { isN
|
|
|
1030
1120
|
id: "releasePrTitleIncludes",
|
|
1031
1121
|
type: "text",
|
|
1032
1122
|
message: `Release PR title includes (blank to skip PR class rule; suggested: ${suggestedReleaseTitle})`,
|
|
1123
|
+
help: "Use this only when release PR titles follow a stable phrase. Blank skips the generated release PR class rule.",
|
|
1033
1124
|
}, {
|
|
1034
1125
|
output,
|
|
1035
1126
|
normalize: normalizeTextAnswer,
|
|
@@ -1044,6 +1135,7 @@ async function promptWorkflowProfileUpdate(promptAdapter, output, profile, { isN
|
|
|
1044
1135
|
id: "updateReleasePrClass",
|
|
1045
1136
|
type: "confirm",
|
|
1046
1137
|
message: "Update existing title-based release PR class rule",
|
|
1138
|
+
help: "Updates the existing title-based release PR class rule in the repository profile. Existing unrelated profile rules are kept.",
|
|
1047
1139
|
defaultValue: false,
|
|
1048
1140
|
}, {
|
|
1049
1141
|
output,
|
|
@@ -1065,6 +1157,7 @@ async function promptWorkflowProfileUpdate(promptAdapter, output, profile, { isN
|
|
|
1065
1157
|
id: "addReleasePrClass",
|
|
1066
1158
|
type: "confirm",
|
|
1067
1159
|
message: "Add release PR class rule from title convention",
|
|
1160
|
+
help: "Adds a title-based release PR class rule to the repository profile when that convention matches this repository.",
|
|
1068
1161
|
defaultValue: true,
|
|
1069
1162
|
}, {
|
|
1070
1163
|
output,
|
|
@@ -1097,6 +1190,7 @@ async function maybeConfigureInteractiveProfile(promptAdapter, output, profileSt
|
|
|
1097
1190
|
id: "createProfile",
|
|
1098
1191
|
type: "confirm",
|
|
1099
1192
|
message: `Create repository profile at this path. ${STARTER_PROFILE_PROMPT_COPY}`,
|
|
1193
|
+
help: "A repository profile is required for live GitHub analysis. Interactive setup can create a starter profile at the path you entered, then you can review or refine it before a full run.",
|
|
1100
1194
|
defaultValue: true,
|
|
1101
1195
|
}, {
|
|
1102
1196
|
output,
|
|
@@ -1111,6 +1205,7 @@ async function maybeConfigureInteractiveProfile(promptAdapter, output, profileSt
|
|
|
1111
1205
|
id: "configureWorkflow",
|
|
1112
1206
|
type: "confirm",
|
|
1113
1207
|
message: "Configure repository workflow profile fields",
|
|
1208
|
+
help: "Workflow profile fields are configured context for report interpretation. Choose yes to review merge, release, and branch strategy prompts; choose no to keep the existing profile values.",
|
|
1114
1209
|
defaultValue: false,
|
|
1115
1210
|
}, {
|
|
1116
1211
|
output,
|
|
@@ -1220,6 +1315,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1220
1315
|
id: "repository",
|
|
1221
1316
|
type: "text",
|
|
1222
1317
|
message: "Target GitHub repository",
|
|
1318
|
+
help: "Enter the live GitHub repository as owner/name. Sample mode is not part of interactive setup; use --source sample --out <directory> for the bundled tutorial.",
|
|
1223
1319
|
}, {
|
|
1224
1320
|
output,
|
|
1225
1321
|
normalize: normalizeTextAnswer,
|
|
@@ -1232,6 +1328,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1232
1328
|
id: "limit",
|
|
1233
1329
|
type: "integer",
|
|
1234
1330
|
message: "Latest merged pull request count",
|
|
1331
|
+
help: "Choose how many recent merged pull requests to collect from live GitHub. Smaller limits are faster; larger limits give reports more evidence.",
|
|
1235
1332
|
defaultValue: 30,
|
|
1236
1333
|
}, {
|
|
1237
1334
|
output,
|
|
@@ -1245,6 +1342,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1245
1342
|
id: "profilePath",
|
|
1246
1343
|
type: "path",
|
|
1247
1344
|
message: "Repository profile path",
|
|
1345
|
+
help: "Enter a local repository-profile.v1 JSON path. If the path does not exist, interactive setup can create a starter profile there.",
|
|
1248
1346
|
});
|
|
1249
1347
|
profileState = prompted;
|
|
1250
1348
|
} else {
|
|
@@ -1284,6 +1382,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1284
1382
|
id: "outDir",
|
|
1285
1383
|
type: "path",
|
|
1286
1384
|
message: "Output directory",
|
|
1385
|
+
help: "Choose where generated artifacts or dry-run probe files should be written. Interactive setup may create the directory and check that it is writable.",
|
|
1287
1386
|
defaultValue: defaultOutDirForRepository(resolved.repository),
|
|
1288
1387
|
}, {
|
|
1289
1388
|
output,
|
|
@@ -1299,7 +1398,8 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1299
1398
|
resolved.dryRun = await askUntilValid(adapter, {
|
|
1300
1399
|
id: "dryRun",
|
|
1301
1400
|
type: "confirm",
|
|
1302
|
-
message: "Run metadata-only
|
|
1401
|
+
message: "Run live GitHub metadata-only coverage probe",
|
|
1402
|
+
help: "A dry run is a live GitHub coverage probe. It validates access, profile JSON, output writability, and sampled API coverage without writing report artifacts.",
|
|
1303
1403
|
defaultValue: false,
|
|
1304
1404
|
}, {
|
|
1305
1405
|
output,
|
|
@@ -1314,6 +1414,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1314
1414
|
id: "csv",
|
|
1315
1415
|
type: "confirm",
|
|
1316
1416
|
message: "Write CSV evidence files",
|
|
1417
|
+
help: "CSV evidence files are optional spreadsheet-friendly artifacts for full report runs. They are not written during dry-run coverage probes.",
|
|
1317
1418
|
defaultValue: true,
|
|
1318
1419
|
}, {
|
|
1319
1420
|
output,
|
|
@@ -1328,6 +1429,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1328
1429
|
id: "json",
|
|
1329
1430
|
type: "confirm",
|
|
1330
1431
|
message: "Print completion as JSON",
|
|
1432
|
+
help: "JSON completion writes the final machine-readable receipt to stdout. Prompts and progress stay on stderr so automation can parse stdout.",
|
|
1331
1433
|
defaultValue: false,
|
|
1332
1434
|
}, {
|
|
1333
1435
|
output,
|
|
@@ -1344,6 +1446,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1344
1446
|
id: "excludedPrClasses",
|
|
1345
1447
|
type: "multi-select",
|
|
1346
1448
|
message: "Exclude PR classes (comma-separated, blank for none)",
|
|
1449
|
+
help: "Optionally exclude configured PR classes from downstream normalized data, metrics, reports, methodology, and CSV artifacts. The source bundle still preserves the full collected sample.",
|
|
1347
1450
|
choices: availablePrClasses,
|
|
1348
1451
|
defaultValue: [],
|
|
1349
1452
|
}, {
|
|
@@ -1362,6 +1465,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1362
1465
|
id: "saveRunPreset",
|
|
1363
1466
|
type: "confirm",
|
|
1364
1467
|
message: "Save local run preset for non-interactive reruns",
|
|
1468
|
+
help: "Run presets store reusable live GitHub run settings such as repo, profile, limit, output, dry-run preference, JSON/CSV preference, and requested PR class exclusions. Sample mode does not save or load presets.",
|
|
1365
1469
|
defaultValue: false,
|
|
1366
1470
|
}, {
|
|
1367
1471
|
output,
|
|
@@ -1373,6 +1477,7 @@ export async function collectInteractiveAnalyzeGithubOptions(options, {
|
|
|
1373
1477
|
id: "runPresetPath",
|
|
1374
1478
|
type: "path",
|
|
1375
1479
|
message: "Run preset path",
|
|
1480
|
+
help: "Choose a local JSON file path for reusable live GitHub run settings. The path must be a regular file path, not a directory or symlink.",
|
|
1376
1481
|
}, {
|
|
1377
1482
|
output,
|
|
1378
1483
|
normalize: normalizeTextAnswer,
|
|
@@ -1938,7 +2043,7 @@ export async function runAnalyzeGithubCli(argv, {
|
|
|
1938
2043
|
try {
|
|
1939
2044
|
const parsedOptions = parseAnalyzeGithubArgs(argv);
|
|
1940
2045
|
if (parsedOptions.help) {
|
|
1941
|
-
stdout.write(
|
|
2046
|
+
stdout.write(usageForOptions(parsedOptions));
|
|
1942
2047
|
return null;
|
|
1943
2048
|
}
|
|
1944
2049
|
if (parsedOptions.source !== undefined) {
|