@deskwork/cli 0.9.5

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 (85) hide show
  1. package/dist/cli.d.ts +19 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +98 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/add.d.ts +13 -0
  6. package/dist/commands/add.d.ts.map +1 -0
  7. package/dist/commands/add.js +91 -0
  8. package/dist/commands/add.js.map +1 -0
  9. package/dist/commands/approve.d.ts +18 -0
  10. package/dist/commands/approve.d.ts.map +1 -0
  11. package/dist/commands/approve.js +179 -0
  12. package/dist/commands/approve.js.map +1 -0
  13. package/dist/commands/customize.d.ts +47 -0
  14. package/dist/commands/customize.d.ts.map +1 -0
  15. package/dist/commands/customize.js +176 -0
  16. package/dist/commands/customize.js.map +1 -0
  17. package/dist/commands/distribute.d.ts +30 -0
  18. package/dist/commands/distribute.d.ts.map +1 -0
  19. package/dist/commands/distribute.js +148 -0
  20. package/dist/commands/distribute.js.map +1 -0
  21. package/dist/commands/doctor.d.ts +35 -0
  22. package/dist/commands/doctor.d.ts.map +1 -0
  23. package/dist/commands/doctor.js +354 -0
  24. package/dist/commands/doctor.js.map +1 -0
  25. package/dist/commands/draft.d.ts +17 -0
  26. package/dist/commands/draft.d.ts.map +1 -0
  27. package/dist/commands/draft.js +77 -0
  28. package/dist/commands/draft.js.map +1 -0
  29. package/dist/commands/ingest.d.ts +43 -0
  30. package/dist/commands/ingest.d.ts.map +1 -0
  31. package/dist/commands/ingest.js +321 -0
  32. package/dist/commands/ingest.js.map +1 -0
  33. package/dist/commands/install-preflight.d.ts +83 -0
  34. package/dist/commands/install-preflight.d.ts.map +1 -0
  35. package/dist/commands/install-preflight.js +300 -0
  36. package/dist/commands/install-preflight.js.map +1 -0
  37. package/dist/commands/install.d.ts +27 -0
  38. package/dist/commands/install.d.ts.map +1 -0
  39. package/dist/commands/install.js +132 -0
  40. package/dist/commands/install.js.map +1 -0
  41. package/dist/commands/iterate.d.ts +33 -0
  42. package/dist/commands/iterate.d.ts.map +1 -0
  43. package/dist/commands/iterate.js +202 -0
  44. package/dist/commands/iterate.js.map +1 -0
  45. package/dist/commands/outline.d.ts +19 -0
  46. package/dist/commands/outline.d.ts.map +1 -0
  47. package/dist/commands/outline.js +102 -0
  48. package/dist/commands/outline.js.map +1 -0
  49. package/dist/commands/pause.d.ts +15 -0
  50. package/dist/commands/pause.d.ts.map +1 -0
  51. package/dist/commands/pause.js +70 -0
  52. package/dist/commands/pause.js.map +1 -0
  53. package/dist/commands/plan.d.ts +12 -0
  54. package/dist/commands/plan.d.ts.map +1 -0
  55. package/dist/commands/plan.js +74 -0
  56. package/dist/commands/plan.js.map +1 -0
  57. package/dist/commands/publish.d.ts +18 -0
  58. package/dist/commands/publish.d.ts.map +1 -0
  59. package/dist/commands/publish.js +105 -0
  60. package/dist/commands/publish.js.map +1 -0
  61. package/dist/commands/resume.d.ts +16 -0
  62. package/dist/commands/resume.d.ts.map +1 -0
  63. package/dist/commands/resume.js +70 -0
  64. package/dist/commands/resume.js.map +1 -0
  65. package/dist/commands/review-cancel.d.ts +15 -0
  66. package/dist/commands/review-cancel.d.ts.map +1 -0
  67. package/dist/commands/review-cancel.js +88 -0
  68. package/dist/commands/review-cancel.js.map +1 -0
  69. package/dist/commands/review-help.d.ts +12 -0
  70. package/dist/commands/review-help.d.ts.map +1 -0
  71. package/dist/commands/review-help.js +52 -0
  72. package/dist/commands/review-help.js.map +1 -0
  73. package/dist/commands/review-report.d.ts +13 -0
  74. package/dist/commands/review-report.d.ts.map +1 -0
  75. package/dist/commands/review-report.js +53 -0
  76. package/dist/commands/review-report.js.map +1 -0
  77. package/dist/commands/review-start.d.ts +17 -0
  78. package/dist/commands/review-start.d.ts.map +1 -0
  79. package/dist/commands/review-start.js +121 -0
  80. package/dist/commands/review-start.js.map +1 -0
  81. package/dist/commands/shortform-start.d.ts +33 -0
  82. package/dist/commands/shortform-start.d.ts.map +1 -0
  83. package/dist/commands/shortform-start.js +127 -0
  84. package/dist/commands/shortform-start.js.map +1 -0
  85. package/package.json +45 -0
@@ -0,0 +1,176 @@
1
+ /**
2
+ * deskwork customize — copy a plugin-default file into the project's
3
+ * `.deskwork/<category>/<name>.ts` so the operator can edit it.
4
+ *
5
+ * Phase 23f. Categories:
6
+ * - templates → copies `packages/studio/src/pages/<name>.ts`
7
+ * - doctor → copies `packages/core/src/doctor/rules/<name>.ts`
8
+ * - prompts → reserved (no default-source mapping yet)
9
+ *
10
+ * Usage (after the dispatcher injects projectRoot):
11
+ * deskwork customize <project-root> <category> <name>
12
+ *
13
+ * The command:
14
+ * 1. Resolves the plugin-default source file via `import.meta.resolve`
15
+ * against the published package paths so it works in both
16
+ * workspace dev and marketplace install.
17
+ * 2. Copies the source verbatim into
18
+ * `<projectRoot>/.deskwork/<category>/<name>.ts`, creating the
19
+ * directory tree as needed.
20
+ * 3. Refuses if the destination file already exists — clobbering an
21
+ * operator's edits would be a bug-factory.
22
+ * 4. Prints the destination path so the operator can edit.
23
+ *
24
+ * Errors:
25
+ * - Unknown category → exit 2 with the list of valid categories.
26
+ * - `prompts` for now → exit 2 with a "reserved for future use" note.
27
+ * - Plugin-default not found → exit 1 with the list of names that DO
28
+ * have defaults (best-effort).
29
+ * - Destination file already exists → exit 1, refuse to overwrite.
30
+ */
31
+ import { copyFileSync, existsSync, mkdirSync, readdirSync, } from 'node:fs';
32
+ import { dirname, isAbsolute, join, resolve } from 'node:path';
33
+ import { fileURLToPath } from 'node:url';
34
+ import { fail } from '@deskwork/core/cli-args';
35
+ const VALID_CATEGORIES = ['templates', 'prompts', 'doctor'];
36
+ function isCategory(value) {
37
+ return VALID_CATEGORIES.includes(value);
38
+ }
39
+ /**
40
+ * Resolve a node module path via `import.meta.resolve`. Returns the
41
+ * absolute file path the package's exports map points at, regardless
42
+ * of whether we're running from the workspace tree or from a
43
+ * marketplace-installed copy.
44
+ *
45
+ * Throws when the package can't be resolved at all (CLI installed in a
46
+ * broken state). The caller surfaces the error to the operator.
47
+ */
48
+ function resolvePackageFile(specifier) {
49
+ try {
50
+ const url = import.meta.resolve(specifier);
51
+ return fileURLToPath(url);
52
+ }
53
+ catch (err) {
54
+ const reason = err instanceof Error ? err.message : String(err);
55
+ throw new Error(`cannot resolve ${specifier} (broken install?): ${reason}`);
56
+ }
57
+ }
58
+ /**
59
+ * Resolve a package's root directory by anchoring on its `package.json`
60
+ * subpath export. Both `@deskwork/core` and `@deskwork/studio` expose
61
+ * `./package.json` implicitly through Node's package-exports machinery
62
+ * (or via a dedicated entry — see each package's exports map).
63
+ *
64
+ * Returns the absolute directory containing the package.json. From there,
65
+ * the customize anchor walks into `src/<...>` for the requested file.
66
+ */
67
+ function resolvePackageRoot(packageName) {
68
+ const pkgJsonPath = resolvePackageFile(`${packageName}/package.json`);
69
+ return dirname(pkgJsonPath);
70
+ }
71
+ /**
72
+ * Find the source-of-truth file for a customize request. Returns an
73
+ * absolute path or throws. The mapping per category:
74
+ *
75
+ * templates → @deskwork/studio package root, then src/pages/<name>.ts.
76
+ * doctor → @deskwork/core package root, then src/doctor/rules/<name>.ts.
77
+ * prompts → throws (reserved).
78
+ *
79
+ * Note: this assumes the published package ships its `src/` tree.
80
+ * Phase 26b's `files: ["dist", ...]` whitelist drops `src/`, so the
81
+ * customize command currently works only against workspace-symlinked
82
+ * packages (the dev path). A follow-up issue tracks shipping the
83
+ * customize sources alongside dist or vendoring template snapshots.
84
+ */
85
+ function resolveDefaultSource(category, name) {
86
+ if (category === 'prompts') {
87
+ throw new Error('category "prompts" is reserved for future use — no default sources to copy yet');
88
+ }
89
+ if (category === 'templates') {
90
+ const studioRoot = resolvePackageRoot('@deskwork/studio');
91
+ const candidate = resolve(studioRoot, 'src', 'pages', `${name}.ts`);
92
+ if (!existsSync(candidate)) {
93
+ throw new Error(`no built-in template named "${name}". Available templates: ${listAvailable(dirname(candidate))}`);
94
+ }
95
+ return candidate;
96
+ }
97
+ // doctor
98
+ const coreRoot = resolvePackageRoot('@deskwork/core');
99
+ const candidate = resolve(coreRoot, 'src', 'doctor', 'rules', `${name}.ts`);
100
+ if (!existsSync(candidate)) {
101
+ throw new Error(`no built-in doctor rule named "${name}". Available rules: ${listAvailable(dirname(candidate))}`);
102
+ }
103
+ return candidate;
104
+ }
105
+ /**
106
+ * Best-effort listing of the available basenames in a directory. Used
107
+ * to enrich error messages when the operator passes a name that
108
+ * doesn't match a built-in default.
109
+ */
110
+ function listAvailable(dir) {
111
+ if (!existsSync(dir))
112
+ return '(none — broken install)';
113
+ const entries = readdirSync(dir)
114
+ .filter((n) => n.endsWith('.ts'))
115
+ .map((n) => n.slice(0, -'.ts'.length))
116
+ .sort();
117
+ return entries.join(', ');
118
+ }
119
+ /**
120
+ * Add `@deskwork/studio/server.ts` resolution support. The studio
121
+ * package's `package.json` lists `bin: { "deskwork-studio": "./src/server.ts" }`
122
+ * but no top-level `exports.server.ts`. We work around that by
123
+ * resolving the package root through `package.json#main` if available;
124
+ * here we cheat and use the studio's own `import.meta` from the
125
+ * compiled bundle. To keep this implementation simple, we resolve via
126
+ * the studio package's `package.json` root and then join the source
127
+ * tree path.
128
+ *
129
+ * (This doc-comment reserves the explanation; the actual logic above
130
+ * uses `@deskwork/studio/server.ts`. Studio's package.json must list
131
+ * an exports entry for that subpath. If it doesn't yet, resolveDefaultSource
132
+ * will throw a clear error and the test will catch the omission.)
133
+ */
134
+ export async function run(argv) {
135
+ // Argv shape after dispatcher inject:
136
+ // [<project-root>, <category>, <name>]
137
+ if (argv.length !== 3) {
138
+ fail('Usage: deskwork customize <project-root> <category> <name>\n' +
139
+ ` category: ${VALID_CATEGORIES.join(' | ')}`, 2);
140
+ }
141
+ const [projectRootArg, categoryArg, name] = argv;
142
+ if (!isCategory(categoryArg)) {
143
+ fail(`unknown category "${categoryArg}". Valid: ${VALID_CATEGORIES.join(', ')}`, 2);
144
+ }
145
+ if (!name || name.includes('/') || name.includes('\\') || name.startsWith('.')) {
146
+ fail(`name "${name}" must be a plain basename (no slashes, no leading dots)`, 2);
147
+ }
148
+ const projectRoot = isAbsolute(projectRootArg)
149
+ ? projectRootArg
150
+ : resolve(process.cwd(), projectRootArg);
151
+ if (!existsSync(projectRoot)) {
152
+ fail(`project root does not exist: ${projectRoot}`, 1);
153
+ }
154
+ let source;
155
+ try {
156
+ source = resolveDefaultSource(categoryArg, name);
157
+ }
158
+ catch (err) {
159
+ fail(err instanceof Error ? err.message : String(err), 1);
160
+ }
161
+ const destDir = join(projectRoot, '.deskwork', categoryArg);
162
+ const destFile = join(destDir, `${name}.ts`);
163
+ if (existsSync(destFile)) {
164
+ fail(`destination already exists: ${destFile}\n` +
165
+ ' Refusing to overwrite operator-edited overrides.\n' +
166
+ ' Move or delete the existing file before re-running.', 1);
167
+ }
168
+ mkdirSync(destDir, { recursive: true });
169
+ copyFileSync(source, destFile);
170
+ process.stdout.write(`Customized ${categoryArg}/${name}\n`);
171
+ process.stdout.write(` source: ${source}\n`);
172
+ process.stdout.write(` dest: ${destFile}\n`);
173
+ process.stdout.write(' Edit the destination file to customize behavior. The studio\n');
174
+ process.stdout.write(' loads the override automatically on the next request.\n');
175
+ }
176
+ //# sourceMappingURL=customize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customize.js","sourceRoot":"","sources":["../../src/commands/customize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * deskwork distribute — record the URL of a posted shortform.
3
+ *
4
+ * Run AFTER the operator has manually posted an approved shortform to
5
+ * the platform. The helper updates the calendar's distribution record
6
+ * with the share URL (and optional date / notes) so the dashboard
7
+ * matrix shows the cell as covered.
8
+ *
9
+ * Match precedence (handled inside `updateDistributionUrl`):
10
+ * - `entryId` (preferred — survives slug renames)
11
+ * - `(slug, platform, channel?)` legacy fallback
12
+ *
13
+ * If no record exists yet for the (slug, platform, channel?) tuple, the
14
+ * helper creates one via `addDistribution`. That call enforces the
15
+ * Published-stage invariant — non-Published entries cannot have
16
+ * distribution records, since deskwork doesn't track shares for posts
17
+ * that haven't shipped yet.
18
+ *
19
+ * Usage:
20
+ * deskwork distribute <project-root> [--site <slug>]
21
+ * --platform <p> [--channel <c>]
22
+ * --url <posted-url>
23
+ * [--date YYYY-MM-DD] [--notes <text>]
24
+ * <slug>
25
+ *
26
+ * Emits a JSON result with the slug, platform, channel (if any), the
27
+ * recorded URL, the resolved dateShared, and notes (if any).
28
+ */
29
+ export declare function run(argv: string[]): Promise<void>;
30
+ //# sourceMappingURL=distribute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distribute.d.ts","sourceRoot":"","sources":["../../src/commands/distribute.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAaH,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6IvD"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * deskwork distribute — record the URL of a posted shortform.
3
+ *
4
+ * Run AFTER the operator has manually posted an approved shortform to
5
+ * the platform. The helper updates the calendar's distribution record
6
+ * with the share URL (and optional date / notes) so the dashboard
7
+ * matrix shows the cell as covered.
8
+ *
9
+ * Match precedence (handled inside `updateDistributionUrl`):
10
+ * - `entryId` (preferred — survives slug renames)
11
+ * - `(slug, platform, channel?)` legacy fallback
12
+ *
13
+ * If no record exists yet for the (slug, platform, channel?) tuple, the
14
+ * helper creates one via `addDistribution`. That call enforces the
15
+ * Published-stage invariant — non-Published entries cannot have
16
+ * distribution records, since deskwork doesn't track shares for posts
17
+ * that haven't shipped yet.
18
+ *
19
+ * Usage:
20
+ * deskwork distribute <project-root> [--site <slug>]
21
+ * --platform <p> [--channel <c>]
22
+ * --url <posted-url>
23
+ * [--date YYYY-MM-DD] [--notes <text>]
24
+ * <slug>
25
+ *
26
+ * Emits a JSON result with the slug, platform, channel (if any), the
27
+ * recorded URL, the resolved dateShared, and notes (if any).
28
+ */
29
+ import { readConfig } from '@deskwork/core/config';
30
+ import { readCalendar, writeCalendar } from '@deskwork/core/calendar';
31
+ import { findEntry, findEntryById, updateDistributionUrl, } from '@deskwork/core/calendar-mutations';
32
+ import { resolveSite, resolveCalendarPath } from '@deskwork/core/paths';
33
+ import { isPlatform, PLATFORMS } from '@deskwork/core/types';
34
+ import { absolutize, emit, fail, parseArgs } from '@deskwork/core/cli-args';
35
+ export async function run(argv) {
36
+ const KNOWN_FLAGS = [
37
+ 'site',
38
+ 'platform',
39
+ 'channel',
40
+ 'url',
41
+ 'date',
42
+ 'notes',
43
+ ];
44
+ const SLUG_RE = /^[a-z0-9][a-z0-9-]*(\/[a-z0-9][a-z0-9-]*)*$/;
45
+ const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
46
+ const { positional, flags } = parse();
47
+ if (positional.length < 2) {
48
+ fail('Usage: deskwork distribute <project-root> [--site <slug>] ' +
49
+ '--platform <p> [--channel <c>] --url <posted-url> ' +
50
+ '[--date YYYY-MM-DD] [--notes <text>] <slug>', 2);
51
+ }
52
+ const [rootArg, slug] = positional;
53
+ const projectRoot = absolutize(rootArg);
54
+ if (!SLUG_RE.test(slug)) {
55
+ fail(`invalid slug: ${slug} (must match ${SLUG_RE})`);
56
+ }
57
+ const platform = flags.platform;
58
+ if (platform === undefined) {
59
+ fail(`--platform is required. Must be one of: ${PLATFORMS.join(', ')}.`, 2);
60
+ }
61
+ if (!isPlatform(platform)) {
62
+ fail(`Invalid --platform "${platform}". Must be one of: ${PLATFORMS.join(', ')}.`);
63
+ }
64
+ const url = flags.url;
65
+ if (url === undefined || url === '') {
66
+ fail('--url is required (the URL of the posted share).', 2);
67
+ }
68
+ if (flags.date !== undefined && !DATE_RE.test(flags.date)) {
69
+ fail(`Invalid --date "${flags.date}". Must match YYYY-MM-DD.`);
70
+ }
71
+ const channel = flags.channel;
72
+ const dateShared = flags.date;
73
+ const notes = flags.notes;
74
+ let config;
75
+ try {
76
+ config = readConfig(projectRoot);
77
+ }
78
+ catch (err) {
79
+ fail(err instanceof Error ? err.message : String(err));
80
+ }
81
+ let site;
82
+ try {
83
+ site = resolveSite(config, flags.site);
84
+ }
85
+ catch (err) {
86
+ fail(err instanceof Error ? err.message : String(err));
87
+ }
88
+ const calendarPath = resolveCalendarPath(projectRoot, config, site);
89
+ const calendar = readCalendar(calendarPath);
90
+ // Resolve entryId from the calendar so the distribution record carries
91
+ // the stable identity. Survives slug renames downstream.
92
+ const entry = findEntryById(calendar, slug) ?? findEntry(calendar, slug);
93
+ if (!entry) {
94
+ const slugs = calendar.entries.map((e) => e.slug).join(', ') || '(none)';
95
+ fail(`No calendar entry with slug "${slug}" on site "${site}". ` +
96
+ `Known slugs: ${slugs}.`);
97
+ }
98
+ // Pre-flight the Published-stage invariant. The mutation throws the same
99
+ // way via `addDistribution` when no prior record exists, but we surface
100
+ // a clearer, action-oriented error here before mutating.
101
+ const hasPriorRecord = calendar.distributions.some((d) => {
102
+ if (d.platform !== platform)
103
+ return false;
104
+ const channelMatches = channel === undefined ? !d.channel : (d.channel?.toLowerCase() ?? '') === channel.toLowerCase();
105
+ if (!channelMatches)
106
+ return false;
107
+ if (entry.id !== undefined && d.entryId === entry.id)
108
+ return true;
109
+ return d.slug === entry.slug;
110
+ });
111
+ if (!hasPriorRecord && entry.stage !== 'Published') {
112
+ fail(`Cannot record distribution for non-Published entry "${entry.slug}" ` +
113
+ `(current stage: ${entry.stage}). Run /deskwork:publish ${entry.slug} first.`);
114
+ }
115
+ let record;
116
+ try {
117
+ record = updateDistributionUrl(calendar, {
118
+ ...(entry.id !== undefined ? { entryId: entry.id } : {}),
119
+ slug: entry.slug,
120
+ platform,
121
+ ...(channel !== undefined ? { channel } : {}),
122
+ }, url, dateShared, notes);
123
+ }
124
+ catch (err) {
125
+ fail(err instanceof Error ? err.message : String(err));
126
+ }
127
+ writeCalendar(calendarPath, calendar);
128
+ emit({
129
+ slug: record.slug,
130
+ ...(record.entryId !== undefined ? { entryId: record.entryId } : {}),
131
+ platform: record.platform,
132
+ ...(record.channel !== undefined ? { channel: record.channel } : {}),
133
+ url: record.url,
134
+ dateShared: record.dateShared,
135
+ ...(record.notes !== undefined ? { notes: record.notes } : {}),
136
+ site,
137
+ calendarPath,
138
+ });
139
+ function parse() {
140
+ try {
141
+ return parseArgs(argv, KNOWN_FLAGS);
142
+ }
143
+ catch (err) {
144
+ fail(err instanceof Error ? err.message : String(err), 2);
145
+ }
146
+ }
147
+ }
148
+ //# sourceMappingURL=distribute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distribute.js","sourceRoot":"","sources":["../../src/commands/distribute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * deskwork doctor — validate and (optionally) repair binding metadata
3
+ * across the calendar + content tree + workflow store.
4
+ *
5
+ * Default mode is audit-only: walk the rules, report findings, exit 0
6
+ * on a clean tree or 1 if anything was reported. `--fix=<rule>` (or
7
+ * `--fix=all`) engages repair mode; `--yes` makes repairs non-
8
+ * interactive (skipping ambiguous cases). `--json` produces machine-
9
+ * readable output that composes with `jq`.
10
+ *
11
+ * Argv shape (after the dispatcher injects projectRoot when needed):
12
+ *
13
+ * <project-root> [flags]
14
+ *
15
+ * Flags:
16
+ * --site <slug> Restrict to one site; default = every site.
17
+ * --fix <rule|all> Engage repair mode for the named rule(s).
18
+ * --yes Non-interactive repair (skip ambiguous).
19
+ * --json Emit JSON instead of human-readable text.
20
+ *
21
+ * Exit codes (Issue #44, Phase 22):
22
+ * 0 Audit clean. OR --fix succeeded for every applicable finding.
23
+ * "Applicable" here means: anything that wasn't skipped because
24
+ * a prerequisite outside doctor's scope hasn't happened yet (e.g.
25
+ * the body file hasn't been scaffolded, so missing-frontmatter-id
26
+ * can't bind).
27
+ * 1 Findings present (audit-only mode). OR --fix encountered real
28
+ * follow-ups: ambiguous cases requiring interactive resolution,
29
+ * schema rejections needing the operator to patch the host
30
+ * schema, editorial decisions, operator declines, or hard
31
+ * apply-failures.
32
+ * 2 Usage / config error.
33
+ */
34
+ export declare function run(argv: string[]): Promise<void>;
35
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAuBH,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4FvD"}