@oevery/rsp 4.0.0 → 4.1.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/dist/chunk-JO6NDJM4.mjs +360 -0
- package/dist/chunk-LGDCIQYL.mjs +725 -0
- package/dist/chunk-P3KO3GZW.mjs +1023 -0
- package/dist/chunk-U56XMIOO.mjs +66 -0
- package/dist/{chunk-HFSTLCCK.mjs → chunk-VDRXFKBP.mjs} +133 -1800
- package/dist/cli.mjs +275 -290
- package/dist/client-EHRWH5Q7.mjs +108 -0
- package/dist/{entry-RIJQ2X46.mjs → entry-NDASTAI5.mjs} +13 -9
- package/dist/viewer/NOTICE.txt +299 -0
- package/dist/viewer/app.css +2 -0
- package/dist/viewer/app.js +670 -0
- package/dist/viewer-build.json +1 -0
- package/dist/viewer-service.mjs +551 -0
- package/package.json +21 -3
- package/skills/rsp/SKILL.md +7 -6
- package/skills/rsp/references/architecture.md +39 -0
- package/skills/rsp/references/durable-review.md +2 -2
- package/skills/rsp/references/focus-continuation.md +6 -2
- package/skills/rsp/references/setup-repair.md +11 -6
- package/skills/rsp/references/work-model.md +12 -2
- package/skills/rsp-doc/SKILL.md +13 -10
- package/skills/rsp-doc/references/skill-authoring.md +2 -2
- package/skills/rsp-implement/SKILL.md +15 -11
- package/skills/rsp-review/SKILL.md +8 -8
- package/skills/rsp-review/references/code-review.md +11 -5
- package/skills/rsp-review/references/document-review.md +7 -9
- package/skills/rsp-shape/SKILL.md +3 -1
- package/skills/rsp-shape/references/planning.md +3 -3
- package/skills/rsp-verify/SKILL.md +8 -13
- package/skills/rsp-doc/references/artifact-lenses.md +0 -43
- package/skills/rsp-review/references/structural-review.md +0 -41
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
readCurrentDocument
|
|
4
|
+
} from "./chunk-LGDCIQYL.mjs";
|
|
5
|
+
import {
|
|
6
|
+
PKG_ROOT,
|
|
7
|
+
RSP_DIR,
|
|
8
|
+
getVersion,
|
|
9
|
+
inspectManagedDirectory,
|
|
10
|
+
inspectManagedFile,
|
|
11
|
+
inspectRspConfig,
|
|
12
|
+
markdownText,
|
|
13
|
+
parseMarkdown,
|
|
14
|
+
walkMarkdown
|
|
15
|
+
} from "./chunk-P3KO3GZW.mjs";
|
|
16
|
+
|
|
17
|
+
// src/architecture/model.ts
|
|
18
|
+
import { createHash } from "crypto";
|
|
19
|
+
import { realpath } from "fs/promises";
|
|
20
|
+
import { isAbsolute, relative, resolve } from "path";
|
|
21
|
+
|
|
22
|
+
// src/architecture/selection.ts
|
|
23
|
+
function selectArchitecture(model, selection) {
|
|
24
|
+
const selected = new Set(model.nodes.map((node) => node.id));
|
|
25
|
+
if (selection.kind === "focus") {
|
|
26
|
+
if (!selected.has(selection.id))
|
|
27
|
+
throw new Error(`Unknown architecture node: ${selection.id}`);
|
|
28
|
+
selected.clear();
|
|
29
|
+
selected.add(selection.id);
|
|
30
|
+
}
|
|
31
|
+
if (selection.kind === "node") {
|
|
32
|
+
if (!selected.has(selection.id))
|
|
33
|
+
throw new Error(`Unknown architecture node: ${selection.id}`);
|
|
34
|
+
selected.clear();
|
|
35
|
+
selected.add(selection.id);
|
|
36
|
+
let added = true;
|
|
37
|
+
while (added) {
|
|
38
|
+
added = false;
|
|
39
|
+
for (const node of model.nodes) {
|
|
40
|
+
if (node.parent && selected.has(node.parent) && !selected.has(node.id)) {
|
|
41
|
+
selected.add(node.id);
|
|
42
|
+
added = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (selection.kind === "view") {
|
|
48
|
+
const view = model.views.find((view2) => view2.id === selection.id);
|
|
49
|
+
if (!view)
|
|
50
|
+
throw new Error(`Unknown architecture view: ${selection.id}`);
|
|
51
|
+
selected.clear();
|
|
52
|
+
view.include.forEach((id) => selected.add(id));
|
|
53
|
+
}
|
|
54
|
+
const relations = model.relations.filter((edge) => selected.has(edge.source) || selected.has(edge.target));
|
|
55
|
+
const visible = /* @__PURE__ */ new Set([...selected, ...relations.flatMap((edge) => [edge.source, edge.target])]);
|
|
56
|
+
return { selected, visible, relations };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/architecture/model.ts
|
|
60
|
+
var ARCHITECTURE_FILE = ".rsp/architecture.json";
|
|
61
|
+
var MAX_CONTENT_BYTES = 16 * 1024 * 1024;
|
|
62
|
+
var digest = (value) => createHash("sha256").update(value).digest("hex");
|
|
63
|
+
function projectPath(file) {
|
|
64
|
+
if (!file || isAbsolute(file) || file.includes("\\") || file.split("/").some((part) => !part || part === "." || part === "..") || file.includes("\0"))
|
|
65
|
+
throw new Error(`Unsafe project-relative path: ${file}`);
|
|
66
|
+
if (file.split("/").some((part) => part === ".git" || part === "node_modules"))
|
|
67
|
+
throw new Error(`Private/runtime path is not readable: ${file}`);
|
|
68
|
+
return file;
|
|
69
|
+
}
|
|
70
|
+
async function readProjectFile(root, file) {
|
|
71
|
+
projectPath(file);
|
|
72
|
+
return (await readCurrentDocument(resolve(root, file), root, file, MAX_CONTENT_BYTES)).content;
|
|
73
|
+
}
|
|
74
|
+
function object(value) {
|
|
75
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
76
|
+
throw new Error("Architecture entries must be objects");
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
function text(value, field) {
|
|
80
|
+
if (typeof value !== "string" || !value.trim())
|
|
81
|
+
throw new Error(`Architecture ${field} must be a non-empty string`);
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
function strings(value, field) {
|
|
85
|
+
if (!Array.isArray(value))
|
|
86
|
+
throw new Error(`Architecture ${field} must be an array`);
|
|
87
|
+
return value.map((item) => text(item, field));
|
|
88
|
+
}
|
|
89
|
+
function collection(value, field) {
|
|
90
|
+
if (!Array.isArray(value))
|
|
91
|
+
throw new Error(`Architecture ${field} must be an array`);
|
|
92
|
+
return value.map(object);
|
|
93
|
+
}
|
|
94
|
+
function unique(items, field) {
|
|
95
|
+
if (new Set(items.map((item) => item.id)).size !== items.length)
|
|
96
|
+
throw new Error(`Duplicate architecture ${field} identity`);
|
|
97
|
+
}
|
|
98
|
+
function parseArchitecture(content) {
|
|
99
|
+
const value = object(JSON.parse(content));
|
|
100
|
+
if (value.schemaVersion !== 1)
|
|
101
|
+
throw new Error(`Unsupported architecture schemaVersion: ${String(value.schemaVersion)}`);
|
|
102
|
+
const nodes = collection(value.nodes, "nodes").map((node) => ({ id: text(node.id, "node.id"), title: text(node.title, "node.title"), description: text(node.description, "node.description"), ...node.parent === void 0 ? {} : { parent: text(node.parent, "node.parent") } }));
|
|
103
|
+
const relations = collection(value.relations, "relations").map((edge) => ({ id: text(edge.id, "relation.id"), source: text(edge.source, "relation.source"), target: text(edge.target, "relation.target"), type: text(edge.type, "relation.type"), description: text(edge.description, "relation.description") }));
|
|
104
|
+
const views = collection(value.views, "views").map((view) => ({ id: text(view.id, "view.id"), title: text(view.title, "view.title"), node: text(view.node, "view.node"), include: strings(view.include, "view.include") }));
|
|
105
|
+
const bindings = collection(value.bindings, "bindings").map((binding) => {
|
|
106
|
+
const file = projectPath(text(binding.file, "binding.file"));
|
|
107
|
+
if (!/\.md$/i.test(file))
|
|
108
|
+
throw new Error("Architecture bindings must reference Markdown files");
|
|
109
|
+
const scope = binding.scope ?? "node";
|
|
110
|
+
if (scope !== "node" && scope !== "subtree")
|
|
111
|
+
throw new Error("Architecture binding.scope must be node or subtree");
|
|
112
|
+
const headings = binding.headings === void 0 ? void 0 : strings(binding.headings, "binding.headings");
|
|
113
|
+
if (headings?.length === 0)
|
|
114
|
+
throw new Error("Omit headings for a whole-file binding");
|
|
115
|
+
return { node: text(binding.node, "binding.node"), file, ...headings ? { headings } : {}, scope };
|
|
116
|
+
});
|
|
117
|
+
unique(nodes, "node");
|
|
118
|
+
unique(relations, "relation");
|
|
119
|
+
unique(views, "view");
|
|
120
|
+
const ids = new Set(nodes.map((node) => node.id));
|
|
121
|
+
const requireNode = (id) => {
|
|
122
|
+
if (!ids.has(id))
|
|
123
|
+
throw new Error(`Missing architecture node: ${id}`);
|
|
124
|
+
};
|
|
125
|
+
for (const node of nodes) {
|
|
126
|
+
const visited = /* @__PURE__ */ new Set([node.id]);
|
|
127
|
+
let parent = node.parent;
|
|
128
|
+
while (parent !== void 0) {
|
|
129
|
+
requireNode(parent);
|
|
130
|
+
if (visited.has(parent))
|
|
131
|
+
throw new Error(`Architecture hierarchy cycle: ${parent}`);
|
|
132
|
+
visited.add(parent);
|
|
133
|
+
parent = nodes.find((node2) => node2.id === parent).parent;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
relations.forEach((edge) => {
|
|
137
|
+
requireNode(edge.source);
|
|
138
|
+
requireNode(edge.target);
|
|
139
|
+
});
|
|
140
|
+
views.forEach((view) => {
|
|
141
|
+
requireNode(view.node);
|
|
142
|
+
view.include.forEach(requireNode);
|
|
143
|
+
});
|
|
144
|
+
bindings.forEach((binding) => requireNode(binding.node));
|
|
145
|
+
return { schemaVersion: 1, nodes, relations, views, bindings };
|
|
146
|
+
}
|
|
147
|
+
function documentHeadings(content) {
|
|
148
|
+
const result = [];
|
|
149
|
+
const stack = [];
|
|
150
|
+
const counts = /* @__PURE__ */ new Map();
|
|
151
|
+
const anchors = /* @__PURE__ */ new Set();
|
|
152
|
+
walkMarkdown(parseMarkdown(content).root, (node) => {
|
|
153
|
+
if (node.type !== "heading")
|
|
154
|
+
return;
|
|
155
|
+
const title = markdownText(node);
|
|
156
|
+
while (stack.length && stack.at(-1).depth >= node.depth) stack.pop();
|
|
157
|
+
stack.push({ title, depth: node.depth });
|
|
158
|
+
const base = title.toLowerCase().replace(/[^\p{L}\p{N}\s_-]/gu, "").replace(/\s/g, "-") || "section";
|
|
159
|
+
let count = counts.get(base) ?? 0;
|
|
160
|
+
let anchor = count ? `${base}-${count}` : base;
|
|
161
|
+
while (anchors.has(anchor)) anchor = `${base}-${++count}`;
|
|
162
|
+
counts.set(base, count + 1);
|
|
163
|
+
anchors.add(anchor);
|
|
164
|
+
result.push({ title, depth: node.depth, anchor, hierarchy: stack.map((item) => item.title) });
|
|
165
|
+
});
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
function resolveHeading(headings, hierarchy) {
|
|
169
|
+
const matches = headings.filter((heading) => hierarchy.length <= heading.hierarchy.length && hierarchy.every((title, i) => title === heading.hierarchy[heading.hierarchy.length - hierarchy.length + i]));
|
|
170
|
+
if (matches.length !== 1)
|
|
171
|
+
throw new Error(`${matches.length ? "Ambiguous" : "Missing"} chapter: ${hierarchy.join(" > ")}`);
|
|
172
|
+
return matches[0];
|
|
173
|
+
}
|
|
174
|
+
async function queryArchitecture(options = {}) {
|
|
175
|
+
if (options.node !== void 0 && !options.node.trim())
|
|
176
|
+
throw new Error("--node requires a non-empty ID");
|
|
177
|
+
if (options.view !== void 0 && !options.view.trim())
|
|
178
|
+
throw new Error("--view requires a non-empty ID");
|
|
179
|
+
if (options.node && options.view)
|
|
180
|
+
throw new Error("--node and --view are mutually exclusive");
|
|
181
|
+
const root = await realpath(resolve(options.root ?? process.cwd()));
|
|
182
|
+
const config = await inspectRspConfig(root);
|
|
183
|
+
if (config.issues.length)
|
|
184
|
+
throw new Error(config.issues.join("; "));
|
|
185
|
+
let content;
|
|
186
|
+
try {
|
|
187
|
+
content = await readProjectFile(root, ARCHITECTURE_FILE);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
const { lstat } = await import("fs/promises");
|
|
190
|
+
try {
|
|
191
|
+
await lstat(resolve(root, ARCHITECTURE_FILE));
|
|
192
|
+
} catch (missing) {
|
|
193
|
+
if (missing.code === "ENOENT")
|
|
194
|
+
return { configured: false, source: { root, file: ARCHITECTURE_FILE, revision: "" }, selection: { kind: "full" }, nodes: [], relations: [], views: [], documents: [], diagnostics: [{ code: "not_configured", message: `Architecture is not configured: ${ARCHITECTURE_FILE}` }] };
|
|
195
|
+
}
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
const model = parseArchitecture(content);
|
|
199
|
+
const selection = options.node ? { kind: "node", id: options.node } : options.view ? { kind: "view", id: options.view } : { kind: "full" };
|
|
200
|
+
const { selected, visible, relations } = selectArchitecture(model, selection);
|
|
201
|
+
const diagnostics = [];
|
|
202
|
+
const chapterMaps = /* @__PURE__ */ new Map();
|
|
203
|
+
const sourceInputs = [content, JSON.stringify(config.config)];
|
|
204
|
+
for (const file of new Set(model.bindings.map((binding) => binding.file))) {
|
|
205
|
+
try {
|
|
206
|
+
const body = await readProjectFile(root, file);
|
|
207
|
+
chapterMaps.set(file, documentHeadings(body));
|
|
208
|
+
sourceInputs.push(file, body);
|
|
209
|
+
} catch (error) {
|
|
210
|
+
diagnostics.push({ code: "document_unavailable", file, message: error.message });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const nodes = model.nodes.filter((node) => visible.has(node.id)).map((node) => {
|
|
214
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
215
|
+
let parent = node.parent;
|
|
216
|
+
while (parent) {
|
|
217
|
+
ancestors.add(parent);
|
|
218
|
+
parent = model.nodes.find((node2) => node2.id === parent)?.parent;
|
|
219
|
+
}
|
|
220
|
+
const bindings = model.bindings.filter((binding) => binding.node === node.id || binding.scope === "subtree" && ancestors.has(binding.node)).map((binding) => {
|
|
221
|
+
const reference = { ...binding, origin: binding.node, inherited: binding.node !== node.id };
|
|
222
|
+
if (!binding.headings || !chapterMaps.has(binding.file))
|
|
223
|
+
return reference;
|
|
224
|
+
try {
|
|
225
|
+
return { ...reference, anchor: resolveHeading(chapterMaps.get(binding.file), binding.headings).anchor };
|
|
226
|
+
} catch (error) {
|
|
227
|
+
diagnostics.push({ code: "chapter_unresolved", file: binding.file, message: error.message });
|
|
228
|
+
return reference;
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
return { ...node, boundary: !selected.has(node.id), bindings };
|
|
232
|
+
});
|
|
233
|
+
return { configured: true, source: { root, file: ARCHITECTURE_FILE, revision: digest(sourceInputs.join("\0")) }, selection, nodes, relations, views: model.views.filter((view) => selection.kind === "full" || view.id === options.view || selected.has(view.node)), documents: [...new Set(nodes.flatMap((node) => node.bindings.map((binding) => binding.file)))], diagnostics };
|
|
234
|
+
}
|
|
235
|
+
function isWithin(root, target) {
|
|
236
|
+
const path = relative(root, target);
|
|
237
|
+
return path !== ".." && !path.startsWith("../") && !isAbsolute(path);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// src/core/project-version.ts
|
|
241
|
+
import { readFile, realpath as realpath2 } from "fs/promises";
|
|
242
|
+
import { join } from "path";
|
|
243
|
+
var PROJECT_VERSION_PATH = ".rsp/version";
|
|
244
|
+
var PROJECT_SOURCE_PATH = ".rsp/source";
|
|
245
|
+
var SOURCE_INVOCATION = "mise exec -- node dist/cli.mjs";
|
|
246
|
+
function isExactVersion(value) {
|
|
247
|
+
return /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-z-][\da-z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-z-][\da-z-]*))*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?$/i.test(value);
|
|
248
|
+
}
|
|
249
|
+
function exactInvocation(version) {
|
|
250
|
+
if (!isExactVersion(version))
|
|
251
|
+
throw new Error(`Invalid exact RSP version: ${version}`);
|
|
252
|
+
return `npx -y @oevery/rsp@${version}`;
|
|
253
|
+
}
|
|
254
|
+
async function readProjectVersion(projectRoot = ".") {
|
|
255
|
+
const directory = inspectManagedDirectory(join(projectRoot, RSP_DIR), "RSP root", { allowMissing: true });
|
|
256
|
+
if (directory.issue)
|
|
257
|
+
throw directory.issue;
|
|
258
|
+
if (!directory.exists)
|
|
259
|
+
return null;
|
|
260
|
+
const path = join(projectRoot, PROJECT_VERSION_PATH);
|
|
261
|
+
const inspection = inspectManagedFile(path, "project CLI version", { allowMissing: true });
|
|
262
|
+
if (inspection.issue)
|
|
263
|
+
throw inspection.issue;
|
|
264
|
+
if (!inspection.exists)
|
|
265
|
+
return null;
|
|
266
|
+
const version = (await readFile(path, "utf8")).trim();
|
|
267
|
+
if (!isExactVersion(version))
|
|
268
|
+
throw new Error(`${PROJECT_VERSION_PATH} must contain one exact package version, not a tag or range`);
|
|
269
|
+
return version;
|
|
270
|
+
}
|
|
271
|
+
async function readProjectRuntime(projectRoot = ".") {
|
|
272
|
+
const version = await readProjectVersion(projectRoot);
|
|
273
|
+
const source = inspectManagedFile(join(projectRoot, PROJECT_SOURCE_PATH), "project source selection", { allowMissing: true });
|
|
274
|
+
if (source.issue)
|
|
275
|
+
throw source.issue;
|
|
276
|
+
if (!source.exists)
|
|
277
|
+
return { mode: "package", version };
|
|
278
|
+
if (version !== null)
|
|
279
|
+
throw new Error(`${PROJECT_SOURCE_PATH} and ${PROJECT_VERSION_PATH} are mutually exclusive; explicitly select one runtime.`);
|
|
280
|
+
if ((await readFile(join(projectRoot, PROJECT_SOURCE_PATH), "utf8")).trim() !== ".")
|
|
281
|
+
throw new Error(`${PROJECT_SOURCE_PATH} must contain . to select this RSP source checkout.`);
|
|
282
|
+
if (await realpath2(projectRoot) !== await realpath2(PKG_ROOT))
|
|
283
|
+
throw new Error(`Source mode requires this checkout's local CLI. Build here, then use ${SOURCE_INVOCATION} <command>; a registry package or another checkout cannot substitute.`);
|
|
284
|
+
const sourceDirectory = inspectManagedDirectory(join(projectRoot, "src"), "RSP source directory");
|
|
285
|
+
const sourceEntry = inspectManagedFile(join(projectRoot, "src/cli.ts"), "RSP source entry");
|
|
286
|
+
if (sourceDirectory.issue || sourceEntry.issue)
|
|
287
|
+
throw sourceDirectory.issue ?? sourceEntry.issue;
|
|
288
|
+
return { mode: "source" };
|
|
289
|
+
}
|
|
290
|
+
async function selectProjectRuntime(operation = "ordinary") {
|
|
291
|
+
const version = await getVersion();
|
|
292
|
+
exactInvocation(version);
|
|
293
|
+
const selected = await readProjectRuntime();
|
|
294
|
+
if (selected.mode === "source")
|
|
295
|
+
return { mode: "source", version };
|
|
296
|
+
if (selected.version && selected.version !== version && operation !== "update") {
|
|
297
|
+
throw new Error(`Project pins RSP ${selected.version}; running CLI is ${version}. Use ${exactInvocation(selected.version)} <command>. To migrate deliberately, inspect the target version and run ${exactInvocation(version)} update.`);
|
|
298
|
+
}
|
|
299
|
+
if (selected.version && operation === "update" && compareVersions(version, selected.version) < 0)
|
|
300
|
+
throw new Error(`Downgrading RSP from ${selected.version} to ${version} is unsupported. Use ${exactInvocation(selected.version)} <command>.`);
|
|
301
|
+
return { mode: "package", version };
|
|
302
|
+
}
|
|
303
|
+
function compareVersions(left, right) {
|
|
304
|
+
const parts = (value) => {
|
|
305
|
+
const [core, ...pre] = value.split("+", 1)[0].split("-");
|
|
306
|
+
return { core: core.split(".").map(BigInt), pre: pre.length ? pre.join("-").split(".") : [] };
|
|
307
|
+
};
|
|
308
|
+
const a = parts(left);
|
|
309
|
+
const b = parts(right);
|
|
310
|
+
for (let i = 0; i < 3; i++) {
|
|
311
|
+
if (a.core[i] !== b.core[i])
|
|
312
|
+
return a.core[i] > b.core[i] ? 1 : -1;
|
|
313
|
+
}
|
|
314
|
+
if (!a.pre.length || !b.pre.length)
|
|
315
|
+
return Number(!a.pre.length) - Number(!b.pre.length);
|
|
316
|
+
for (let i = 0; i < Math.max(a.pre.length, b.pre.length); i++) {
|
|
317
|
+
const x = a.pre[i];
|
|
318
|
+
const y = b.pre[i];
|
|
319
|
+
if (x === y)
|
|
320
|
+
continue;
|
|
321
|
+
if (x === void 0 || y === void 0)
|
|
322
|
+
return x === void 0 ? -1 : 1;
|
|
323
|
+
const nx = /^\d+$/.test(x);
|
|
324
|
+
const ny = /^\d+$/.test(y);
|
|
325
|
+
if (nx && ny)
|
|
326
|
+
return BigInt(x) > BigInt(y) ? 1 : -1;
|
|
327
|
+
if (nx !== ny)
|
|
328
|
+
return nx ? -1 : 1;
|
|
329
|
+
return x > y ? 1 : -1;
|
|
330
|
+
}
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
333
|
+
async function guardProjectVersion(rawArgs) {
|
|
334
|
+
if (rawArgs.some((arg) => ["--help", "-h"].includes(arg)) || rawArgs.length === 1 && ["--version", "-v"].includes(rawArgs[0]))
|
|
335
|
+
return;
|
|
336
|
+
if (["doctor", "config", "update"].includes(rawArgs[0] ?? ""))
|
|
337
|
+
return;
|
|
338
|
+
await selectProjectRuntime();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export {
|
|
342
|
+
selectArchitecture,
|
|
343
|
+
ARCHITECTURE_FILE,
|
|
344
|
+
MAX_CONTENT_BYTES,
|
|
345
|
+
digest,
|
|
346
|
+
projectPath,
|
|
347
|
+
readProjectFile,
|
|
348
|
+
documentHeadings,
|
|
349
|
+
queryArchitecture,
|
|
350
|
+
isWithin,
|
|
351
|
+
PROJECT_VERSION_PATH,
|
|
352
|
+
SOURCE_INVOCATION,
|
|
353
|
+
isExactVersion,
|
|
354
|
+
exactInvocation,
|
|
355
|
+
readProjectVersion,
|
|
356
|
+
readProjectRuntime,
|
|
357
|
+
selectProjectRuntime,
|
|
358
|
+
compareVersions,
|
|
359
|
+
guardProjectVersion
|
|
360
|
+
};
|